From 54320e9067409dafdea8cabbfeb2b5647a1b6317 Mon Sep 17 00:00:00 2001 From: Momo Langenstein Date: Fri, 3 Dec 2021 10:01:10 +0000 Subject: [PATCH] Documented RON roundtrip Options --- src/de/mod.rs | 31 ++++++++++-------- src/error.rs | 14 +++++++-- src/options.rs | 61 ++++++++++++++++++++++++----------- src/parse.rs | 15 +-------- src/ser/mod.rs | 82 ++++++++++++++---------------------------------- tests/options.rs | 4 +-- 6 files changed, 99 insertions(+), 108 deletions(-) diff --git a/src/de/mod.rs b/src/de/mod.rs index 339582983..c24235b39 100644 --- a/src/de/mod.rs +++ b/src/de/mod.rs @@ -1,6 +1,5 @@ /// Deserialization module. -pub use crate::error::{Error, ErrorCode, Result}; -pub use crate::parse::Position; +pub use crate::error::{Error, ErrorCode, Position, Result}; use serde::de::{self, DeserializeSeed, Deserializer as SerdeError, Visitor}; use std::{borrow::Cow, io, str}; @@ -31,20 +30,26 @@ impl<'de> Deserializer<'de> { // Cannot implement trait here since output is tied to input lifetime 'de. #[allow(clippy::should_implement_trait)] pub fn from_str(input: &'de str) -> Result { - Deserializer::from_bytes(input.as_bytes()) + Self::from_str_with_options(input, Options::default()) } pub fn from_bytes(input: &'de [u8]) -> Result { - Ok(Deserializer { + Self::from_bytes_with_options(input, Options::default()) + } + + pub fn from_str_with_options(input: &'de str, options: Options) -> Result { + Self::from_bytes_with_options(input.as_bytes(), options) + } + + pub fn from_bytes_with_options(input: &'de [u8], options: Options) -> Result { + let mut deserializer = Deserializer { bytes: Bytes::new(input)?, newtype_variant: false, - }) - } + }; + + deserializer.bytes.exts |= options.default_extensions; - #[must_use] - pub fn with_default_extensions(mut self, default_extensions: Extensions) -> Self { - self.bytes.exts |= default_extensions; - self + Ok(deserializer) } pub fn remainder(&self) -> Cow<'_, str> { @@ -59,7 +64,7 @@ where R: io::Read, T: de::DeserializeOwned, { - Options::build().from_reader(rdr) + Options::default().from_reader(rdr) } /// A convenience function for building a deserializer @@ -68,7 +73,7 @@ pub fn from_str<'a, T>(s: &'a str) -> Result where T: de::Deserialize<'a>, { - Options::build().from_str(s) + Options::default().from_str(s) } /// A convenience function for building a deserializer @@ -77,7 +82,7 @@ pub fn from_bytes<'a, T>(s: &'a [u8]) -> Result where T: de::Deserialize<'a>, { - Options::build().from_bytes(s) + Options::default().from_bytes(s) } impl<'de> Deserializer<'de> { diff --git a/src/error.rs b/src/error.rs index 2a5052159..f265f09b4 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,8 +1,6 @@ use serde::{de, ser}; use std::{error::Error as StdError, fmt, io, str::Utf8Error, string::FromUtf8Error}; -pub use crate::parse::Position; - /// This type represents all possible errors that can occur when /// serializing or deserializing RON data. #[derive(Clone, Debug, PartialEq)] @@ -113,6 +111,18 @@ impl fmt::Display for ErrorCode { } } +#[derive(Clone, Copy, Debug, PartialEq)] +pub struct Position { + pub line: usize, + pub col: usize, +} + +impl fmt::Display for Position { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}:{}", self.line, self.col) + } +} + impl de::Error for Error { fn custom(msg: T) -> Self { Error { diff --git a/src/options.rs b/src/options.rs index 49ba8b645..281a9fa4b 100644 --- a/src/options.rs +++ b/src/options.rs @@ -1,31 +1,60 @@ +//! Roundtrip serde Options module. + use std::io; -use serde::{de, ser}; +use serde::{de, ser, Deserialize, Serialize}; use crate::de::Deserializer; use crate::error::Result; use crate::extensions::Extensions; use crate::ser::{PrettyConfig, Serializer}; +/// Roundtrip serde options. +/// +/// # Examples +/// +/// ``` +/// use ron::{Options, extensions::Extensions}; +/// +/// let ron = Options::default() +/// .with_default_extension(Extensions::IMPLICIT_SOME); +/// +/// let de: Option = ron.from_str("42").unwrap(); +/// let ser = ron.to_string(&de).unwrap(); +/// +/// assert_eq!(ser, "42"); +/// ``` +#[derive(Clone, Debug, Serialize, Deserialize)] +#[serde(default)] pub struct Options { - default_extensions: Extensions, + /// Extensions that are enabled by default during serialization and + /// deserialization. + /// During serialization, these extensions do NOT have to be explicitly + /// enabled in the parsed RON. + /// During deserialization, these extensions are used, but their explicit + /// activation is NOT included in the output RON. + /// No extensions are enabled by default. + pub default_extensions: Extensions, } -impl Options { - #[must_use] - pub fn build() -> Self { +impl Default for Options { + fn default() -> Self { Self { default_extensions: Extensions::empty(), } } +} +impl Options { #[must_use] + /// Enable `default_extension` by default during serialization and deserialization. pub fn with_default_extension(mut self, default_extension: Extensions) -> Self { self.default_extensions |= default_extension; self } #[must_use] + /// Do NOT enable `default_extension` by default during serialization and deserialization. pub fn without_default_extension(mut self, default_extension: Extensions) -> Self { self.default_extensions &= !default_extension; self @@ -61,13 +90,13 @@ impl Options { where T: de::Deserialize<'a>, { - let mut deserializer = - Deserializer::from_bytes(s)?.with_default_extensions(self.default_extensions); - let t = T::deserialize(&mut deserializer)?; + let mut deserializer = Deserializer::from_bytes_with_options(s, self.clone())?; + + let value = T::deserialize(&mut deserializer)?; deserializer.end()?; - Ok(t) + Ok(value) } /// Serializes `value` into `writer` @@ -76,7 +105,7 @@ impl Options { W: io::Write, T: ?Sized + ser::Serialize, { - let mut s = Serializer::new_with_default_extensions(writer, None, self.default_extensions)?; + let mut s = Serializer::with_options(writer, None, self.clone())?; value.serialize(&mut s) } @@ -86,8 +115,7 @@ impl Options { W: io::Write, T: ?Sized + ser::Serialize, { - let mut s = - Serializer::new_with_default_extensions(writer, Some(config), self.default_extensions)?; + let mut s = Serializer::with_options(writer, Some(config), self.clone())?; value.serialize(&mut s) } @@ -100,8 +128,7 @@ impl Options { T: ?Sized + ser::Serialize, { let mut output = Vec::new(); - let mut s = - Serializer::new_with_default_extensions(&mut output, None, self.default_extensions)?; + let mut s = Serializer::with_options(&mut output, None, self.clone())?; value.serialize(&mut s)?; Ok(String::from_utf8(output).expect("Ron should be utf-8")) } @@ -112,11 +139,7 @@ impl Options { T: ?Sized + ser::Serialize, { let mut output = Vec::new(); - let mut s = Serializer::new_with_default_extensions( - &mut output, - Some(config), - self.default_extensions, - )?; + let mut s = Serializer::with_options(&mut output, Some(config), self.clone())?; value.serialize(&mut s)?; Ok(String::from_utf8(output).expect("Ron should be utf-8")) } diff --git a/src/parse.rs b/src/parse.rs index d20c0f9b2..a00e7a8d1 100644 --- a/src/parse.rs +++ b/src/parse.rs @@ -2,12 +2,11 @@ use std::{ char::from_u32 as char_from_u32, - fmt::{Display, Formatter, Result as FmtResult}, str::{from_utf8, from_utf8_unchecked, FromStr}, }; use crate::{ - error::{Error, ErrorCode, Result}, + error::{Error, ErrorCode, Position, Result}, extensions::Extensions, }; @@ -922,18 +921,6 @@ pub enum ParsedStr<'a> { Slice(&'a str), } -#[derive(Clone, Copy, Debug, PartialEq)] -pub struct Position { - pub line: usize, - pub col: usize, -} - -impl Display for Position { - fn fmt(&self, f: &mut Formatter<'_>) -> FmtResult { - write!(f, "{}:{}", self.line, self.col) - } -} - #[cfg(test)] mod tests { use super::*; diff --git a/src/ser/mod.rs b/src/ser/mod.rs index afa80d094..507a0aa47 100644 --- a/src/ser/mod.rs +++ b/src/ser/mod.rs @@ -18,7 +18,7 @@ where W: io::Write, T: ?Sized + Serialize, { - Options::build().to_writer(writer, value) + Options::default().to_writer(writer, value) } /// Serializes `value` into `writer` in a pretty way. @@ -27,7 +27,7 @@ where W: io::Write, T: ?Sized + Serialize, { - Options::build().to_writer_pretty(writer, value, config) + Options::default().to_writer_pretty(writer, value, config) } /// Serializes `value` and returns it as string. @@ -38,7 +38,7 @@ pub fn to_string(value: &T) -> Result where T: ?Sized + Serialize, { - Options::build().to_string(value) + Options::default().to_string(value) } /// Serializes `value` in the recommended RON layout in a pretty way. @@ -46,7 +46,7 @@ pub fn to_string_pretty(value: &T, config: PrettyConfig) -> Result where T: ?Sized + Serialize, { - Options::build().to_string_pretty(value, config) + Options::default().to_string_pretty(value, config) } /// Pretty serializer state @@ -70,25 +70,18 @@ struct Pretty { #[derive(Clone, Debug, Serialize, Deserialize)] pub struct PrettyConfig { /// Limit the pretty-ness up to the given depth. - #[serde(default = "default_depth_limit")] pub depth_limit: usize, /// New line string - #[serde(default = "default_new_line")] pub new_line: String, /// Indentation string - #[serde(default = "default_indentor")] pub indentor: String, // Whether to emit struct names - #[serde(default = "default_struct_names")] pub struct_names: bool, /// Separate tuple members with indentation - #[serde(default = "default_separate_tuple_members")] pub separate_tuple_members: bool, /// Enumerate array items in comments - #[serde(default = "default_enumerate_arrays")] pub enumerate_arrays: bool, /// Always include the decimal in floats - #[serde(default = "default_decimal_floats")] pub decimal_floats: bool, /// Enable extensions. Only configures 'implicit_some', /// 'unwrap_newtypes', and 'unwrap_variant_newtypes' for now. @@ -186,50 +179,21 @@ impl PrettyConfig { } } -fn default_depth_limit() -> usize { - !0 -} - -fn default_new_line() -> String { - #[cfg(not(target_os = "windows"))] - let new_line = "\n".to_string(); - #[cfg(target_os = "windows")] - let new_line = "\r\n".to_string(); - - new_line -} - -fn default_decimal_floats() -> bool { - false -} - -fn default_indentor() -> String { - " ".to_string() -} - -fn default_struct_names() -> bool { - false -} - -fn default_separate_tuple_members() -> bool { - false -} - -fn default_enumerate_arrays() -> bool { - false -} - impl Default for PrettyConfig { fn default() -> Self { PrettyConfig { - depth_limit: default_depth_limit(), - new_line: default_new_line(), - indentor: default_indentor(), - struct_names: default_struct_names(), - separate_tuple_members: default_separate_tuple_members(), - enumerate_arrays: default_enumerate_arrays(), - extensions: Extensions::default(), - decimal_floats: default_decimal_floats(), + depth_limit: !0, + new_line: if cfg!(not(target_os = "windows")) { + String::from("\n") + } else { + String::from("\r\n") + }, + indentor: String::from(" "), + struct_names: false, + separate_tuple_members: false, + enumerate_arrays: false, + extensions: Extensions::empty(), + decimal_floats: false, _future_proof: (), } } @@ -252,19 +216,19 @@ impl Serializer { /// /// Most of the time you can just use `to_string` or `to_string_pretty`. pub fn new(writer: W, config: Option) -> Result { - Self::new_with_default_extensions(writer, config, Extensions::empty()) + Self::with_options(writer, config, Options::default()) } /// Creates a new `Serializer`. /// /// Most of the time you can just use `to_string` or `to_string_pretty`. - pub fn new_with_default_extensions( + pub fn with_options( mut writer: W, config: Option, - default_extensions: Extensions, + options: Options, ) -> Result { if let Some(conf) = &config { - let non_default_extensions = !default_extensions; + let non_default_extensions = !options.default_extensions; if (non_default_extensions & conf.extensions).contains(Extensions::IMPLICIT_SOME) { writer.write_all(b"#![enable(implicit_some)]")?; @@ -292,7 +256,7 @@ impl Serializer { }, ) }), - default_extensions, + default_extensions: options.default_extensions, is_empty: None, newtype_variant: false, }) @@ -731,10 +695,12 @@ impl<'a, W: io::Write> ser::Serializer for &'a mut Serializer { } } -pub enum State { +enum State { First, Rest, } + +#[doc(hidden)] pub struct Compound<'a, W: io::Write> { ser: &'a mut Serializer, state: State, diff --git a/tests/options.rs b/tests/options.rs index fa40fa733..89a122af8 100644 --- a/tests/options.rs +++ b/tests/options.rs @@ -10,7 +10,7 @@ struct Struct(Option, Newtype); #[test] fn default_options() { - let ron = Options::build(); + let ron = Options::default(); let de: Struct = ron.from_str("(Some(42),(4.2))").unwrap(); let ser = ron.to_string(&de).unwrap(); @@ -20,7 +20,7 @@ fn default_options() { #[test] fn single_default_extension() { - let ron = Options::build().with_default_extension(Extensions::IMPLICIT_SOME); + let ron = Options::default().with_default_extension(Extensions::IMPLICIT_SOME); let de: Struct = ron.from_str("(42,(4.2))").unwrap(); let ser = ron.to_string(&de).unwrap();