ron/value/
raw.rs

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
5use std::{fmt, ops::Range};
6
7use serde::{de, ser, Deserialize, Serialize};
8
9use crate::{
10    error::{Error, SpannedResult},
11    options::Options,
12};
13
14// NOTE: Keep synchronised with fuzz/arbitrary::typed_data::RAW_VALUE_TOKEN
15pub(crate) const RAW_VALUE_TOKEN: &str = "$ron::private::RawValue";
16
17#[allow(clippy::module_name_repetitions)]
18#[derive(PartialEq, Eq, PartialOrd, Ord, Hash)]
19#[repr(transparent)]
20pub struct RawValue {
21    ron: str,
22}
23
24#[allow(unsafe_code)]
25impl RawValue {
26    fn from_borrowed_str(ron: &str) -> &Self {
27        // Safety: RawValue is a transparent newtype around str
28        unsafe { &*(ron as *const str as *const RawValue) }
29    }
30
31    fn from_boxed_str(ron: Box<str>) -> Box<Self> {
32        // Safety: RawValue is a transparent newtype around str
33        unsafe { std::mem::transmute::<Box<str>, Box<RawValue>>(ron) }
34    }
35
36    fn into_boxed_str(raw_value: Box<Self>) -> Box<str> {
37        // Safety: RawValue is a transparent newtype around str
38        unsafe { std::mem::transmute::<Box<RawValue>, Box<str>>(raw_value) }
39    }
40
41    #[allow(clippy::expect_used)]
42    fn trim_range(ron: &str) -> Range<usize> {
43        fn trim_range_inner(ron: &str) -> Result<Range<usize>, Error> {
44            let mut deserializer = crate::Deserializer::from_str(ron).map_err(Error::from)?;
45
46            deserializer.parser.skip_ws()?;
47            let start_offset = ron.len() - deserializer.parser.src().len();
48
49            let _ = serde::de::IgnoredAny::deserialize(&mut deserializer)?;
50
51            deserializer.parser.skip_ws()?;
52            let end_offset = deserializer.parser.pre_ws_src().len();
53
54            Ok(start_offset..(ron.len() - end_offset))
55        }
56
57        trim_range_inner(ron).expect("RawValue must contain valid ron")
58    }
59}
60
61impl Clone for Box<RawValue> {
62    fn clone(&self) -> Self {
63        (**self).to_owned()
64    }
65}
66
67impl ToOwned for RawValue {
68    type Owned = Box<RawValue>;
69
70    fn to_owned(&self) -> Self::Owned {
71        RawValue::from_boxed_str(self.ron.to_owned().into_boxed_str())
72    }
73}
74
75impl fmt::Debug for RawValue {
76    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
77        f.debug_tuple("RawValue")
78            .field(&format_args!("{}", &self.ron))
79            .finish()
80    }
81}
82
83impl fmt::Display for RawValue {
84    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
85        f.write_str(&self.ron)
86    }
87}
88
89impl RawValue {
90    /// Get the inner raw RON string, which is guaranteed to contain valid RON.
91    #[must_use]
92    pub fn get_ron(&self) -> &str {
93        &self.ron
94    }
95
96    /// Helper function to validate a RON string and turn it into a
97    /// [`RawValue`].
98    pub fn from_ron(ron: &str) -> SpannedResult<&Self> {
99        let mut deserializer = crate::Deserializer::from_str(ron)?;
100
101        // raw values can be used everywhere but extensions cannot
102        if !deserializer.extensions().is_empty() {
103            return Err(deserializer.span_error(Error::Message(String::from(
104                "ron::value::RawValue cannot enable extensions",
105            ))));
106        }
107
108        let _ = <&Self>::deserialize(&mut deserializer).map_err(|e| deserializer.span_error(e))?;
109
110        deserializer.end().map_err(|e| deserializer.span_error(e))?;
111
112        Ok(Self::from_borrowed_str(ron))
113    }
114
115    /// Helper function to validate a RON string and turn it into a
116    /// [`RawValue`].
117    pub fn from_boxed_ron(ron: Box<str>) -> SpannedResult<Box<Self>> {
118        match Self::from_ron(&ron) {
119            Ok(_) => Ok(Self::from_boxed_str(ron)),
120            Err(err) => Err(err),
121        }
122    }
123
124    /// Helper function to deserialize the inner RON string into `T`.
125    pub fn into_rust<'de, T: Deserialize<'de>>(&'de self) -> SpannedResult<T> {
126        Options::default().from_str(&self.ron)
127    }
128
129    /// Helper function to serialize `value` into a RON string.
130    pub fn from_rust<T: Serialize>(value: &T) -> Result<Box<Self>, Error> {
131        let ron = Options::default().to_string(value)?;
132
133        Ok(RawValue::from_boxed_str(ron.into_boxed_str()))
134    }
135}
136
137impl RawValue {
138    #[must_use]
139    /// Trims any leadning and trailing whitespace off the raw RON string,
140    /// including whitespace characters and comments.
141    pub fn trim(&self) -> &Self {
142        Self::from_borrowed_str(&self.ron[RawValue::trim_range(&self.ron)])
143    }
144
145    #[must_use]
146    #[allow(unsafe_code)]
147    /// Trims any leadning and trailing whitespace off the boxed raw RON string,
148    /// including whitespace characters and comments.
149    pub fn trim_boxed(self: Box<Self>) -> Box<Self> {
150        let trim_range = RawValue::trim_range(&self.ron);
151        let mut boxed_ron = RawValue::into_boxed_str(self).into_string();
152        // SAFETY: ron[trim_range] is a valid str, so draining everything
153        //         before and after leaves a valid str
154        unsafe {
155            boxed_ron.as_mut_vec().drain(trim_range.end..);
156            boxed_ron.as_mut_vec().drain(0..trim_range.start);
157        }
158        RawValue::from_boxed_str(boxed_ron.into_boxed_str())
159    }
160}
161
162impl From<Box<RawValue>> for Box<str> {
163    fn from(raw_value: Box<RawValue>) -> Self {
164        RawValue::into_boxed_str(raw_value)
165    }
166}
167
168impl Serialize for RawValue {
169    fn serialize<S: ser::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
170        serializer.serialize_newtype_struct(RAW_VALUE_TOKEN, &self.ron)
171    }
172}
173
174impl<'de: 'a, 'a> Deserialize<'de> for &'a RawValue {
175    fn deserialize<D: de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
176        struct ReferenceVisitor;
177
178        impl<'de> de::Visitor<'de> for ReferenceVisitor {
179            type Value = &'de RawValue;
180
181            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
182                // This error message only shows up with foreign Deserializers
183                write!(formatter, "any valid borrowed RON-value-string")
184            }
185
186            fn visit_borrowed_str<E: de::Error>(self, ron: &'de str) -> Result<Self::Value, E> {
187                match Options::default().from_str::<de::IgnoredAny>(ron) {
188                    Ok(_) => Ok(RawValue::from_borrowed_str(ron)),
189                    Err(err) => Err(de::Error::custom(format!(
190                        "invalid RON value at {}: {}",
191                        err.position, err.code
192                    ))),
193                }
194            }
195
196            fn visit_newtype_struct<D: de::Deserializer<'de>>(
197                self,
198                deserializer: D,
199            ) -> Result<Self::Value, D::Error> {
200                deserializer.deserialize_str(self)
201            }
202        }
203
204        deserializer.deserialize_newtype_struct(RAW_VALUE_TOKEN, ReferenceVisitor)
205    }
206}
207
208impl<'de> Deserialize<'de> for Box<RawValue> {
209    fn deserialize<D: de::Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
210        struct BoxedVisitor;
211
212        impl<'de> de::Visitor<'de> for BoxedVisitor {
213            type Value = Box<RawValue>;
214
215            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
216                // This error message only shows up with foreign Deserializers
217                write!(formatter, "any valid RON-value-string")
218            }
219
220            fn visit_str<E: de::Error>(self, ron: &str) -> Result<Self::Value, E> {
221                match Options::default().from_str::<de::IgnoredAny>(ron) {
222                    Ok(_) => Ok(RawValue::from_boxed_str(ron.to_owned().into_boxed_str())),
223                    Err(err) => Err(de::Error::custom(format!(
224                        "invalid RON value at {}: {}",
225                        err.position, err.code
226                    ))),
227                }
228            }
229
230            fn visit_string<E: de::Error>(self, ron: String) -> Result<Self::Value, E> {
231                match Options::default().from_str::<de::IgnoredAny>(&ron) {
232                    Ok(_) => Ok(RawValue::from_boxed_str(ron.into_boxed_str())),
233                    Err(err) => Err(de::Error::custom(format!(
234                        "invalid RON value at {}: {}",
235                        err.position, err.code
236                    ))),
237                }
238            }
239
240            fn visit_newtype_struct<D: de::Deserializer<'de>>(
241                self,
242                deserializer: D,
243            ) -> Result<Self::Value, D::Error> {
244                deserializer.deserialize_string(self)
245            }
246        }
247
248        deserializer.deserialize_newtype_struct(RAW_VALUE_TOKEN, BoxedVisitor)
249    }
250}