diff --git a/crates/toml/src/ser/array.rs b/crates/toml/src/ser/array.rs new file mode 100644 index 00000000..b3864612 --- /dev/null +++ b/crates/toml/src/ser/array.rs @@ -0,0 +1,169 @@ +use super::write_document; +use super::write_value; +use super::{Error, Serializer, ValueSerializer}; +use crate::fmt::DocumentFormatter; + +type InnerSerializeDocumentSeq = + ::SerializeSeq; + +#[doc(hidden)] +pub struct SerializeDocumentArray<'d> { + inner: InnerSerializeDocumentSeq, + dst: &'d mut String, + settings: DocumentFormatter, +} + +impl<'d> SerializeDocumentArray<'d> { + pub(crate) fn new(ser: Serializer<'d>, inner: InnerSerializeDocumentSeq) -> Self { + Self { + inner, + dst: ser.dst, + settings: ser.settings, + } + } +} + +impl serde::ser::SerializeSeq for SerializeDocumentArray<'_> { + type Ok = (); + type Error = Error; + + fn serialize_element(&mut self, value: &T) -> Result<(), Error> + where + T: serde::ser::Serialize + ?Sized, + { + self.inner.serialize_element(value).map_err(Error::wrap) + } + + fn end(self) -> Result { + write_document(self.dst, self.settings, self.inner.end()) + } +} + +impl serde::ser::SerializeTuple for SerializeDocumentArray<'_> { + type Ok = (); + type Error = Error; + + fn serialize_element(&mut self, value: &T) -> Result<(), Error> + where + T: serde::ser::Serialize + ?Sized, + { + self.inner.serialize_element(value).map_err(Error::wrap) + } + + fn end(self) -> Result { + write_document(self.dst, self.settings, self.inner.end()) + } +} + +impl serde::ser::SerializeTupleVariant for SerializeDocumentArray<'_> { + type Ok = (); + type Error = Error; + + fn serialize_field(&mut self, value: &T) -> Result<(), Error> + where + T: serde::ser::Serialize + ?Sized, + { + self.inner.serialize_field(value).map_err(Error::wrap) + } + + fn end(self) -> Result { + write_document(self.dst, self.settings, self.inner.end()) + } +} + +impl serde::ser::SerializeTupleStruct for SerializeDocumentArray<'_> { + type Ok = (); + type Error = Error; + + fn serialize_field(&mut self, value: &T) -> Result<(), Error> + where + T: serde::ser::Serialize + ?Sized, + { + self.inner.serialize_field(value).map_err(Error::wrap) + } + + fn end(self) -> Result { + write_document(self.dst, self.settings, self.inner.end()) + } +} + +type InnerSerializeValueSeq = ::SerializeSeq; + +#[doc(hidden)] +pub struct SerializeValueArray<'d> { + inner: InnerSerializeValueSeq, + dst: &'d mut String, +} + +impl<'d> SerializeValueArray<'d> { + pub(crate) fn new(ser: ValueSerializer<'d>, inner: InnerSerializeValueSeq) -> Self { + Self { + inner, + dst: ser.dst, + } + } +} + +impl serde::ser::SerializeSeq for SerializeValueArray<'_> { + type Ok = (); + type Error = Error; + + fn serialize_element(&mut self, value: &T) -> Result<(), Error> + where + T: serde::ser::Serialize + ?Sized, + { + self.inner.serialize_element(value).map_err(Error::wrap) + } + + fn end(self) -> Result { + write_value(self.dst, self.inner.end()) + } +} + +impl serde::ser::SerializeTuple for SerializeValueArray<'_> { + type Ok = (); + type Error = Error; + + fn serialize_element(&mut self, value: &T) -> Result<(), Error> + where + T: serde::ser::Serialize + ?Sized, + { + self.inner.serialize_element(value).map_err(Error::wrap) + } + + fn end(self) -> Result { + write_value(self.dst, self.inner.end()) + } +} + +impl serde::ser::SerializeTupleVariant for SerializeValueArray<'_> { + type Ok = (); + type Error = Error; + + fn serialize_field(&mut self, value: &T) -> Result<(), Error> + where + T: serde::ser::Serialize + ?Sized, + { + self.inner.serialize_field(value).map_err(Error::wrap) + } + + fn end(self) -> Result { + write_value(self.dst, self.inner.end()) + } +} + +impl serde::ser::SerializeTupleStruct for SerializeValueArray<'_> { + type Ok = (); + type Error = Error; + + fn serialize_field(&mut self, value: &T) -> Result<(), Error> + where + T: serde::ser::Serialize + ?Sized, + { + self.inner.serialize_field(value).map_err(Error::wrap) + } + + fn end(self) -> Result { + write_value(self.dst, self.inner.end()) + } +} diff --git a/crates/toml/src/ser/map.rs b/crates/toml/src/ser/map.rs new file mode 100644 index 00000000..9f4cbf79 --- /dev/null +++ b/crates/toml/src/ser/map.rs @@ -0,0 +1,120 @@ +use super::write_document; +use super::write_value; +use super::{Error, Serializer, ValueSerializer}; +use crate::fmt::DocumentFormatter; + +type InnerSerializeDocumentTable = + ::SerializeMap; + +#[doc(hidden)] +pub struct SerializeDocumentTable<'d> { + inner: InnerSerializeDocumentTable, + dst: &'d mut String, + settings: DocumentFormatter, +} + +impl<'d> SerializeDocumentTable<'d> { + pub(crate) fn new(ser: Serializer<'d>, inner: InnerSerializeDocumentTable) -> Self { + Self { + inner, + dst: ser.dst, + settings: ser.settings, + } + } +} + +impl serde::ser::SerializeMap for SerializeDocumentTable<'_> { + type Ok = (); + type Error = Error; + + fn serialize_key(&mut self, input: &T) -> Result<(), Self::Error> + where + T: serde::ser::Serialize + ?Sized, + { + self.inner.serialize_key(input).map_err(Error::wrap) + } + + fn serialize_value(&mut self, value: &T) -> Result<(), Self::Error> + where + T: serde::ser::Serialize + ?Sized, + { + self.inner.serialize_value(value).map_err(Error::wrap) + } + + fn end(self) -> Result { + write_document(self.dst, self.settings, self.inner.end()) + } +} + +impl serde::ser::SerializeStruct for SerializeDocumentTable<'_> { + type Ok = (); + type Error = Error; + + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> + where + T: serde::ser::Serialize + ?Sized, + { + self.inner.serialize_field(key, value).map_err(Error::wrap) + } + + fn end(self) -> Result { + write_document(self.dst, self.settings, self.inner.end()) + } +} + +type InnerSerializeValueTable = + ::SerializeMap; + +#[doc(hidden)] +pub struct SerializeValueTable<'d> { + inner: InnerSerializeValueTable, + dst: &'d mut String, +} + +impl<'d> SerializeValueTable<'d> { + pub(crate) fn new(ser: ValueSerializer<'d>, inner: InnerSerializeValueTable) -> Self { + Self { + inner, + dst: ser.dst, + } + } +} + +impl serde::ser::SerializeMap for SerializeValueTable<'_> { + type Ok = (); + type Error = Error; + + fn serialize_key(&mut self, input: &T) -> Result<(), Self::Error> + where + T: serde::ser::Serialize + ?Sized, + { + self.inner.serialize_key(input).map_err(Error::wrap) + } + + fn serialize_value(&mut self, value: &T) -> Result<(), Self::Error> + where + T: serde::ser::Serialize + ?Sized, + { + self.inner.serialize_value(value).map_err(Error::wrap) + } + + fn end(self) -> Result { + write_value(self.dst, self.inner.end()) + } +} + +impl serde::ser::SerializeStruct for SerializeValueTable<'_> { + type Ok = (); + type Error = Error; + + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> + where + T: serde::ser::Serialize + ?Sized, + { + self.inner.serialize_field(key, value).map_err(Error::wrap) + } + + fn end(self) -> Result { + write_value(self.dst, self.inner.end()) + } +} diff --git a/crates/toml/src/ser.rs b/crates/toml/src/ser/mod.rs similarity index 66% rename from crates/toml/src/ser.rs rename to crates/toml/src/ser/mod.rs index e1c25906..716e3164 100644 --- a/crates/toml/src/ser.rs +++ b/crates/toml/src/ser/mod.rs @@ -4,6 +4,11 @@ //! into TOML documents (as strings). Note that some top-level functions here //! are also provided at the top of the crate. +#[cfg(feature = "display")] +mod array; +#[cfg(feature = "display")] +mod map; + /// Serialize the given data structure as a String of TOML. /// /// Serialization can fail if `T`'s implementation of `Serialize` decides to @@ -179,12 +184,12 @@ impl<'d> Serializer<'d> { impl<'d> serde::ser::Serializer for Serializer<'d> { type Ok = (); type Error = Error; - type SerializeSeq = SerializeDocumentArray<'d>; - type SerializeTuple = SerializeDocumentArray<'d>; - type SerializeTupleStruct = SerializeDocumentArray<'d>; - type SerializeTupleVariant = SerializeDocumentArray<'d>; - type SerializeMap = SerializeDocumentTable<'d>; - type SerializeStruct = SerializeDocumentTable<'d>; + type SerializeSeq = array::SerializeDocumentArray<'d>; + type SerializeTuple = array::SerializeDocumentArray<'d>; + type SerializeTupleStruct = array::SerializeDocumentArray<'d>; + type SerializeTupleVariant = array::SerializeDocumentArray<'d>; + type SerializeMap = map::SerializeDocumentTable<'d>; + type SerializeStruct = map::SerializeDocumentTable<'d>; type SerializeStructVariant = serde::ser::Impossible; fn serialize_bool(self, v: bool) -> Result { @@ -388,7 +393,7 @@ impl<'d> serde::ser::Serializer for Serializer<'d> { let ser = toml_edit::ser::ValueSerializer::new() .serialize_seq(len) .map_err(Error::wrap)?; - let ser = SerializeDocumentArray::new(self, ser); + let ser = array::SerializeDocumentArray::new(self, ser); Ok(ser) } @@ -418,7 +423,7 @@ impl<'d> serde::ser::Serializer for Serializer<'d> { let ser = toml_edit::ser::ValueSerializer::new() .serialize_map(len) .map_err(Error::wrap)?; - let ser = SerializeDocumentTable::new(self, ser); + let ser = map::SerializeDocumentTable::new(self, ser); Ok(ser) } @@ -506,12 +511,12 @@ impl<'d> ValueSerializer<'d> { impl<'d> serde::ser::Serializer for ValueSerializer<'d> { type Ok = (); type Error = Error; - type SerializeSeq = SerializeValueArray<'d>; - type SerializeTuple = SerializeValueArray<'d>; - type SerializeTupleStruct = SerializeValueArray<'d>; - type SerializeTupleVariant = SerializeValueArray<'d>; - type SerializeMap = SerializeValueTable<'d>; - type SerializeStruct = SerializeValueTable<'d>; + type SerializeSeq = array::SerializeValueArray<'d>; + type SerializeTuple = array::SerializeValueArray<'d>; + type SerializeTupleStruct = array::SerializeValueArray<'d>; + type SerializeTupleVariant = array::SerializeValueArray<'d>; + type SerializeMap = map::SerializeValueTable<'d>; + type SerializeStruct = map::SerializeValueTable<'d>; type SerializeStructVariant = serde::ser::Impossible; fn serialize_bool(self, v: bool) -> Result { @@ -694,7 +699,7 @@ impl<'d> serde::ser::Serializer for ValueSerializer<'d> { let ser = toml_edit::ser::ValueSerializer::new() .serialize_seq(len) .map_err(Error::wrap)?; - let ser = SerializeValueArray::new(self, ser); + let ser = array::SerializeValueArray::new(self, ser); Ok(ser) } @@ -724,7 +729,7 @@ impl<'d> serde::ser::Serializer for ValueSerializer<'d> { let ser = toml_edit::ser::ValueSerializer::new() .serialize_map(len) .map_err(Error::wrap)?; - let ser = SerializeValueTable::new(self, ser); + let ser = map::SerializeValueTable::new(self, ser); Ok(ser) } @@ -748,333 +753,40 @@ impl<'d> serde::ser::Serializer for ValueSerializer<'d> { } #[cfg(feature = "display")] -use internal::{ - write_document, write_value, SerializeDocumentArray, SerializeDocumentTable, - SerializeValueArray, SerializeValueTable, -}; - -#[cfg(feature = "display")] -mod internal { - use super::{Error, Serializer, ValueSerializer}; - - use crate::fmt::DocumentFormatter; - - type InnerSerializeDocumentSeq = - ::SerializeSeq; - - #[doc(hidden)] - pub struct SerializeDocumentArray<'d> { - inner: InnerSerializeDocumentSeq, - dst: &'d mut String, - settings: DocumentFormatter, - } - - impl<'d> SerializeDocumentArray<'d> { - pub(crate) fn new(ser: Serializer<'d>, inner: InnerSerializeDocumentSeq) -> Self { - Self { - inner, - dst: ser.dst, - settings: ser.settings, - } - } - } - - impl serde::ser::SerializeSeq for SerializeDocumentArray<'_> { - type Ok = (); - type Error = Error; - - fn serialize_element(&mut self, value: &T) -> Result<(), Error> - where - T: serde::ser::Serialize + ?Sized, - { - self.inner.serialize_element(value).map_err(Error::wrap) - } - - fn end(self) -> Result { - write_document(self.dst, self.settings, self.inner.end()) - } - } - - impl serde::ser::SerializeTuple for SerializeDocumentArray<'_> { - type Ok = (); - type Error = Error; - - fn serialize_element(&mut self, value: &T) -> Result<(), Error> - where - T: serde::ser::Serialize + ?Sized, - { - self.inner.serialize_element(value).map_err(Error::wrap) - } - - fn end(self) -> Result { - write_document(self.dst, self.settings, self.inner.end()) - } - } - - impl serde::ser::SerializeTupleVariant for SerializeDocumentArray<'_> { - type Ok = (); - type Error = Error; - - fn serialize_field(&mut self, value: &T) -> Result<(), Error> - where - T: serde::ser::Serialize + ?Sized, - { - self.inner.serialize_field(value).map_err(Error::wrap) - } - - fn end(self) -> Result { - write_document(self.dst, self.settings, self.inner.end()) - } - } - - impl serde::ser::SerializeTupleStruct for SerializeDocumentArray<'_> { - type Ok = (); - type Error = Error; - - fn serialize_field(&mut self, value: &T) -> Result<(), Error> - where - T: serde::ser::Serialize + ?Sized, - { - self.inner.serialize_field(value).map_err(Error::wrap) - } - - fn end(self) -> Result { - write_document(self.dst, self.settings, self.inner.end()) - } - } - - type InnerSerializeDocumentTable = - ::SerializeMap; - - #[doc(hidden)] - pub struct SerializeDocumentTable<'d> { - inner: InnerSerializeDocumentTable, - dst: &'d mut String, - settings: DocumentFormatter, - } - - impl<'d> SerializeDocumentTable<'d> { - pub(crate) fn new(ser: Serializer<'d>, inner: InnerSerializeDocumentTable) -> Self { - Self { - inner, - dst: ser.dst, - settings: ser.settings, - } - } - } - - impl serde::ser::SerializeMap for SerializeDocumentTable<'_> { - type Ok = (); - type Error = Error; - - fn serialize_key(&mut self, input: &T) -> Result<(), Self::Error> - where - T: serde::ser::Serialize + ?Sized, - { - self.inner.serialize_key(input).map_err(Error::wrap) - } - - fn serialize_value(&mut self, value: &T) -> Result<(), Self::Error> - where - T: serde::ser::Serialize + ?Sized, - { - self.inner.serialize_value(value).map_err(Error::wrap) - } - - fn end(self) -> Result { - write_document(self.dst, self.settings, self.inner.end()) - } - } - - impl serde::ser::SerializeStruct for SerializeDocumentTable<'_> { - type Ok = (); - type Error = Error; - - fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> - where - T: serde::ser::Serialize + ?Sized, - { - self.inner.serialize_field(key, value).map_err(Error::wrap) - } - - fn end(self) -> Result { - write_document(self.dst, self.settings, self.inner.end()) - } - } - - pub(crate) fn write_document( - dst: &mut String, - mut settings: DocumentFormatter, - value: Result, - ) -> Result<(), Error> { - use std::fmt::Write; - use toml_edit::visit_mut::VisitMut as _; - - let value = value.map_err(Error::wrap)?; - let mut table = match toml_edit::Item::Value(value).into_table() { - Ok(i) => i, - Err(_) => { - return Err(Error::unsupported_type(None)); - } - }; - - settings.visit_table_mut(&mut table); - - let doc: toml_edit::DocumentMut = table.into(); - write!(dst, "{doc}").unwrap(); - - Ok(()) - } - - type InnerSerializeValueSeq = - ::SerializeSeq; - - #[doc(hidden)] - pub struct SerializeValueArray<'d> { - inner: InnerSerializeValueSeq, - dst: &'d mut String, - } - - impl<'d> SerializeValueArray<'d> { - pub(crate) fn new(ser: ValueSerializer<'d>, inner: InnerSerializeValueSeq) -> Self { - Self { - inner, - dst: ser.dst, - } - } - } - - impl serde::ser::SerializeSeq for SerializeValueArray<'_> { - type Ok = (); - type Error = Error; +pub(crate) fn write_document( + dst: &mut String, + mut settings: crate::fmt::DocumentFormatter, + value: Result, +) -> Result<(), Error> { + use std::fmt::Write; + use toml_edit::visit_mut::VisitMut as _; - fn serialize_element(&mut self, value: &T) -> Result<(), Error> - where - T: serde::ser::Serialize + ?Sized, - { - self.inner.serialize_element(value).map_err(Error::wrap) + let value = value.map_err(Error::wrap)?; + let mut table = match toml_edit::Item::Value(value).into_table() { + Ok(i) => i, + Err(_) => { + return Err(Error::unsupported_type(None)); } + }; - fn end(self) -> Result { - write_value(self.dst, self.inner.end()) - } - } - - impl serde::ser::SerializeTuple for SerializeValueArray<'_> { - type Ok = (); - type Error = Error; - - fn serialize_element(&mut self, value: &T) -> Result<(), Error> - where - T: serde::ser::Serialize + ?Sized, - { - self.inner.serialize_element(value).map_err(Error::wrap) - } - - fn end(self) -> Result { - write_value(self.dst, self.inner.end()) - } - } - - impl serde::ser::SerializeTupleVariant for SerializeValueArray<'_> { - type Ok = (); - type Error = Error; - - fn serialize_field(&mut self, value: &T) -> Result<(), Error> - where - T: serde::ser::Serialize + ?Sized, - { - self.inner.serialize_field(value).map_err(Error::wrap) - } - - fn end(self) -> Result { - write_value(self.dst, self.inner.end()) - } - } + settings.visit_table_mut(&mut table); - impl serde::ser::SerializeTupleStruct for SerializeValueArray<'_> { - type Ok = (); - type Error = Error; + let doc: toml_edit::DocumentMut = table.into(); + write!(dst, "{doc}").unwrap(); - fn serialize_field(&mut self, value: &T) -> Result<(), Error> - where - T: serde::ser::Serialize + ?Sized, - { - self.inner.serialize_field(value).map_err(Error::wrap) - } - - fn end(self) -> Result { - write_value(self.dst, self.inner.end()) - } - } - - type InnerSerializeValueTable = - ::SerializeMap; - - #[doc(hidden)] - pub struct SerializeValueTable<'d> { - inner: InnerSerializeValueTable, - dst: &'d mut String, - } - - impl<'d> SerializeValueTable<'d> { - pub(crate) fn new(ser: ValueSerializer<'d>, inner: InnerSerializeValueTable) -> Self { - Self { - inner, - dst: ser.dst, - } - } - } - - impl serde::ser::SerializeMap for SerializeValueTable<'_> { - type Ok = (); - type Error = Error; - - fn serialize_key(&mut self, input: &T) -> Result<(), Self::Error> - where - T: serde::ser::Serialize + ?Sized, - { - self.inner.serialize_key(input).map_err(Error::wrap) - } - - fn serialize_value(&mut self, value: &T) -> Result<(), Self::Error> - where - T: serde::ser::Serialize + ?Sized, - { - self.inner.serialize_value(value).map_err(Error::wrap) - } - - fn end(self) -> Result { - write_value(self.dst, self.inner.end()) - } - } - - impl serde::ser::SerializeStruct for SerializeValueTable<'_> { - type Ok = (); - type Error = Error; - - fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> - where - T: serde::ser::Serialize + ?Sized, - { - self.inner.serialize_field(key, value).map_err(Error::wrap) - } - - fn end(self) -> Result { - write_value(self.dst, self.inner.end()) - } - } + Ok(()) +} - pub(crate) fn write_value( - dst: &mut String, - value: Result, - ) -> Result<(), Error> { - use std::fmt::Write; +#[cfg(feature = "display")] +pub(crate) fn write_value( + dst: &mut String, + value: Result, +) -> Result<(), Error> { + use std::fmt::Write; - let value = value.map_err(Error::wrap)?; + let value = value.map_err(Error::wrap)?; - write!(dst, "{value}").unwrap(); + write!(dst, "{value}").unwrap(); - Ok(()) - } + Ok(()) } diff --git a/crates/toml_edit/src/ser/key.rs b/crates/toml_edit/src/ser/key.rs index 6ebbc7ac..42f5bc74 100644 --- a/crates/toml_edit/src/ser/key.rs +++ b/crates/toml_edit/src/ser/key.rs @@ -7,87 +7,87 @@ pub(crate) struct KeySerializer; impl serde::ser::Serializer for KeySerializer { type Ok = Key; type Error = Error; - type SerializeSeq = serde::ser::Impossible; - type SerializeTuple = serde::ser::Impossible; - type SerializeTupleStruct = serde::ser::Impossible; - type SerializeTupleVariant = serde::ser::Impossible; - type SerializeMap = serde::ser::Impossible; - type SerializeStruct = serde::ser::Impossible; - type SerializeStructVariant = serde::ser::Impossible; + type SerializeSeq = serde::ser::Impossible; + type SerializeTuple = serde::ser::Impossible; + type SerializeTupleStruct = serde::ser::Impossible; + type SerializeTupleVariant = serde::ser::Impossible; + type SerializeMap = serde::ser::Impossible; + type SerializeStruct = serde::ser::Impossible; + type SerializeStructVariant = serde::ser::Impossible; - fn serialize_bool(self, _v: bool) -> Result { - Err(Error::KeyNotString) + fn serialize_bool(self, _v: bool) -> Result { + Err(Error::key_not_string()) } - fn serialize_i8(self, _v: i8) -> Result { - Err(Error::KeyNotString) + fn serialize_i8(self, _v: i8) -> Result { + Err(Error::key_not_string()) } - fn serialize_i16(self, _v: i16) -> Result { - Err(Error::KeyNotString) + fn serialize_i16(self, _v: i16) -> Result { + Err(Error::key_not_string()) } - fn serialize_i32(self, _v: i32) -> Result { - Err(Error::KeyNotString) + fn serialize_i32(self, _v: i32) -> Result { + Err(Error::key_not_string()) } - fn serialize_i64(self, _v: i64) -> Result { - Err(Error::KeyNotString) + fn serialize_i64(self, _v: i64) -> Result { + Err(Error::key_not_string()) } - fn serialize_u8(self, _v: u8) -> Result { - Err(Error::KeyNotString) + fn serialize_u8(self, _v: u8) -> Result { + Err(Error::key_not_string()) } - fn serialize_u16(self, _v: u16) -> Result { - Err(Error::KeyNotString) + fn serialize_u16(self, _v: u16) -> Result { + Err(Error::key_not_string()) } - fn serialize_u32(self, _v: u32) -> Result { - Err(Error::KeyNotString) + fn serialize_u32(self, _v: u32) -> Result { + Err(Error::key_not_string()) } - fn serialize_u64(self, _v: u64) -> Result { - Err(Error::KeyNotString) + fn serialize_u64(self, _v: u64) -> Result { + Err(Error::key_not_string()) } - fn serialize_f32(self, _v: f32) -> Result { - Err(Error::KeyNotString) + fn serialize_f32(self, _v: f32) -> Result { + Err(Error::key_not_string()) } - fn serialize_f64(self, _v: f64) -> Result { - Err(Error::KeyNotString) + fn serialize_f64(self, _v: f64) -> Result { + Err(Error::key_not_string()) } - fn serialize_char(self, _v: char) -> Result { - Err(Error::KeyNotString) + fn serialize_char(self, _v: char) -> Result { + Err(Error::key_not_string()) } - fn serialize_str(self, value: &str) -> Result { + fn serialize_str(self, value: &str) -> Result { Ok(Key::new(value)) } - fn serialize_bytes(self, _value: &[u8]) -> Result { - Err(Error::KeyNotString) + fn serialize_bytes(self, _value: &[u8]) -> Result { + Err(Error::key_not_string()) } - fn serialize_none(self) -> Result { - Err(Error::KeyNotString) + fn serialize_none(self) -> Result { + Err(Error::key_not_string()) } - fn serialize_some(self, _value: &T) -> Result + fn serialize_some(self, _value: &T) -> Result where T: serde::ser::Serialize + ?Sized, { - Err(Error::KeyNotString) + Err(Error::key_not_string()) } - fn serialize_unit(self) -> Result { - Err(Error::KeyNotString) + fn serialize_unit(self) -> Result { + Err(Error::key_not_string()) } - fn serialize_unit_struct(self, _name: &'static str) -> Result { - Err(Error::KeyNotString) + fn serialize_unit_struct(self, _name: &'static str) -> Result { + Err(Error::key_not_string()) } fn serialize_unit_variant( @@ -95,11 +95,15 @@ impl serde::ser::Serializer for KeySerializer { _name: &'static str, _variant_index: u32, variant: &'static str, - ) -> Result { + ) -> Result { Ok(variant.into()) } - fn serialize_newtype_struct(self, _name: &'static str, value: &T) -> Result + fn serialize_newtype_struct( + self, + _name: &'static str, + value: &T, + ) -> Result where T: serde::ser::Serialize + ?Sized, { @@ -112,19 +116,19 @@ impl serde::ser::Serializer for KeySerializer { _variant_index: u32, _variant: &'static str, _value: &T, - ) -> Result + ) -> Result where T: serde::ser::Serialize + ?Sized, { - Err(Error::KeyNotString) + Err(Error::key_not_string()) } fn serialize_seq(self, _len: Option) -> Result { - Err(Error::KeyNotString) + Err(Error::key_not_string()) } fn serialize_tuple(self, _len: usize) -> Result { - Err(Error::KeyNotString) + Err(Error::key_not_string()) } fn serialize_tuple_struct( @@ -132,7 +136,7 @@ impl serde::ser::Serializer for KeySerializer { _name: &'static str, _len: usize, ) -> Result { - Err(Error::KeyNotString) + Err(Error::key_not_string()) } fn serialize_tuple_variant( @@ -142,11 +146,11 @@ impl serde::ser::Serializer for KeySerializer { _variant: &'static str, _len: usize, ) -> Result { - Err(Error::KeyNotString) + Err(Error::key_not_string()) } fn serialize_map(self, _len: Option) -> Result { - Err(Error::KeyNotString) + Err(Error::key_not_string()) } fn serialize_struct( @@ -154,7 +158,7 @@ impl serde::ser::Serializer for KeySerializer { _name: &'static str, _len: usize, ) -> Result { - Err(Error::KeyNotString) + Err(Error::key_not_string()) } fn serialize_struct_variant( @@ -164,6 +168,6 @@ impl serde::ser::Serializer for KeySerializer { _variant: &'static str, _len: usize, ) -> Result { - Err(Error::KeyNotString) + Err(Error::key_not_string()) } } diff --git a/crates/toml_edit/src/ser/map.rs b/crates/toml_edit/src/ser/map.rs index e23a0caf..c0ded871 100644 --- a/crates/toml_edit/src/ser/map.rs +++ b/crates/toml_edit/src/ser/map.rs @@ -1,4 +1,7 @@ -use super::{Error, KeySerializer, SerializeValueArray, ValueSerializer}; +use super::array::SerializeValueArray; +use super::key::KeySerializer; +use super::value::ValueSerializer; +use super::Error; #[doc(hidden)] #[allow(clippy::large_enum_variant)] @@ -125,7 +128,7 @@ impl serde::ser::SerializeStruct for SerializeDatetime { } fn end(self) -> Result { - self.value.ok_or(Error::UnsupportedNone) + self.value.ok_or(Error::unsupported_none()) } } @@ -175,7 +178,7 @@ impl serde::ser::SerializeMap for SerializeInlineTable { self.items.insert(key, item); } Err(e) => { - if !(e == Error::UnsupportedNone && value_serializer.is_none) { + if !(e == Error::unsupported_none() && value_serializer.is_none) { return Err(e); } } @@ -204,7 +207,7 @@ impl serde::ser::SerializeStruct for SerializeInlineTable { self.items.insert(crate::Key::new(key), item); } Err(e) => { - if !(e == Error::UnsupportedNone && value_serializer.is_none) { + if !(e == Error::unsupported_none() && value_serializer.is_none) { return Err(e); } } @@ -232,51 +235,51 @@ impl serde::ser::Serializer for DatetimeFieldSerializer { type SerializeStructVariant = serde::ser::Impossible; fn serialize_bool(self, _value: bool) -> Result { - Err(Error::DateInvalid) + Err(Error::date_invalid()) } fn serialize_i8(self, _value: i8) -> Result { - Err(Error::DateInvalid) + Err(Error::date_invalid()) } fn serialize_i16(self, _value: i16) -> Result { - Err(Error::DateInvalid) + Err(Error::date_invalid()) } fn serialize_i32(self, _value: i32) -> Result { - Err(Error::DateInvalid) + Err(Error::date_invalid()) } fn serialize_i64(self, _value: i64) -> Result { - Err(Error::DateInvalid) + Err(Error::date_invalid()) } fn serialize_u8(self, _value: u8) -> Result { - Err(Error::DateInvalid) + Err(Error::date_invalid()) } fn serialize_u16(self, _value: u16) -> Result { - Err(Error::DateInvalid) + Err(Error::date_invalid()) } fn serialize_u32(self, _value: u32) -> Result { - Err(Error::DateInvalid) + Err(Error::date_invalid()) } fn serialize_u64(self, _value: u64) -> Result { - Err(Error::DateInvalid) + Err(Error::date_invalid()) } fn serialize_f32(self, _value: f32) -> Result { - Err(Error::DateInvalid) + Err(Error::date_invalid()) } fn serialize_f64(self, _value: f64) -> Result { - Err(Error::DateInvalid) + Err(Error::date_invalid()) } fn serialize_char(self, _value: char) -> Result { - Err(Error::DateInvalid) + Err(Error::date_invalid()) } fn serialize_str(self, v: &str) -> Result { @@ -284,26 +287,26 @@ impl serde::ser::Serializer for DatetimeFieldSerializer { } fn serialize_bytes(self, _value: &[u8]) -> Result { - Err(Error::DateInvalid) + Err(Error::date_invalid()) } fn serialize_none(self) -> Result { - Err(Error::DateInvalid) + Err(Error::date_invalid()) } fn serialize_some(self, _value: &T) -> Result where T: serde::ser::Serialize + ?Sized, { - Err(Error::DateInvalid) + Err(Error::date_invalid()) } fn serialize_unit(self) -> Result { - Err(Error::DateInvalid) + Err(Error::date_invalid()) } fn serialize_unit_struct(self, _name: &'static str) -> Result { - Err(Error::DateInvalid) + Err(Error::date_invalid()) } fn serialize_unit_variant( @@ -312,7 +315,7 @@ impl serde::ser::Serializer for DatetimeFieldSerializer { _variant_index: u32, _variant: &'static str, ) -> Result { - Err(Error::DateInvalid) + Err(Error::date_invalid()) } fn serialize_newtype_struct( @@ -323,7 +326,7 @@ impl serde::ser::Serializer for DatetimeFieldSerializer { where T: serde::ser::Serialize + ?Sized, { - Err(Error::DateInvalid) + Err(Error::date_invalid()) } fn serialize_newtype_variant( @@ -336,15 +339,15 @@ impl serde::ser::Serializer for DatetimeFieldSerializer { where T: serde::ser::Serialize + ?Sized, { - Err(Error::DateInvalid) + Err(Error::date_invalid()) } fn serialize_seq(self, _len: Option) -> Result { - Err(Error::DateInvalid) + Err(Error::date_invalid()) } fn serialize_tuple(self, _len: usize) -> Result { - Err(Error::DateInvalid) + Err(Error::date_invalid()) } fn serialize_tuple_struct( @@ -352,7 +355,7 @@ impl serde::ser::Serializer for DatetimeFieldSerializer { _name: &'static str, _len: usize, ) -> Result { - Err(Error::DateInvalid) + Err(Error::date_invalid()) } fn serialize_tuple_variant( @@ -362,11 +365,11 @@ impl serde::ser::Serializer for DatetimeFieldSerializer { _variant: &'static str, _len: usize, ) -> Result { - Err(Error::DateInvalid) + Err(Error::date_invalid()) } fn serialize_map(self, _len: Option) -> Result { - Err(Error::DateInvalid) + Err(Error::date_invalid()) } fn serialize_struct( @@ -374,7 +377,7 @@ impl serde::ser::Serializer for DatetimeFieldSerializer { _name: &'static str, _len: usize, ) -> Result { - Err(Error::DateInvalid) + Err(Error::date_invalid()) } fn serialize_struct_variant( @@ -384,11 +387,10 @@ impl serde::ser::Serializer for DatetimeFieldSerializer { _variant: &'static str, _len: usize, ) -> Result { - Err(Error::DateInvalid) + Err(Error::date_invalid()) } } -#[derive(Default)] struct MapValueSerializer { is_none: bool, } @@ -468,7 +470,7 @@ impl serde::ser::Serializer for &mut MapValueSerializer { fn serialize_none(self) -> Result { self.is_none = true; - Err(Error::UnsupportedNone) + Err(Error::unsupported_none()) } fn serialize_some(self, value: &T) -> Result @@ -576,7 +578,7 @@ pub struct SerializeVariant { inner: T, } -impl SerializeVariant { +impl SerializeTupleVariant { pub(crate) fn tuple(variant: &'static str, len: usize) -> Self { Self { variant, @@ -585,7 +587,7 @@ impl SerializeVariant { } } -impl SerializeVariant { +impl SerializeStructVariant { pub(crate) fn struct_(variant: &'static str, len: usize) -> Self { Self { variant, diff --git a/crates/toml_edit/src/ser/mod.rs b/crates/toml_edit/src/ser/mod.rs index 3cf00c30..cf3fccf9 100644 --- a/crates/toml_edit/src/ser/mod.rs +++ b/crates/toml_edit/src/ser/mod.rs @@ -8,76 +8,9 @@ mod map; mod pretty; mod value; -pub(crate) use array::*; -pub(crate) use key::*; -pub(crate) use map::*; +use crate::visit_mut::VisitMut as _; -use crate::visit_mut::VisitMut; - -/// Errors that can occur when deserializing a type. -#[derive(Debug, Clone, PartialEq, Eq)] -#[non_exhaustive] -pub enum Error { - /// Type could not be serialized to TOML - UnsupportedType(Option<&'static str>), - /// Value was out of range for the given type - OutOfRange(Option<&'static str>), - /// `None` could not be serialized to TOML - UnsupportedNone, - /// Key was not convertible to `String` for serializing to TOML - KeyNotString, - /// A serialized date was invalid - DateInvalid, - /// Other serialization error - Custom(String), -} - -impl Error { - pub(crate) fn custom(msg: T) -> Self - where - T: std::fmt::Display, - { - Error::Custom(msg.to_string()) - } -} - -impl serde::ser::Error for Error { - fn custom(msg: T) -> Self - where - T: std::fmt::Display, - { - Self::custom(msg) - } -} - -impl std::fmt::Display for Error { - fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::UnsupportedType(Some(t)) => write!(formatter, "unsupported {t} type"), - Self::UnsupportedType(None) => write!(formatter, "unsupported rust type"), - Self::OutOfRange(Some(t)) => write!(formatter, "out-of-range value for {t} type"), - Self::OutOfRange(None) => write!(formatter, "out-of-range value"), - Self::UnsupportedNone => "unsupported None value".fmt(formatter), - Self::KeyNotString => "map key was not a string".fmt(formatter), - Self::DateInvalid => "a serialized date was invalid".fmt(formatter), - Self::Custom(s) => s.fmt(formatter), - } - } -} - -impl From for Error { - fn from(e: crate::TomlError) -> Error { - Self::custom(e) - } -} - -impl From for crate::TomlError { - fn from(e: Error) -> crate::TomlError { - Self::custom(e.to_string(), None) - } -} - -impl std::error::Error for Error {} +pub use value::ValueSerializer; /// Serialize the given data structure as a TOML byte vector. /// @@ -165,4 +98,87 @@ where Ok(root.into()) } -pub use value::ValueSerializer; +/// Errors that can occur when deserializing a type. +#[derive(Debug, Clone, PartialEq, Eq)] +#[non_exhaustive] +pub enum Error { + /// Type could not be serialized to TOML + UnsupportedType(Option<&'static str>), + /// Value was out of range for the given type + OutOfRange(Option<&'static str>), + /// `None` could not be serialized to TOML + UnsupportedNone, + /// Key was not convertible to `String` for serializing to TOML + KeyNotString, + /// A serialized date was invalid + DateInvalid, + /// Other serialization error + Custom(String), +} + +impl Error { + pub(crate) fn custom(msg: T) -> Self + where + T: std::fmt::Display, + { + Error::Custom(msg.to_string()) + } + + pub(crate) fn unsupported_type(t: Option<&'static str>) -> Self { + Error::UnsupportedType(t) + } + + fn out_of_range(t: Option<&'static str>) -> Self { + Error::OutOfRange(t) + } + + pub(crate) fn unsupported_none() -> Self { + Error::UnsupportedNone + } + + pub(crate) fn key_not_string() -> Self { + Error::KeyNotString + } + + fn date_invalid() -> Self { + Error::DateInvalid + } +} + +impl serde::ser::Error for Error { + fn custom(msg: T) -> Self + where + T: std::fmt::Display, + { + Self::custom(msg) + } +} + +impl std::fmt::Display for Error { + fn fmt(&self, formatter: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Self::UnsupportedType(Some(t)) => write!(formatter, "unsupported {t} type"), + Self::UnsupportedType(None) => write!(formatter, "unsupported rust type"), + Self::OutOfRange(Some(t)) => write!(formatter, "out-of-range value for {t} type"), + Self::OutOfRange(None) => write!(formatter, "out-of-range value"), + Self::UnsupportedNone => "unsupported None value".fmt(formatter), + Self::KeyNotString => "map key was not a string".fmt(formatter), + Self::DateInvalid => "a serialized date was invalid".fmt(formatter), + Self::Custom(s) => s.fmt(formatter), + } + } +} + +impl From for Error { + fn from(e: crate::TomlError) -> Error { + Self::custom(e) + } +} + +impl From for crate::TomlError { + fn from(e: Error) -> crate::TomlError { + Self::custom(e.to_string(), None) + } +} + +impl std::error::Error for Error {} diff --git a/crates/toml_edit/src/ser/value.rs b/crates/toml_edit/src/ser/value.rs index b67bd8af..7898c5f1 100644 --- a/crates/toml_edit/src/ser/value.rs +++ b/crates/toml_edit/src/ser/value.rs @@ -61,13 +61,13 @@ impl ValueSerializer { 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; + type SerializeSeq = super::array::SerializeValueArray; + type SerializeTuple = super::array::SerializeValueArray; + type SerializeTupleStruct = super::array::SerializeValueArray; + type SerializeTupleVariant = super::map::SerializeTupleVariant; + type SerializeMap = super::map::SerializeMap; + type SerializeStruct = super::map::SerializeMap; + type SerializeStructVariant = super::map::SerializeStructVariant; fn serialize_bool(self, v: bool) -> Result { Ok(v.into()) @@ -104,7 +104,7 @@ impl serde::ser::Serializer for ValueSerializer { fn serialize_u64(self, v: u64) -> Result { let v: i64 = v .try_into() - .map_err(|_err| Error::OutOfRange(Some("u64")))?; + .map_err(|_err| Error::out_of_range(Some("u64")))?; self.serialize_i64(v) } @@ -141,7 +141,7 @@ impl serde::ser::Serializer for ValueSerializer { } fn serialize_none(self) -> Result { - Err(Error::UnsupportedNone) + Err(Error::unsupported_none()) } fn serialize_some(self, value: &T) -> Result @@ -152,11 +152,11 @@ impl serde::ser::Serializer for ValueSerializer { } fn serialize_unit(self) -> Result { - Err(Error::UnsupportedType(Some("unit"))) + Err(Error::unsupported_type(Some("unit"))) } fn serialize_unit_struct(self, name: &'static str) -> Result { - Err(Error::UnsupportedType(Some(name))) + Err(Error::unsupported_type(Some(name))) } fn serialize_unit_variant( @@ -197,8 +197,8 @@ impl serde::ser::Serializer for ValueSerializer { fn serialize_seq(self, len: Option) -> Result { let serializer = match len { - Some(len) => super::SerializeValueArray::with_capacity(len), - None => super::SerializeValueArray::new(), + Some(len) => super::array::SerializeValueArray::with_capacity(len), + None => super::array::SerializeValueArray::new(), }; Ok(serializer) } @@ -222,13 +222,13 @@ impl serde::ser::Serializer for ValueSerializer { variant: &'static str, len: usize, ) -> Result { - Ok(super::SerializeTupleVariant::tuple(variant, len)) + Ok(super::map::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(), + Some(len) => super::map::SerializeMap::table_with_capacity(len), + None => super::map::SerializeMap::table(), }; Ok(serializer) } @@ -239,7 +239,7 @@ impl serde::ser::Serializer for ValueSerializer { len: usize, ) -> Result { if name == toml_datetime::__unstable::NAME { - Ok(super::SerializeMap::datetime()) + Ok(super::map::SerializeMap::datetime()) } else { self.serialize_map(Some(len)) } @@ -252,6 +252,6 @@ impl serde::ser::Serializer for ValueSerializer { variant: &'static str, len: usize, ) -> Result { - Ok(super::SerializeStructVariant::struct_(variant, len)) + Ok(super::map::SerializeStructVariant::struct_(variant, len)) } } diff --git a/crates/toml_write/src/value.rs b/crates/toml_write/src/value.rs index 8c27e271..bc0c8e3e 100644 --- a/crates/toml_write/src/value.rs +++ b/crates/toml_write/src/value.rs @@ -97,7 +97,19 @@ impl WriteTomlValue for i128 { impl WriteTomlValue for f32 { fn write_toml_value(&self, writer: &mut W) -> core::fmt::Result { - write!(writer, "{self}") + match (self.is_sign_negative(), self.is_nan(), *self == 0.0) { + (true, true, _) => write!(writer, "-nan"), + (false, true, _) => write!(writer, "nan"), + (true, false, true) => write!(writer, "-0.0"), + (false, false, true) => write!(writer, "0.0"), + (_, false, false) => { + if self % 1.0 == 0.0 { + write!(writer, "{self}.0") + } else { + write!(writer, "{self}") + } + } + } } } @@ -119,6 +131,14 @@ impl WriteTomlValue for f64 { } } +impl WriteTomlValue for char { + fn write_toml_value(&self, writer: &mut W) -> core::fmt::Result { + let mut buf = [0; 4]; + let v = self.encode_utf8(&mut buf); + v.write_toml_value(writer) + } +} + impl WriteTomlValue for str { fn write_toml_value(&self, writer: &mut W) -> core::fmt::Result { crate::TomlStringBuilder::new(self) diff --git a/crates/toml_write/src/write.rs b/crates/toml_write/src/write.rs index 26b58f4c..ffc4ee17 100644 --- a/crates/toml_write/src/write.rs +++ b/crates/toml_write/src/write.rs @@ -39,6 +39,22 @@ pub trait TomlWrite: core::fmt::Write { value.write_toml_key(self) } + ///
+ /// + /// For floats, this preserves the sign bit for [`f32::NAN`] / [`f64::NAN`] for the sake of + /// format-preserving editing. + /// However, in most cases the sign bit is indeterminate and outputting signed NANs can be a + /// cause of non-repeatable behavior. + /// + /// For general serialization, you should discard the sign bit. For example: + /// ``` + /// # let mut v = f64::NAN; + /// if v.is_nan() { + /// v = v.copysign(1.0); + /// } + /// ``` + /// + ///
fn value(&mut self, value: impl crate::WriteTomlValue) -> core::fmt::Result { value.write_toml_value(self) }