diff options
Diffstat (limited to 'third_party/rust/ron/src/ser')
-rw-r--r-- | third_party/rust/ron/src/ser/mod.rs | 996 | ||||
-rw-r--r-- | third_party/rust/ron/src/ser/tests.rs | 146 | ||||
-rw-r--r-- | third_party/rust/ron/src/ser/value.rs | 23 |
3 files changed, 1165 insertions, 0 deletions
diff --git a/third_party/rust/ron/src/ser/mod.rs b/third_party/rust/ron/src/ser/mod.rs new file mode 100644 index 0000000000..f723d15e09 --- /dev/null +++ b/third_party/rust/ron/src/ser/mod.rs @@ -0,0 +1,996 @@ +use serde::{ser, Deserialize, Serialize}; +use std::io; + +use crate::{ + error::{Error, Result}, + extensions::Extensions, + options::Options, + parse::{is_ident_first_char, is_ident_other_char, LargeSInt, LargeUInt}, +}; + +#[cfg(test)] +mod tests; +mod value; + +/// Serializes `value` into `writer` +pub fn to_writer<W, T>(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<W, T>(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<T>(value: &T) -> Result<String> +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<T>(value: &T, config: PrettyConfig) -> Result<String> +where + T: ?Sized + Serialize, +{ + Options::default().to_string_pretty(value, config) +} + +/// Pretty serializer state +struct Pretty { + indent: usize, + sequence_index: Vec<usize>, +} + +/// 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: [std::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: !0, + 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 the `pretty` module. +pub struct Serializer<W: io::Write> { + output: W, + pretty: Option<(PrettyConfig, Pretty)>, + default_extensions: Extensions, + is_empty: Option<bool>, + newtype_variant: bool, +} + +impl<W: io::Write> Serializer<W> { + /// 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<PrettyConfig>) -> Result<Self> { + 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<PrettyConfig>, + options: Options, + ) -> Result<Self> { + 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, + }) + } + + 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<LargeSInt>) -> Result<()> { + // TODO optimize + write!(self.output, "{}", value.into())?; + + Ok(()) + } + + fn serialize_uint(&mut self, value: impl Into<LargeUInt>) -> Result<()> { + // TODO optimize + write!(self.output, "{}", value.into())?; + + Ok(()) + } + + fn write_identifier(&mut self, name: &str) -> io::Result<()> { + let mut bytes = name.as_bytes().iter().cloned(); + 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) + } +} + +impl<'a, W: io::Write> ser::Serializer for &'a mut Serializer<W> { + 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::encode(v).as_str()) + } + + fn serialize_none(self) -> Result<()> { + self.output.write_all(b"None")?; + + Ok(()) + } + + fn serialize_some<T>(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(")?; + } + 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<T>(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 value.serialize(&mut *self); + } + + if self.struct_names() { + self.write_identifier(name)?; + } + + self.output.write_all(b"(")?; + value.serialize(&mut *self)?; + self.output.write_all(b")")?; + Ok(()) + } + + fn serialize_newtype_variant<T>( + 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); + + value.serialize(&mut *self)?; + + self.newtype_variant = false; + + self.output.write_all(b")")?; + Ok(()) + } + + fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq> { + 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); + } + + Ok(Compound { + ser: self, + state: State::First, + newtype_variant: false, + }) + } + + fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple> { + 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()?; + } + + Ok(Compound { + ser: self, + state: State::First, + newtype_variant: old_newtype_variant, + }) + } + + fn serialize_tuple_struct( + self, + name: &'static str, + len: usize, + ) -> Result<Self::SerializeTupleStruct> { + 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::SerializeTupleVariant> { + 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()?; + } + + Ok(Compound { + ser: self, + state: State::First, + newtype_variant: false, + }) + } + + fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap> { + self.newtype_variant = false; + + self.output.write_all(b"{")?; + + if let Some(len) = len { + self.is_empty = Some(len == 0); + } + + self.start_indent()?; + + Ok(Compound { + ser: self, + state: State::First, + newtype_variant: false, + }) + } + + fn serialize_struct(self, name: &'static str, len: usize) -> Result<Self::SerializeStruct> { + 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()?; + + Ok(Compound { + ser: self, + state: State::First, + newtype_variant: old_newtype_variant, + }) + } + + fn serialize_struct_variant( + self, + _: &'static str, + _: u32, + variant: &'static str, + len: usize, + ) -> Result<Self::SerializeStructVariant> { + self.newtype_variant = false; + + self.write_identifier(variant)?; + self.output.write_all(b"(")?; + + self.is_empty = Some(len == 0); + self.start_indent()?; + + Ok(Compound { + ser: self, + state: State::First, + newtype_variant: false, + }) + } +} + +enum State { + First, + Rest, +} + +#[doc(hidden)] +pub struct Compound<'a, W: io::Write> { + ser: &'a mut Serializer<W>, + state: State, + newtype_variant: bool, +} + +impl<'a, W: io::Write> ser::SerializeSeq for Compound<'a, W> { + type Error = Error; + type Ok = (); + + fn serialize_element<T>(&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; + } + } + + 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<T>(&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()?; + } + + 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<T>(&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<T>(&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<T>(&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()?; + key.serialize(&mut *self.ser) + } + + fn serialize_value<T>(&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())?; + } + + 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<T>(&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())?; + } + + 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<T>(&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) + } +} diff --git a/third_party/rust/ron/src/ser/tests.rs b/third_party/rust/ron/src/ser/tests.rs new file mode 100644 index 0000000000..f1056e6575 --- /dev/null +++ b/third_party/rust/ron/src/ser/tests.rs @@ -0,0 +1,146 @@ +use super::to_string; +use serde::Serialize; + +#[derive(Serialize)] +struct EmptyStruct1; + +#[derive(Serialize)] +struct EmptyStruct2 {} + +#[derive(Serialize)] +struct MyStruct { + x: f32, + y: f32, +} + +#[derive(Serialize)] +enum MyEnum { + A, + B(bool), + C(bool, f32), + D { a: i32, b: i32 }, +} + +#[test] +fn test_empty_struct() { + assert_eq!(to_string(&EmptyStruct1).unwrap(), "()"); + assert_eq!(to_string(&EmptyStruct2 {}).unwrap(), "()"); +} + +#[test] +fn test_struct() { + let my_struct = MyStruct { x: 4.0, y: 7.0 }; + + assert_eq!(to_string(&my_struct).unwrap(), "(x:4.0,y:7.0)"); + + #[derive(Serialize)] + struct NewType(i32); + + assert_eq!(to_string(&NewType(42)).unwrap(), "(42)"); + + #[derive(Serialize)] + struct TupleStruct(f32, f32); + + assert_eq!(to_string(&TupleStruct(2.0, 5.0)).unwrap(), "(2.0,5.0)"); +} + +#[test] +fn test_option() { + assert_eq!(to_string(&Some(1u8)).unwrap(), "Some(1)"); + assert_eq!(to_string(&None::<u8>).unwrap(), "None"); +} + +#[test] +fn test_enum() { + assert_eq!(to_string(&MyEnum::A).unwrap(), "A"); + assert_eq!(to_string(&MyEnum::B(true)).unwrap(), "B(true)"); + assert_eq!(to_string(&MyEnum::C(true, 3.5)).unwrap(), "C(true,3.5)"); + assert_eq!(to_string(&MyEnum::D { a: 2, b: 3 }).unwrap(), "D(a:2,b:3)"); +} + +#[test] +fn test_array() { + let empty: [i32; 0] = []; + assert_eq!(to_string(&empty).unwrap(), "()"); + let empty_ref: &[i32] = ∅ + assert_eq!(to_string(&empty_ref).unwrap(), "[]"); + + assert_eq!(to_string(&[2, 3, 4i32]).unwrap(), "(2,3,4)"); + assert_eq!(to_string(&(&[2, 3, 4i32] as &[i32])).unwrap(), "[2,3,4]"); +} + +#[test] +fn test_slice() { + assert_eq!(to_string(&[0, 1, 2, 3, 4, 5][..]).unwrap(), "[0,1,2,3,4,5]"); + assert_eq!(to_string(&[0, 1, 2, 3, 4, 5][1..4]).unwrap(), "[1,2,3]"); +} + +#[test] +fn test_vec() { + assert_eq!(to_string(&vec![0, 1, 2, 3, 4, 5]).unwrap(), "[0,1,2,3,4,5]"); +} + +#[test] +fn test_map() { + use std::collections::HashMap; + + let mut map = HashMap::new(); + map.insert((true, false), 4); + map.insert((false, false), 123); + + let s = to_string(&map).unwrap(); + s.starts_with('{'); + s.contains("(true,false):4"); + s.contains("(false,false):123"); + s.ends_with('}'); +} + +#[test] +fn test_string() { + assert_eq!(to_string(&"Some string").unwrap(), "\"Some string\""); +} + +#[test] +fn test_char() { + assert_eq!(to_string(&'c').unwrap(), "'c'"); +} + +#[test] +fn test_escape() { + assert_eq!(to_string(&r#""Quoted""#).unwrap(), r#""\"Quoted\"""#); +} + +#[test] +fn test_byte_stream() { + use serde_bytes; + + let small: [u8; 16] = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15]; + assert_eq!( + to_string(&small).unwrap(), + "(0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15)" + ); + + let large = vec![255u8; 64]; + let large = serde_bytes::Bytes::new(&large); + assert_eq!( + to_string(&large).unwrap(), + concat!( + "\"/////////////////////////////////////////", + "////////////////////////////////////////////w==\"" + ) + ); +} + +#[test] +fn rename() { + #[derive(Serialize, Debug, PartialEq)] + enum Foo { + #[serde(rename = "2d")] + D2, + #[serde(rename = "triangle-list")] + TriangleList, + } + + assert_eq!(to_string(&Foo::D2).unwrap(), "r#2d"); + assert_eq!(to_string(&Foo::TriangleList).unwrap(), "r#triangle-list"); +} diff --git a/third_party/rust/ron/src/ser/value.rs b/third_party/rust/ron/src/ser/value.rs new file mode 100644 index 0000000000..1a47758986 --- /dev/null +++ b/third_party/rust/ron/src/ser/value.rs @@ -0,0 +1,23 @@ +use serde::ser::{Serialize, Serializer}; + +use crate::value::{Number, Value}; + +impl Serialize for Value { + fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> + where + S: Serializer, + { + match *self { + Value::Bool(b) => serializer.serialize_bool(b), + Value::Char(c) => serializer.serialize_char(c), + Value::Map(ref m) => Serialize::serialize(m, serializer), + Value::Number(Number::Float(ref f)) => serializer.serialize_f64(f.get()), + Value::Number(Number::Integer(i)) => serializer.serialize_i64(i), + Value::Option(Some(ref o)) => serializer.serialize_some(o.as_ref()), + Value::Option(None) => serializer.serialize_none(), + Value::String(ref s) => serializer.serialize_str(s), + Value::Seq(ref s) => Serialize::serialize(s, serializer), + Value::Unit => serializer.serialize_unit(), + } + } +} |