1
//! Roundtrip serde Options module.
2

            
3
use alloc::string::String;
4
use core::fmt;
5

            
6
use serde::{de, ser};
7
use serde_derive::{Deserialize, Serialize};
8

            
9
use crate::{
10
    de::Deserializer,
11
    error::{Result, SpannedResult},
12
    extensions::Extensions,
13
    ser::{PrettyConfig, Serializer},
14
};
15

            
16
#[cfg(feature = "std")]
17
use {
18
    crate::error::{Position, 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]
41
pub 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

            
58
impl Default for Options {
59
689725
    fn default() -> Self {
60
689725
        Self {
61
689725
            default_extensions: Extensions::empty(),
62
689725
            recursion_limit: Some(128),
63
689725
        }
64
689725
    }
65
}
66

            
67
impl Options {
68
    #[must_use]
69
    /// Enable `default_extension` by default during serialization and deserialization.
70
2780
    pub fn with_default_extension(mut self, default_extension: Extensions) -> Self {
71
2780
        self.default_extensions |= default_extension;
72
2780
        self
73
2780
    }
74

            
75
    #[must_use]
76
    /// Do NOT enable `default_extension` by default during serialization and deserialization.
77
1112
    pub fn without_default_extension(mut self, default_extension: Extensions) -> Self {
78
1112
        self.default_extensions &= !default_extension;
79
1112
        self
80
1112
    }
81

            
82
    #[must_use]
83
    /// Set a maximum recursion limit during serialization and deserialization.
84
16
    pub fn with_recursion_limit(mut self, recursion_limit: usize) -> Self {
85
16
        self.recursion_limit = Some(recursion_limit);
86
16
        self
87
16
    }
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
8
    pub fn without_recursion_limit(mut self) -> Self {
95
8
        self.recursion_limit = None;
96
8
        self
97
8
    }
98
}
99

            
100
impl 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
296
    pub fn from_reader<R, T>(&self, rdr: R) -> SpannedResult<T>
105
296
    where
106
296
        R: io::Read,
107
296
        T: de::DeserializeOwned,
108
296
    {
109
296
        self.from_reader_seed(rdr, core::marker::PhantomData)
110
296
    }
111

            
112
    /// A convenience function for building a deserializer
113
    /// and deserializing a value of type `T` from a string.
114
25864
    pub fn from_str<'a, T>(&self, s: &'a str) -> SpannedResult<T>
115
25864
    where
116
25864
        T: de::Deserialize<'a>,
117
25864
    {
118
25864
        self.from_str_seed(s, core::marker::PhantomData)
119
25864
    }
120

            
121
    /// A convenience function for building a deserializer
122
    /// and deserializing a value of type `T` from bytes.
123
312
    pub fn from_bytes<'a, T>(&self, s: &'a [u8]) -> SpannedResult<T>
124
312
    where
125
312
        T: de::Deserialize<'a>,
126
312
    {
127
312
        self.from_bytes_seed(s, core::marker::PhantomData)
128
312
    }
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
296
    pub fn from_reader_seed<R, S, T>(&self, mut rdr: R, seed: S) -> SpannedResult<T>
137
296
    where
138
296
        R: io::Read,
139
296
        S: for<'a> de::DeserializeSeed<'a, Value = T>,
140
296
    {
141
296
        let mut bytes = Vec::new();
142

            
143
296
        let io_err = if let Err(err) = rdr.read_to_end(&mut bytes) {
144
12
            err
145
        } else {
146
284
            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
12
        let valid_input = match core::str::from_utf8(&bytes) {
153
8
            Ok(valid_input) => valid_input,
154
4
            Err(err) => core::str::from_utf8(&bytes[..err.valid_up_to()])
155
4
                .expect("source is valid up to error"),
156
        };
157

            
158
12
        Err(SpannedError {
159
12
            code: io_err.into(),
160
12
            position: Position::from_src_end(valid_input),
161
12
        })
162
296
    }
163

            
164
    /// A convenience function for building a deserializer
165
    /// and deserializing a value of type `T` from a string
166
    /// and a seed.
167
25880
    pub fn from_str_seed<'a, S, T>(&self, s: &'a str, seed: S) -> SpannedResult<T>
168
25880
    where
169
25880
        S: de::DeserializeSeed<'a, Value = T>,
170
25880
    {
171
25880
        let mut deserializer = Deserializer::from_str_with_options(s, self)?;
172

            
173
25860
        let value = seed
174
25860
            .deserialize(&mut deserializer)
175
25860
            .map_err(|e| deserializer.span_error(e))?;
176

            
177
23508
        deserializer.end().map_err(|e| deserializer.span_error(e))?;
178

            
179
23432
        Ok(value)
180
25880
    }
181

            
182
    /// A convenience function for building a deserializer
183
    /// and deserializing a value of type `T` from bytes
184
    /// and a seed.
