ron/
options.rs

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