ron/
options.rs

1//! Roundtrip serde Options module.
2
3use alloc::string::String;
4use core::fmt;
5
6use serde::{de, ser};
7use serde_derive::{Deserialize, Serialize};
8
9use crate::{
10    de::Deserializer,
11    error::{Result, SpannedResult},
12    extensions::Extensions,
13    ser::{PrettyConfig, Serializer},
14};
15
16#[cfg(feature = "std")]
17use {
18    crate::error::{Position, Span, SpannedError},
19    alloc::vec::Vec,
20    std::io,
21};
22
23/// Roundtrip serde options.
24///
25/// # Examples
26///
27/// ```
28/// use ron::{Options, extensions::Extensions};
29///
30/// let ron = Options::default()
31///     .with_default_extension(Extensions::IMPLICIT_SOME);
32///
33/// let de: Option<i32> = ron.from_str("42").unwrap();
34/// let ser = ron.to_string(&de).unwrap();
35///
36/// assert_eq!(ser, "42");
37/// ```
38#[derive(Clone, Debug, Serialize, Deserialize)] // GRCOV_EXCL_LINE
39#[serde(default)]
40#[non_exhaustive]
41pub struct Options {
42    /// Extensions that are enabled by default during serialization and
43    ///  deserialization.
44    /// During serialization, these extensions do NOT have to be explicitly
45    ///  enabled in the parsed RON.
46    /// During deserialization, these extensions are used, but their explicit
47    ///  activation is NOT included in the output RON.
48    /// No extensions are enabled by default.
49    pub default_extensions: Extensions,
50    /// Default recursion limit that is checked during serialization and
51    ///  deserialization.
52    /// If set to `None`, infinite recursion is allowed and stack overflow
53    ///  errors can crash the serialization or deserialization process.
54    /// Defaults to `Some(128)`, i.e. 128 recursive calls are allowed.
55    pub recursion_limit: Option<usize>,
56}
57
58impl Default for Options {
59    fn default() -> Self {
60        Self {
61            default_extensions: Extensions::empty(),
62            recursion_limit: Some(128),
63        }
64    }
65}
66
67impl Options {
68    #[must_use]
69    /// Enable `default_extension` by default during serialization and deserialization.
70    pub fn with_default_extension(mut self, default_extension: Extensions) -> Self {
71        self.default_extensions |= default_extension;
72        self
73    }
74
75    #[must_use]
76    /// Do NOT enable `default_extension` by default during serialization and deserialization.
77    pub fn without_default_extension(mut self, default_extension: Extensions) -> Self {
78        self.default_extensions &= !default_extension;
79        self
80    }
81
82    #[must_use]
83    /// Set a maximum recursion limit during serialization and deserialization.
84    pub fn with_recursion_limit(mut self, recursion_limit: usize) -> Self {
85        self.recursion_limit = Some(recursion_limit);
86        self
87    }
88
89    #[must_use]
90    /// Disable the recursion limit during serialization and deserialization.
91    ///
92    /// If you expect to handle highly recursive datastructures, consider wrapping
93    /// `ron` with [`serde_stacker`](https://docs.rs/serde_stacker/latest/serde_stacker/).
94    pub fn without_recursion_limit(mut self) -> Self {
95        self.recursion_limit = None;
96        self
97    }
98}
99
100impl Options {
101    /// A convenience function for building a deserializer
102    /// and deserializing a value of type `T` from a reader.
103    #[cfg(feature = "std")]
104    pub fn from_reader<R, T>(&self, rdr: R) -> SpannedResult<T>
105    where
106        R: io::Read,
107        T: de::DeserializeOwned,
108    {
109        self.from_reader_seed(rdr, core::marker::PhantomData)
110    }
111
112    /// A convenience function for building a deserializer
113    /// and deserializing a value of type `T` from a string.
114    pub fn from_str<'a, T>(&self, s: &'a str) -> SpannedResult<T>
115    where
116        T: de::Deserialize<'a>,
117    {
118        self.from_str_seed(s, core::marker::PhantomData)
119    }
120
121    /// A convenience function for building a deserializer
122    /// and deserializing a value of type `T` from bytes.
123    pub fn from_bytes<'a, T>(&self, s: &'a [u8]) -> SpannedResult<T>
124    where
125        T: de::Deserialize<'a>,
126    {
127        self.from_bytes_seed(s, core::marker::PhantomData)
128    }
129
130    /// A convenience function for building a deserializer
131    /// and deserializing a value of type `T` from a reader
132    /// and a seed.
133    // FIXME: panic is not actually possible, remove once utf8_chunks is stabilized
134    #[allow(clippy::missing_panics_doc)]
135    #[cfg(feature = "std")]
136    pub fn from_reader_seed<R, S, T>(&self, mut rdr: R, seed: S) -> SpannedResult<T>
137    where
138        R: io::Read,
139        S: for<'a> de::DeserializeSeed<'a, Value = T>,
140    {
141        let mut bytes = Vec::new();
142
143        let io_err = if let Err(err) = rdr.read_to_end(&mut bytes) {
144            err
145        } else {
146            return self.from_bytes_seed(&bytes, seed);
147        };
148
149        // Try to compute a good error position for the I/O error
150        // FIXME: use [`utf8_chunks`](https://github.com/rust-lang/rust/issues/99543) once stabilised
151        #[allow(clippy::expect_used)]
152        let valid_input = match core::str::from_utf8(&bytes) {
153            Ok(valid_input) => valid_input,
154            Err(err) => core::str::from_utf8(&bytes[..err.valid_up_to()])
155                .expect("source is valid up to error"),
156        };
157
158        Err(SpannedError {
159            code: io_err.into(),
160            span: Span {
161                start: Position { line: 1, col: 1 },
162                end: Position::from_src_end(valid_input),
163            },
164        })
165    }
166
167    /// A convenience function for building a deserializer
168    /// and deserializing a value of type `T` from a string
169    /// and a seed.
170    pub fn from_str_seed<'a, S, T>(&self, s: &'a str, seed: S) -> SpannedResult<T>
171    where
172        S: de::DeserializeSeed<'a, Value = T>,
173    {
174        let mut deserializer = Deserializer::from_str_with_options(s, self)?;
175
176        let value = seed
177            .deserialize(&mut deserializer)
178            .map_err(|e| deserializer.span_error(e))?;
179
180        deserializer.end().map_err(|e| deserializer.span_error(e))?;
181
182        Ok(value)
183    }
184
185    /// A convenience function for building a deserializer
186    /// and deserializing a value of type `T` from bytes
187    /// and a seed.
188    pub fn from_bytes_seed<'a, S, T>(&self, s: &'a [u8], seed: S) -> SpannedResult<T>
189    where
190        S: de::DeserializeSeed<'a, Value = T>,
191    {
192        let mut deserializer = Deserializer::from_bytes_with_options(s, self)?;
193
194        let value = seed
195            .deserialize(&mut deserializer)
196            .map_err(|e| deserializer.span_error(e))?;
197
198        deserializer.end().map_err(|e| deserializer.span_error(e))?;
199
200        Ok(value)
201    }
202
203    /// Serializes `value` into `writer`.
204    ///
205    /// This function does not generate any newlines or nice formatting;
206    /// if you want that, you can use
207    /// [`to_writer_pretty`][Self::to_writer_pretty] instead.
208    pub fn to_writer<W, T>(&self, writer: W, value: &T) -> Result<()>
209    where
210        W: fmt::Write,
211        T: ?Sized + ser::Serialize,
212    {
213        let mut s = Serializer::with_options(writer, None, self)?;
214        value.serialize(&mut s)
215    }
216
217    /// Serializes `value` into `writer` in a pretty way.
218    pub fn to_writer_pretty<W, T>(&self, writer: W, value: &T, config: PrettyConfig) -> Result<()>
219    where
220        W: fmt::Write,
221        T: ?Sized + ser::Serialize,
222    {
223        let mut s = Serializer::with_options(writer, Some(config), self)?;
224        value.serialize(&mut s)
225    }
226
227    /// Serializes `value` into `writer`.
228    ///
229    /// This function does not generate any newlines or nice formatting;
230    /// if you want that, you can use
231    /// [`to_io_writer_pretty`][Self::to_io_writer_pretty] instead.
232    #[cfg(feature = "std")]
233    pub fn to_io_writer<W, T>(&self, writer: W, value: &T) -> Result<()>
234    where
235        W: io::Write,
236        T: ?Sized + ser::Serialize,
237    {
238        let mut adapter = Adapter {
239            writer,
240            error: Ok(()),
241        };
242        let result = self.to_writer(&mut adapter, value);
243        adapter.error?;
244        result
245    }
246
247    /// Serializes `value` into `writer` in a pretty way.
248    #[cfg(feature = "std")]
249    pub fn to_io_writer_pretty<W, T>(
250        &self,
251        writer: W,
252        value: &T,
253        config: PrettyConfig,
254    ) -> Result<()>
255    where
256        W: io::Write,
257        T: ?Sized + ser::Serialize,
258    {
259        let mut adapter = Adapter {
260            writer,
261            error: Ok(()),
262        };
263        let result = self.to_writer_pretty(&mut adapter, value, config);
264        adapter.error?;
265        result
266    }
267
268    /// Serializes `value` and returns it as string.
269    ///
270    /// This function does not generate any newlines or nice formatting;
271    /// if you want that, you can use
272    /// [`to_string_pretty`][Self::to_string_pretty] instead.
273    pub fn to_string<T>(&self, value: &T) -> Result<String>
274    where
275        T: ?Sized + ser::Serialize,
276    {
277        let mut output = String::new();
278        let mut s = Serializer::with_options(&mut output, None, self)?;
279        value.serialize(&mut s)?;
280        Ok(output)
281    }
282
283    /// Serializes `value` in the recommended RON layout in a pretty way.
284    pub fn to_string_pretty<T>(&self, value: &T, config: PrettyConfig) -> Result<String>
285    where
286        T: ?Sized + ser::Serialize,
287    {
288        let mut output = String::new();
289        let mut s = Serializer::with_options(&mut output, Some(config), self)?;
290        value.serialize(&mut s)?;
291        Ok(output)
292    }
293}
294
295// Adapter from io::Write to fmt::Write that keeps the error
296#[cfg(feature = "std")]
297struct Adapter<W: io::Write> {
298    writer: W,
299    error: io::Result<()>,
300}
301
302#[cfg(feature = "std")]
303impl<T: io::Write> fmt::Write for Adapter<T> {
304    fn write_str(&mut self, s: &str) -> fmt::Result {
305        match self.writer.write_all(s.as_bytes()) {
306            Ok(()) => Ok(()),
307            Err(e) => {
308                self.error = Err(e);
309                Err(fmt::Error)
310            }
311        }
312    }
313}