1
// Inspired by David Tolnay's serde-rs
2
// https://github.com/serde-rs/json/blob/master/src/raw.rs
3
// Licensed under either of Apache License, Version 2.0 or MIT license at your option.
4

            
5
use alloc::{borrow::ToOwned, boxed::Box, format, string::String};
6
use core::{fmt, ops::Range};
7

            
8
use serde::{de, ser, Deserialize, Serialize};
9

            
10
use crate::{
11
    error::{Error, SpannedResult},
12
    options::Options,
13
};
14

            
15
// NOTE: Keep synchronised with fuzz/arbitrary::typed_data::RAW_VALUE_TOKEN
16
pub(crate) const RAW_VALUE_TOKEN: &str = "$ron::private::RawValue";
17

            
18
#[allow(clippy::module_name_repetitions)]
19
#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
20
#[repr(transparent)]
21
pub struct RawValue {
22
    ron: str,
23
}
24

            
25
#[allow(unsafe_code)]
26
impl RawValue {
27
27900
    fn from_borrowed_str(ron: &str) -> &Self {
28
        // Safety: RawValue is a transparent newtype around str
29
27900
        unsafe { &*(ron as *const str as *const RawValue) }
30
27900
    }
31

            
32
23870
    fn from_boxed_str(ron: Box<str>) -> Box<Self> {
33
        // Safety: RawValue is a transparent newtype around str
34
23870
        unsafe { core::mem::transmute::<Box<str>, Box<RawValue>>(ron) }
35
23870
    }
36

            
37
4650
    fn into_boxed_str(raw_value: Box<Self>) -> Box<str> {
38
        // Safety: RawValue is a transparent newtype around str
39
4650
        unsafe { core::mem::transmute::<Box<RawValue>, Box<str>>(raw_value) }
40
4650
    }
41

            
42
    #[allow(clippy::expect_used)]
43
8370
    fn trim_range(ron: &str) -> Range<usize> {
44
8370
        fn trim_range_inner(ron: &str) -> Result<Range<usize>, Error> {
45
8370
            let mut deserializer = crate::Deserializer::from_str(ron).map_err(Error::from)?;
46

            
47
8370
            deserializer.parser.skip_ws()?;
48
8370
            let start_offset = ron.len() - deserializer.parser.src().len();
49

            
50
8370
            let _ = serde::de::IgnoredAny::deserialize(&mut deserializer)?;
51

            
52
8370
            deserializer.parser.skip_ws()?;
53
8370
            let end_offset = deserializer.parser.pre_ws_src().len();
54

            
55
8370
            Ok(start_offset..(ron.len() - end_offset))
56
8370
        }
57

            
58
8370
        trim_range_inner(ron).expect("RawValue must contain valid ron")
59
8370
    }
60
}
61

            
62
impl Clone for Box<RawValue> {
63
3720
    fn clone(&self) -> Self {
64
3720
        (**self).to_owned()
65
3720
    }
66
}
67

            
68
impl ToOwned for RawValue {
69
    type Owned = Box<RawValue>;
70

            
71
16120
    fn to_owned(&self) -> Self::Owned {
72
16120
        RawValue::from_boxed_str(self.ron.to_owned().into_boxed_str())
73
16120
    }
74
}
75

            
76
impl fmt::Debug for RawValue {
77
310
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
78
310
        f.debug_tuple("RawValue")
79
310
            .field(&format_args!("{}", &self.ron))
80
310
            .finish()
81
310
    }
82
}
83

            
84
impl fmt::Display for RawValue {
85
310
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
86
310
        f.write_str(&self.ron)
87
310
    }
