use super::Error; /// Serialization for TOML [values][crate::Value]. /// /// This structure implements serialization support for TOML to serialize an /// arbitrary type to TOML. Note that the TOML format does not support all /// datatypes in Rust, such as enums, tuples, and tuple structs. These types /// will generate an error when serialized. /// /// Currently a serializer always writes its output to an in-memory `String`, /// which is passed in when creating the serializer itself. /// /// # Examples /// /// ``` /// use serde::Serialize; /// /// #[derive(Serialize)] /// struct Config { /// database: Database, /// } /// /// #[derive(Serialize)] /// struct Database { /// ip: String, /// port: Vec, /// connection_max: u32, /// enabled: bool, /// } /// /// let config = Config { /// database: Database { /// ip: "192.168.1.1".to_string(), /// port: vec![8001, 8002, 8003], /// connection_max: 5000, /// enabled: false, /// }, /// }; /// /// let value = serde::Serialize::serialize( /// &config, /// toml_edit::ser::ValueSerializer::new() /// ).unwrap(); /// println!("{}", value) /// ``` #[derive(Default)] #[non_exhaustive] pub struct ValueSerializer {} impl ValueSerializer { /// Creates a new serializer generate a TOML document. pub fn new() -> Self { Self {} } } impl serde::ser::Serializer for ValueSerializer { type Ok = crate::Value; type Error = Error; type SerializeSeq = super::SerializeValueArray; type SerializeTuple = super::SerializeValueArray; type SerializeTupleStruct = super::SerializeValueArray; type SerializeTupleVariant = super::SerializeTupleVariant; type SerializeMap = super::SerializeMap; type SerializeStruct = super::SerializeMap; type SerializeStructVariant = super::SerializeStructVariant; fn serialize_bool(self, v: bool) -> Result { Ok(v.into()) } fn serialize_i8(self, v: i8) -> Result { self.serialize_i64(v as i64) } fn serialize_i16(self, v: i16) -> Result { self.serialize_i64(v as i64) } fn serialize_i32(self, v: i32) -> Result { self.serialize_i64(v as i64) } fn serialize_i64(self, v: i64) -> Result { Ok(v.into()) } fn serialize_u8(self, v: u8) -> Result { self.serialize_i64(v as i64) } fn serialize_u16(self, v: u16) -> Result { self.serialize_i64(v as i64) } fn serialize_u32(self, v: u32) -> Result { self.serialize_i64(v as i64) } fn serialize_u64(self, v: u64) -> Result { let v: i64 = v .try_into() .map_err(|_err| Error::OutOfRange(Some("u64")))?; self.serialize_i64(v) } fn serialize_f32(self, v: f32) -> Result { self.serialize_f64(v as f64) } fn serialize_f64(self, mut v: f64) -> Result { // Discard sign of NaN when serialized using Serde. // // In all likelihood the sign of NaNs is not meaningful in the user's // program. Ending up with `-nan` in the TOML document would usually be // surprising and undesirable, when the sign of the NaN was not // intentionally controlled by the caller, or may even be // nondeterministic if it comes from arithmetic operations or a cast. if v.is_nan() { v = v.copysign(1.0); } Ok(v.into()) } fn serialize_char(self, v: char) -> Result { let mut buf = [0; 4]; self.serialize_str(v.encode_utf8(&mut buf)) } fn serialize_str(self, v: &str) -> Result { Ok(v.into()) } fn serialize_bytes(self, value: &[u8]) -> Result { use serde::ser::Serialize; value.serialize(self) } fn serialize_none(self) -> Result { Err(Error::UnsupportedNone) } fn serialize_some(self, value: &T) -> Result where T: serde::ser::Serialize, { value.serialize(self) } fn serialize_unit(self) -> Result { Err(Error::UnsupportedType(Some("unit"))) } fn serialize_unit_struct(self, name: &'static str) -> Result { Err(Error::UnsupportedType(Some(name))) } fn serialize_unit_variant( self, _name: &'static str, _variant_index: u32, variant: &'static str, ) -> Result { self.serialize_str(variant) } fn serialize_newtype_struct( self, _name: &'static str, value: &T, ) -> Result where T: serde::ser::Serialize, { value.serialize(self) } fn serialize_newtype_variant( self, _name: &'static str, _variant_index: u32, variant: &'static str, value: &T, ) -> Result where T: serde::ser::Serialize, { let value = value.serialize(self)?; let mut table = crate::InlineTable::new(); table.insert(variant, value); Ok(table.into()) } fn serialize_seq(self, len: Option) -> Result { let serializer = match len { Some(len) => super::SerializeValueArray::with_capacity(len), None => super::SerializeValueArray::new(), }; Ok(serializer) } fn serialize_tuple(self, len: usize) -> Result { self.serialize_seq(Some(len)) } fn serialize_tuple_struct( self, _name: &'static str, len: usize, ) -> Result { self.serialize_seq(Some(len)) } fn serialize_tuple_variant( self, _name: &'static str, _variant_index: u32, variant: &'static str, len: usize, ) -> Result { Ok(super::SerializeTupleVariant::tuple(variant, len)) } fn serialize_map(self, len: Option) -> Result { let serializer = match len { Some(len) => super::SerializeMap::table_with_capacity(len), None => super::SerializeMap::table(), }; Ok(serializer) } fn serialize_struct( self, name: &'static str, len: usize, ) -> Result { if name == toml_datetime::__unstable::NAME { Ok(super::SerializeMap::datetime()) } else { self.serialize_map(Some(len)) } } fn serialize_struct_variant( self, _name: &'static str, _variant_index: u32, variant: &'static str, len: usize, ) -> Result { Ok(super::SerializeStructVariant::struct_(variant, len)) } }