185
596
    pub fn from_bytes_seed<'a, S, T>(&self, s: &'a [u8], seed: S) -> SpannedResult<T>
186
596
    where
187
596
        S: de::DeserializeSeed<'a, Value = T>,
188
596
    {
189
596
        let mut deserializer = Deserializer::from_bytes_with_options(s, self)?;
190

            
191
564
        let value = seed
192
564
            .deserialize(&mut deserializer)
193
564
            .map_err(|e| deserializer.span_error(e))?;
194

            
195
352
        deserializer.end().map_err(|e| deserializer.span_error(e))?;
196

            
197
352
        Ok(value)
198
596
    }
199

            
200
    /// Serializes `value` into `writer`.
201
    ///
202
    /// This function does not generate any newlines or nice formatting;
203
    /// if you want that, you can use
204
    /// [`to_writer_pretty`][Self::to_writer_pretty] instead.
205
360
    pub fn to_writer<W, T>(&self, writer: W, value: &T) -> Result<()>
206
360
    where
207
360
        W: fmt::Write,
208
360
        T: ?Sized + ser::Serialize,
209
360
    {
210
360
        let mut s = Serializer::with_options(writer, None, self)?;
211
360
        value.serialize(&mut s)
212
360
    }
213

            
214
    /// Serializes `value` into `writer` in a pretty way.
215
360
    pub fn to_writer_pretty<W, T>(&self, writer: W, value: &T, config: PrettyConfig) -> Result<()>
216
360
    where
217
360
        W: fmt::Write,
218
360
        T: ?Sized + ser::Serialize,
219
360
    {
220
360
        let mut s = Serializer::with_options(writer, Some(config), self)?;
221
360
        value.serialize(&mut s)
222
360
    }
223

            
224
    /// Serializes `value` into `writer`.
225
    ///
226
    /// This function does not generate any newlines or nice formatting;
227
    /// if you want that, you can use
228
    /// [`to_io_writer_pretty`][Self::to_io_writer_pretty] instead.
229
    #[cfg(feature = "std")]
230
    pub fn to_io_writer<W, T>(&self, writer: W, value: &T) -> Result<()>
231
    where
232
        W: io::Write,
233
        T: ?Sized + ser::Serialize,
234
    {
235
        let mut adapter = Adapter {
236
            writer,
237
            error: Ok(()),
238
        };
239
        let result = self.to_writer(&mut adapter, value);
240
        adapter.error?;
241
        result
242
    }
243

            
244
    /// Serializes `value` into `writer` in a pretty way.
245
    #[cfg(feature = "std")]
246
    pub fn to_io_writer_pretty<W, T>(
247
        &self,
248
        writer: W,
249
        value: &T,
250
        config: PrettyConfig,
251
    ) -> Result<()>
252
    where
253
        W: io::Write,
254
        T: ?Sized + ser::Serialize,
255
    {
256
        let mut adapter = Adapter {
257
            writer,
258
            error: Ok(()),
259
        };
260
        let result = self.to_writer_pretty(&mut adapter, value, config);
261
        adapter.error?;
262
        result
263
    }
264

            
265
    /// Serializes `value` and returns it as string.
266
    ///
267
    /// This function does not generate any newlines or nice formatting;
268
    /// if you want that, you can use
269
    /// [`to_string_pretty`][Self::to_string_pretty] instead.
270
1692
    pub fn to_string<T>(&self, value: &T) -> Result<String>
271
1692
    where
272
1692
        T: ?Sized + ser::Serialize,
273
1692
    {
274
1692
        let mut output = String::new();
275
1692
        let mut s = Serializer::with_options(&mut output, None, self)?;
276
1692
        value.serialize(&mut s)?;
277
1568
        Ok(output)
278
1692
    }
279

            
280
    /// Serializes `value` in the recommended RON layout in a pretty way.
281
1396
    pub fn to_string_pretty<T>(&self, value: &T, config: PrettyConfig) -> Result<String>
282
1396
    where
283
1396
        T: ?Sized + ser::Serialize,
284
1396
    {
285
1396
        let mut output = String::new();
286
1396
        let mut s = Serializer::with_options(&mut output, Some(config), self)?;
287
1384
        value.serialize(&mut s)?;
288
1366
        Ok(output)
289
1396
    }
290
}
291

            
292
// Adapter from io::Write to fmt::Write that keeps the error
293
#[cfg(feature = "std")]
294
struct Adapter<W: io::Write> {
295
    writer: W,
296
    error: io::Result<()>,
297
}
298

            
299
#[cfg(feature = "std")]
300
impl<T: io::Write> fmt::Write for Adapter<T> {
301
    fn write_str(&mut self, s: &str) -> fmt::Result {
302
        match self.writer.write_all(s.as_bytes()) {
303
            Ok(()) => Ok(()),
304
            Err(e) => {
305
                self.error = Err(e);
306
                Err(fmt::Error)
307
            }
308
        }
309
    }
310
}