88
}
89

            
90
impl RawValue {
91
    /// Get the inner raw RON string, which is guaranteed to contain valid RON.
92
    #[must_use]
93
17360
    pub fn get_ron(&self) -> &str {
94
17360
        &self.ron
95
17360
    }
96

            
97
    /// Helper function to validate a RON string and turn it into a
98
    /// [`RawValue`].
99
29760
    pub fn from_ron(ron: &str) -> SpannedResult<&Self> {
100
29760
        let mut deserializer = crate::Deserializer::from_str(ron)?;
101

            
102
        // raw values can be used everywhere but extensions cannot
103
29760
        if !deserializer.extensions().is_empty() {
104
930
            return Err(deserializer.span_error(Error::Message(String::from(
105
930
                "ron::value::RawValue cannot enable extensions",
106
930
            ))));
107
28830
        }
108

            
109
        // neither can global attributes like `#![type = ".."]`
110
28830
        if deserializer.parser.global_attributes {
111
1550
            return Err(deserializer.span_error(Error::Message(String::from(
112
1550
                "ron::value::RawValue cannot contain attributes",
113
1550
            ))));
114
27280
        }
115

            
116
27280
        let _ = de::Deserializer::deserialize_newtype_struct(
117
27280
            &mut deserializer,
118
            RAW_VALUE_TOKEN,
119
27280
            de::IgnoredAny,
120
        )
121
27280
        .map_err(|e| deserializer.span_error(e))?;
122

            
123
24180
        deserializer.end().map_err(|e| deserializer.span_error(e))?;
124

            
125
23870
        Ok(Self::from_borrowed_str(ron))
126
29760
    }
127

            
128
    /// Helper function to validate a RON string and turn it into a
129
    /// [`RawValue`].
130
4340
    pub fn from_boxed_ron(ron: Box<str>) -> SpannedResult<Box<Self>> {
131
4340
        match Self::from_ron(&ron) {
132
2790
            Ok(_) => Ok(Self::from_boxed_str(ron)),
133
1550
            Err(err) => Err(err),
134
        }
135
4340
    }
136

            
137
    /// Helper function to deserialize the inner RON string into `T`.
138
8
    pub fn into_rust<'de, T: Deserialize<'de>>(&'de self) -> SpannedResult<T> {
139
8
        Options::default().from_str(&self.ron)
140
8
    }
141

            
142
    /// Helper function to serialize `value` into a RON string.
143
8
    pub fn from_rust<T: Serialize>(value: &T) -> Result<Box<Self>, Error> {
144
8
        let ron = Options::default().to_string(value)?;
145

            
146
8
        Ok(RawValue::from_boxed_str(ron.into_boxed_str()))
147
8
    }
148
}
149

            
150
impl RawValue {
151
    #[must_use]
152
    /// Trims any leadning and trailing whitespace off the raw RON string,
153
    /// including whitespace characters and comments.
154
4030
    pub fn trim(&self) -> &Self {
155
4030
        Self::from_borrowed_str(&self.ron[RawValue::trim_range(&self.ron)])
156
4030
    }
157

            
158
    #[must_use]
159
    /// Trims any leadning and trailing whitespace off the boxed raw RON string,
160
    /// including whitespace characters and comments.
161
4340
    pub fn trim_boxed(self: Box<Self>) -> Box<Self> {
162
4340
        let trim_range = RawValue::trim_range(&self.ron);
163
4340
        let mut boxed_ron = RawValue::into_boxed_str(self).into_string();
164
4340
        boxed_ron.truncate(trim_range.end);
165
4340
        boxed_ron.drain(..trim_range.start);
166
4340
        RawValue::from_boxed_str(boxed_ron.into_boxed_str())
167
4340
    }
168
}
169

            
170
impl From<Box<RawValue>> for Box<str> {
171
310
    fn from(raw_value: Box<RawValue>) -> Self {
172
310
        RawValue::into_boxed_str(raw_value)
173
310
    }
174
}
175

            
176
impl Serialize for RawValue {
177
120
    fn serialize<S: ser::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
178
120
        serializer.serialize_newtype_struct(RAW_VALUE_TOKEN, &self.ron)
179
120
    }
180
}
181

            
182
impl<'de: 'a, 'a> Deserialize<'de> for &'a RawValue {
183
72
    fn deserialize<D: de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
184
        struct ReferenceVisitor;
185

            
186
        impl<'de> de::Visitor<'de> for ReferenceVisitor {
187
            type Value = &'de RawValue;
188

            
189
620
            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
190
                // This error message only shows up with foreign Deserializers
191
620
                write!(formatter, "any valid borrowed RON-value-string")
192
620
            }
193

            
194
52
            fn visit_borrowed_str<E: de::Error>(self, ron: &'de str) -> Result<Self::Value, E> {
195
52
                match RawValue::from_ron(ron) {
196
44
                    Ok(raw_value) => Ok(raw_value),
197
8
                    Err(err) => Err(de::Error::custom(format!("invalid RON value at {}", err))),
198
                }
199
52
            }
200

            
201
12
            fn visit_newtype_struct<D: de::Deserializer<'de>>(
202
12
                self,
203
12
                deserializer: D,
204
12
            ) -> Result<Self::Value, D::Error> {
205
12
                deserializer.deserialize_str(self)
206
12
            }
207
        }
208

            
209
72
        deserializer.deserialize_newtype_struct(RAW_VALUE_TOKEN, ReferenceVisitor)
210
72
    }
211
}
212

            
213
impl<'de> Deserialize<'de> for Box<RawValue> {
214
192
    fn deserialize<D: de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
215
        struct BoxedVisitor;
216

            
217
        impl<'de> de::Visitor<'de> for BoxedVisitor {
218
            type Value = Box<RawValue>;
219

            
220
1860
            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
221
                // This error message only shows up with foreign Deserializers
222
1860
                write!(formatter, "any valid RON-value-string")
223
1860
            }
224

            
225
160
            fn visit_str<E: de::Error>(self, ron: &str) -> Result<Self::Value, E> {
226
160
                match RawValue::from_ron(ron) {
227
140
                    Ok(raw_value) => Ok(raw_value.to_owned()),
228
20
                    Err(err) => Err(de::Error::custom(format!("invalid RON value at {}", err))),
229
                }
230
160
            }
231

            
232
8
            fn visit_string<E: de::Error>(self, ron: String) -> Result<Self::Value, E> {
233
8
                match RawValue::from_boxed_ron(ron.into_boxed_str()) {
234
4
                    Ok(raw_value) => Ok(raw_value),
235
4
                    Err(err) => Err(de::Error::custom(format!("invalid RON value at {}", err))),
236
                }
237
8
            }
238

            
239
48
            fn visit_newtype_struct<D: de::Deserializer<'de>>(
240
48
                self,
241
48
                deserializer: D,
242
48
            ) -> Result<Self::Value, D::Error> {
243
48
                deserializer.deserialize_string(self)
244
48
            }
245
        }
246

            
247
192
        deserializer.deserialize_newtype_struct(RAW_VALUE_TOKEN, BoxedVisitor)
248
192
    }
249
}