use std::io; use base64::Engine; use serde::{ser, ser::Serialize}; use serde_derive::{Deserialize, Serialize}; use crate::{ error::{Error, Result}, extensions::Extensions, options::Options, parse::{ is_ident_first_char, is_ident_other_char, is_ident_raw_char, LargeSInt, LargeUInt, BASE64_ENGINE, }, }; #[cfg(test)] mod tests; mod value; /// Serializes `value` into `writer`. /// /// This function does not generate any newlines or nice formatting; /// if you want that, you can use [`to_writer_pretty`] instead. pub fn to_writer(writer: W, value: &T) -> Result<()> where W: io::Write, T: ?Sized + Serialize, { Options::default().to_writer(writer, value) } /// Serializes `value` into `writer` in a pretty way. pub fn to_writer_pretty(writer: W, value: &T, config: PrettyConfig) -> Result<()> where W: io::Write, T: ?Sized + Serialize, { Options::default().to_writer_pretty(writer, value, config) } /// Serializes `value` and returns it as string. /// /// This function does not generate any newlines or nice formatting; /// if you want that, you can use [`to_string_pretty`] instead. pub fn to_string(value: &T) -> Result where T: ?Sized + Serialize, { Options::default().to_string(value) } /// Serializes `value` in the recommended RON layout in a pretty way. pub fn to_string_pretty(value: &T, config: PrettyConfig) -> Result where T: ?Sized + Serialize, { Options::default().to_string_pretty(value, config) } /// Pretty serializer state struct Pretty { indent: usize, sequence_index: Vec, } /// Pretty serializer configuration. /// /// # Examples /// /// ``` /// use ron::ser::PrettyConfig; /// /// let my_config = PrettyConfig::new() /// .depth_limit(4) /// // definitely superior (okay, just joking) /// .indentor("\t".to_owned()); /// ``` #[derive(Clone, Debug, Serialize, Deserialize)] #[serde(default)] #[non_exhaustive] pub struct PrettyConfig { /// Limit the pretty-ness up to the given depth. pub depth_limit: usize, /// New line string pub new_line: String, /// Indentation string pub indentor: String, /// Separator string pub separator: String, // Whether to emit struct names pub struct_names: bool, /// Separate tuple members with indentation pub separate_tuple_members: bool, /// Enumerate array items in comments pub enumerate_arrays: bool, /// Enable extensions. Only configures 'implicit_some', /// 'unwrap_newtypes', and 'unwrap_variant_newtypes' for now. pub extensions: Extensions, /// Enable compact arrays pub compact_arrays: bool, } impl PrettyConfig { /// Creates a default [`PrettyConfig`]. pub fn new() -> Self { Default::default() } /// Limits the pretty-formatting based on the number of indentations. /// I.e., with a depth limit of 5, starting with an element of depth /// (indentation level) 6, everything will be put into the same line, /// without pretty formatting. /// /// Default: [usize::MAX] pub fn depth_limit(mut self, depth_limit: usize) -> Self { self.depth_limit = depth_limit; self } /// Configures the newlines used for serialization. /// /// Default: `\r\n` on Windows, `\n` otherwise pub fn new_line(mut self, new_line: String) -> Self { self.new_line = new_line; self } /// Configures the string sequence used for indentation. /// /// Default: 4 spaces pub fn indentor(mut self, indentor: String) -> Self { self.indentor = indentor; self } /// Configures the string sequence used to separate items inline. /// /// Default: 1 space pub fn separator(mut self, separator: String) -> Self { self.separator = separator; self } /// Configures whether to emit struct names. /// /// Default: `false` pub fn struct_names(mut self, struct_names: bool) -> Self { self.struct_names = struct_names; self } /// Configures whether tuples are single- or multi-line. /// If set to `true`, tuples will have their fields indented and in new /// lines. If set to `false`, tuples will be serialized without any /// newlines or indentations. /// /// Default: `false` pub fn separate_tuple_members(mut self, separate_tuple_members: bool) -> Self { self.separate_tuple_members = separate_tuple_members; self } /// Configures whether a comment shall be added to every array element, /// indicating the index. /// /// Default: `false` pub fn enumerate_arrays(mut self, enumerate_arrays: bool) -> Self { self.enumerate_arrays = enumerate_arrays; self } /// Configures whether every array should be a single line (`true`) /// or a multi line one (`false`). /// /// When `false`, `["a","b"]` (as well as any array) will serialize to /// ``` /// [ /// "a", /// "b", /// ] /// # ; /// ``` /// When `true`, `["a","b"]` (as well as any array) will serialize to /// ``` /// ["a","b"] /// # ; /// ``` /// /// Default: `false` pub fn compact_arrays(mut self, compact_arrays: bool) -> Self { self.compact_arrays = compact_arrays; self } /// Configures extensions /// /// Default: [Extensions::empty()] pub fn extensions(mut self, extensions: Extensions) -> Self { self.extensions = extensions; self } } impl Default for PrettyConfig { fn default() -> Self { PrettyConfig { depth_limit: usize::MAX, new_line: if cfg!(not(target_os = "windows")) { String::from("\n") } else { String::from("\r\n") }, indentor: String::from(" "), separator: String::from(" "), struct_names: false, separate_tuple_members: false, enumerate_arrays: false, extensions: Extensions::empty(), compact_arrays: false, } } } /// The RON serializer. /// /// You can just use [`to_string`] for deserializing a value. /// If you want it pretty-printed, take a look at [`to_string_pretty`]. pub struct Serializer { output: W, pretty: Option<(PrettyConfig, Pretty)>, default_extensions: Extensions, is_empty: Option, newtype_variant: bool, recursion_limit: Option, } impl Serializer { /// Creates a new [`Serializer`]. /// /// Most of the time you can just use [`to_string`] or /// [`to_string_pretty`]. pub fn new(writer: W, config: Option) -> Result { 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 with_options( mut writer: W, config: Option, options: Options, ) -> Result { if let Some(conf) = &config { let non_default_extensions = !options.default_extensions; if (non_default_extensions & conf.extensions).contains(Extensions::IMPLICIT_SOME) { writer.write_all(b"#![enable(implicit_some)]")?; writer.write_all(conf.new_line.as_bytes())?; }; if (non_default_extensions & conf.extensions).contains(Extensions::UNWRAP_NEWTYPES) { writer.write_all(b"#![enable(unwrap_newtypes)]")?; writer.write_all(conf.new_line.as_bytes())?; }; if (non_default_extensions & conf.extensions) .contains(Extensions::UNWRAP_VARIANT_NEWTYPES) { writer.write_all(b"#![enable(unwrap_variant_newtypes)]")?; writer.write_all(conf.new_line.as_bytes())?; }; }; Ok(Serializer { output: writer, pretty: config.map(|conf| { ( conf, Pretty { indent: 0, sequence_index: Vec::new(), }, ) }), default_extensions: options.default_extensions, is_empty: None, newtype_variant: false, recursion_limit: options.recursion_limit, }) } fn separate_tuple_members(&self) -> bool { self.pretty .as_ref() .map_or(false, |&(ref config, _)| config.separate_tuple_members) } fn compact_arrays(&self) -> bool { self.pretty .as_ref() .map_or(false, |&(ref config, _)| config.compact_arrays) } fn extensions(&self) -> Extensions { self.default_extensions | self .pretty .as_ref() .map_or(Extensions::empty(), |&(ref config, _)| config.extensions) } fn start_indent(&mut self) -> Result<()> { if let Some((ref config, ref mut pretty)) = self.pretty { pretty.indent += 1; if pretty.indent <= config.depth_limit { let is_empty = self.is_empty.unwrap_or(false); if !is_empty { self.output.write_all(config.new_line.as_bytes())?; } } } Ok(()) } fn indent(&mut self) -> io::Result<()> { if let Some((ref config, ref pretty)) = self.pretty { if pretty.indent <= config.depth_limit { for _ in 0..pretty.indent { self.output.write_all(config.indentor.as_bytes())?; } } } Ok(()) } fn end_indent(&mut self) -> io::Result<()> { if let Some((ref config, ref mut pretty)) = self.pretty { if pretty.indent <= config.depth_limit { let is_empty = self.is_empty.unwrap_or(false); if !is_empty { for _ in 1..pretty.indent { self.output.write_all(config.indentor.as_bytes())?; } } } pretty.indent -= 1; self.is_empty = None; } Ok(()) } fn serialize_escaped_str(&mut self, value: &str) -> io::Result<()> { self.output.write_all(b"\"")?; let mut scalar = [0u8; 4]; for c in value.chars().flat_map(|c| c.escape_debug()) { self.output .write_all(c.encode_utf8(&mut scalar).as_bytes())?; } self.output.write_all(b"\"")?; Ok(()) } fn serialize_sint(&mut self, value: impl Into) -> Result<()> { // TODO optimize write!(self.output, "{}", value.into())?; Ok(()) } fn serialize_uint(&mut self, value: impl Into) -> Result<()> { // TODO optimize write!(self.output, "{}", value.into())?; Ok(()) } fn write_identifier(&mut self, name: &str) -> Result<()> { if name.is_empty() || !name.as_bytes().iter().copied().all(is_ident_raw_char) { return Err(Error::InvalidIdentifier(name.into())); } let mut bytes = name.as_bytes().iter().copied(); if !bytes.next().map_or(false, is_ident_first_char) || !bytes.all(is_ident_other_char) { self.output.write_all(b"r#")?; } self.output.write_all(name.as_bytes())?; Ok(()) } fn struct_names(&self) -> bool { self.pretty .as_ref() .map(|(pc, _)| pc.struct_names) .unwrap_or(false) } } macro_rules! guard_recursion { ($self:expr => $expr:expr) => {{ if let Some(limit) = &mut $self.recursion_limit { if let Some(new_limit) = limit.checked_sub(1) { *limit = new_limit; } else { return Err(Error::ExceededRecursionLimit); } } let result = $expr; if let Some(limit) = &mut $self.recursion_limit { *limit = limit.saturating_add(1); } result }}; } impl<'a, W: io::Write> ser::Serializer for &'a mut Serializer { type Error = Error; type Ok = (); type SerializeMap = Compound<'a, W>; type SerializeSeq = Compound<'a, W>; type SerializeStruct = Compound<'a, W>; type SerializeStructVariant = Compound<'a, W>; type SerializeTuple = Compound<'a, W>; type SerializeTupleStruct = Compound<'a, W>; type SerializeTupleVariant = Compound<'a, W>; fn serialize_bool(self, v: bool) -> Result<()> { self.output.write_all(if v { b"true" } else { b"false" })?; Ok(()) } fn serialize_i8(self, v: i8) -> Result<()> { self.serialize_sint(v) } fn serialize_i16(self, v: i16) -> Result<()> { self.serialize_sint(v) } fn serialize_i32(self, v: i32) -> Result<()> { self.serialize_sint(v) } fn serialize_i64(self, v: i64) -> Result<()> { self.serialize_sint(v) } #[cfg(feature = "integer128")] fn serialize_i128(self, v: i128) -> Result<()> { self.serialize_sint(v) } fn serialize_u8(self, v: u8) -> Result<()> { self.serialize_uint(v) } fn serialize_u16(self, v: u16) -> Result<()> { self.serialize_uint(v) } fn serialize_u32(self, v: u32) -> Result<()> { self.serialize_uint(v) } fn serialize_u64(self, v: u64) -> Result<()> { self.serialize_uint(v) } #[cfg(feature = "integer128")] fn serialize_u128(self, v: u128) -> Result<()> { self.serialize_uint(v) } fn serialize_f32(self, v: f32) -> Result<()> { write!(self.output, "{}", v)?; if v.fract() == 0.0 { write!(self.output, ".0")?; } Ok(()) } fn serialize_f64(self, v: f64) -> Result<()> { write!(self.output, "{}", v)?; if v.fract() == 0.0 { write!(self.output, ".0")?; } Ok(()) } fn serialize_char(self, v: char) -> Result<()> { self.output.write_all(b"'")?; if v == '\\' || v == '\'' { self.output.write_all(b"\\")?; } write!(self.output, "{}", v)?; self.output.write_all(b"'")?; Ok(()) } fn serialize_str(self, v: &str) -> Result<()> { self.serialize_escaped_str(v)?; Ok(()) } fn serialize_bytes(self, v: &[u8]) -> Result<()> { self.serialize_str(BASE64_ENGINE.encode(v).as_str()) } fn serialize_none(self) -> Result<()> { self.output.write_all(b"None")?; Ok(()) } fn serialize_some(self, value: &T) -> Result<()> where T: ?Sized + Serialize, { let implicit_some = self.extensions().contains(Extensions::IMPLICIT_SOME); if !implicit_some { self.output.write_all(b"Some(")?; } guard_recursion! { self => value.serialize(&mut *self)? }; if !implicit_some { self.output.write_all(b")")?; } Ok(()) } fn serialize_unit(self) -> Result<()> { if !self.newtype_variant { self.output.write_all(b"()")?; } self.newtype_variant = false; Ok(()) } fn serialize_unit_struct(self, name: &'static str) -> Result<()> { if self.struct_names() && !self.newtype_variant { self.write_identifier(name)?; Ok(()) } else { self.serialize_unit() } } fn serialize_unit_variant(self, _: &'static str, _: u32, variant: &'static str) -> Result<()> { self.write_identifier(variant)?; Ok(()) } fn serialize_newtype_struct(self, name: &'static str, value: &T) -> Result<()> where T: ?Sized + Serialize, { if self.extensions().contains(Extensions::UNWRAP_NEWTYPES) || self.newtype_variant { self.newtype_variant = false; return guard_recursion! { self => value.serialize(&mut *self) }; } if self.struct_names() { self.write_identifier(name)?; } self.output.write_all(b"(")?; guard_recursion! { self => value.serialize(&mut *self)? }; self.output.write_all(b")")?; Ok(()) } fn serialize_newtype_variant( self, _: &'static str, _: u32, variant: &'static str, value: &T, ) -> Result<()> where T: ?Sized + Serialize, { self.write_identifier(variant)?; self.output.write_all(b"(")?; self.newtype_variant = self .extensions() .contains(Extensions::UNWRAP_VARIANT_NEWTYPES); guard_recursion! { self => value.serialize(&mut *self)? }; self.newtype_variant = false; self.output.write_all(b")")?; Ok(()) } fn serialize_seq(self, len: Option) -> Result { self.newtype_variant = false; self.output.write_all(b"[")?; if let Some(len) = len { self.is_empty = Some(len == 0); } if !self.compact_arrays() { self.start_indent()?; } if let Some((_, ref mut pretty)) = self.pretty { pretty.sequence_index.push(0); } Compound::try_new(self, false) } fn serialize_tuple(self, len: usize) -> Result { let old_newtype_variant = self.newtype_variant; self.newtype_variant = false; if !old_newtype_variant { self.output.write_all(b"(")?; } if self.separate_tuple_members() { self.is_empty = Some(len == 0); self.start_indent()?; } Compound::try_new(self, old_newtype_variant) } fn serialize_tuple_struct( self, name: &'static str, len: usize, ) -> Result { if self.struct_names() && !self.newtype_variant { self.write_identifier(name)?; } self.serialize_tuple(len) } fn serialize_tuple_variant( self, _: &'static str, _: u32, variant: &'static str, len: usize, ) -> Result { self.newtype_variant = false; self.write_identifier(variant)?; self.output.write_all(b"(")?; if self.separate_tuple_members() { self.is_empty = Some(len == 0); self.start_indent()?; } Compound::try_new(self, false) } fn serialize_map(self, len: Option) -> Result { self.newtype_variant = false; self.output.write_all(b"{")?; if let Some(len) = len { self.is_empty = Some(len == 0); } self.start_indent()?; Compound::try_new(self, false) } fn serialize_struct(self, name: &'static str, len: usize) -> Result { let old_newtype_variant = self.newtype_variant; self.newtype_variant = false; if !old_newtype_variant { if self.struct_names() { self.write_identifier(name)?; } self.output.write_all(b"(")?; } self.is_empty = Some(len == 0); self.start_indent()?; Compound::try_new(self, old_newtype_variant) } fn serialize_struct_variant( self, _: &'static str, _: u32, variant: &'static str, len: usize, ) -> Result { self.newtype_variant = false; self.write_identifier(variant)?; self.output.write_all(b"(")?; self.is_empty = Some(len == 0); self.start_indent()?; Compound::try_new(self, false) } } enum State { First, Rest, } #[doc(hidden)] pub struct Compound<'a, W: io::Write> { ser: &'a mut Serializer, state: State, newtype_variant: bool, } impl<'a, W: io::Write> Compound<'a, W> { fn try_new(ser: &'a mut Serializer, newtype_variant: bool) -> Result { if let Some(limit) = &mut ser.recursion_limit { if let Some(new_limit) = limit.checked_sub(1) { *limit = new_limit; } else { return Err(Error::ExceededRecursionLimit); } } Ok(Compound { ser, state: State::First, newtype_variant, }) } } impl<'a, W: io::Write> Drop for Compound<'a, W> { fn drop(&mut self) { if let Some(limit) = &mut self.ser.recursion_limit { *limit = limit.saturating_add(1); } } } impl<'a, W: io::Write> ser::SerializeSeq for Compound<'a, W> { type Error = Error; type Ok = (); fn serialize_element(&mut self, value: &T) -> Result<()> where T: ?Sized + Serialize, { if let State::First = self.state { self.state = State::Rest; } else { self.ser.output.write_all(b",")?; if let Some((ref config, ref mut pretty)) = self.ser.pretty { if pretty.indent <= config.depth_limit && !config.compact_arrays { self.ser.output.write_all(config.new_line.as_bytes())?; } else { self.ser.output.write_all(config.separator.as_bytes())?; } } } if !self.ser.compact_arrays() { self.ser.indent()?; } if let Some((ref mut config, ref mut pretty)) = self.ser.pretty { if pretty.indent <= config.depth_limit && config.enumerate_arrays { let index = pretty.sequence_index.last_mut().unwrap(); write!(self.ser.output, "/*[{}]*/ ", index)?; *index += 1; } } guard_recursion! { self.ser => value.serialize(&mut *self.ser)? }; Ok(()) } fn end(self) -> Result<()> { if let State::Rest = self.state { if let Some((ref config, ref mut pretty)) = self.ser.pretty { if pretty.indent <= config.depth_limit && !config.compact_arrays { self.ser.output.write_all(b",")?; self.ser.output.write_all(config.new_line.as_bytes())?; } } } if !self.ser.compact_arrays() { self.ser.end_indent()?; } if let Some((_, ref mut pretty)) = self.ser.pretty { pretty.sequence_index.pop(); } // seq always disables `self.newtype_variant` self.ser.output.write_all(b"]")?; Ok(()) } } impl<'a, W: io::Write> ser::SerializeTuple for Compound<'a, W> { type Error = Error; type Ok = (); fn serialize_element(&mut self, value: &T) -> Result<()> where T: ?Sized + Serialize, { if let State::First = self.state { self.state = State::Rest; } else { self.ser.output.write_all(b",")?; if let Some((ref config, ref pretty)) = self.ser.pretty { if pretty.indent <= config.depth_limit && self.ser.separate_tuple_members() { self.ser.output.write_all(config.new_line.as_bytes())?; } else { self.ser.output.write_all(config.separator.as_bytes())?; } } } if self.ser.separate_tuple_members() { self.ser.indent()?; } guard_recursion! { self.ser => value.serialize(&mut *self.ser)? }; Ok(()) } fn end(self) -> Result<()> { if let State::Rest = self.state { if let Some((ref config, ref pretty)) = self.ser.pretty { if self.ser.separate_tuple_members() && pretty.indent <= config.depth_limit { self.ser.output.write_all(b",")?; self.ser.output.write_all(config.new_line.as_bytes())?; } } } if self.ser.separate_tuple_members() { self.ser.end_indent()?; } if !self.newtype_variant { self.ser.output.write_all(b")")?; } Ok(()) } } // Same thing but for tuple structs. impl<'a, W: io::Write> ser::SerializeTupleStruct for Compound<'a, W> { type Error = Error; type Ok = (); fn serialize_field(&mut self, value: &T) -> Result<()> where T: ?Sized + Serialize, { ser::SerializeTuple::serialize_element(self, value) } fn end(self) -> Result<()> { ser::SerializeTuple::end(self) } } impl<'a, W: io::Write> ser::SerializeTupleVariant for Compound<'a, W> { type Error = Error; type Ok = (); fn serialize_field(&mut self, value: &T) -> Result<()> where T: ?Sized + Serialize, { ser::SerializeTuple::serialize_element(self, value) } fn end(self) -> Result<()> { ser::SerializeTuple::end(self) } } impl<'a, W: io::Write> ser::SerializeMap for Compound<'a, W> { type Error = Error; type Ok = (); fn serialize_key(&mut self, key: &T) -> Result<()> where T: ?Sized + Serialize, { if let State::First = self.state { self.state = State::Rest; } else { self.ser.output.write_all(b",")?; if let Some((ref config, ref pretty)) = self.ser.pretty { if pretty.indent <= config.depth_limit { self.ser.output.write_all(config.new_line.as_bytes())?; } else { self.ser.output.write_all(config.separator.as_bytes())?; } } } self.ser.indent()?; guard_recursion! { self.ser => key.serialize(&mut *self.ser) } } fn serialize_value(&mut self, value: &T) -> Result<()> where T: ?Sized + Serialize, { self.ser.output.write_all(b":")?; if let Some((ref config, _)) = self.ser.pretty { self.ser.output.write_all(config.separator.as_bytes())?; } guard_recursion! { self.ser => value.serialize(&mut *self.ser)? }; Ok(()) } fn end(self) -> Result<()> { if let State::Rest = self.state { if let Some((ref config, ref pretty)) = self.ser.pretty { if pretty.indent <= config.depth_limit { self.ser.output.write_all(b",")?; self.ser.output.write_all(config.new_line.as_bytes())?; } } } self.ser.end_indent()?; // map always disables `self.newtype_variant` self.ser.output.write_all(b"}")?; Ok(()) } } impl<'a, W: io::Write> ser::SerializeStruct for Compound<'a, W> { type Error = Error; type Ok = (); fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> where T: ?Sized + Serialize, { if let State::First = self.state { self.state = State::Rest; } else { self.ser.output.write_all(b",")?; if let Some((ref config, ref pretty)) = self.ser.pretty { if pretty.indent <= config.depth_limit { self.ser.output.write_all(config.new_line.as_bytes())?; } else { self.ser.output.write_all(config.separator.as_bytes())?; } } } self.ser.indent()?; self.ser.write_identifier(key)?; self.ser.output.write_all(b":")?; if let Some((ref config, _)) = self.ser.pretty { self.ser.output.write_all(config.separator.as_bytes())?; } guard_recursion! { self.ser => value.serialize(&mut *self.ser)? }; Ok(()) } fn end(self) -> Result<()> { if let State::Rest = self.state { if let Some((ref config, ref pretty)) = self.ser.pretty { if pretty.indent <= config.depth_limit { self.ser.output.write_all(b",")?; self.ser.output.write_all(config.new_line.as_bytes())?; } } } self.ser.end_indent()?; if !self.newtype_variant { self.ser.output.write_all(b")")?; } Ok(()) } } impl<'a, W: io::Write> ser::SerializeStructVariant for Compound<'a, W> { type Error = Error; type Ok = (); fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<()> where T: ?Sized + Serialize, { ser::SerializeStruct::serialize_field(self, key, value) } fn end(self) -> Result<()> { ser::SerializeStruct::end(self) } }