aboutsummaryrefslogtreecommitdiff
path: root/src/ser
diff options
context:
space:
mode:
Diffstat (limited to 'src/ser')
-rw-r--r--src/ser/map.rs271
-rw-r--r--src/ser/mod.rs5
-rw-r--r--src/ser/value.rs28
3 files changed, 288 insertions, 16 deletions
diff --git a/src/ser/map.rs b/src/ser/map.rs
index d743e3d..47e56ba 100644
--- a/src/ser/map.rs
+++ b/src/ser/map.rs
@@ -1,4 +1,4 @@
-use super::{Error, KeySerializer};
+use super::{Error, KeySerializer, SerializeValueArray, ValueSerializer};
#[doc(hidden)]
pub enum SerializeMap {
@@ -165,7 +165,6 @@ impl serde::ser::SerializeMap for SerializeInlineTable {
where
T: serde::ser::Serialize,
{
- self.key = None;
self.key = Some(input.serialize(KeySerializer)?);
Ok(())
}
@@ -174,7 +173,8 @@ impl serde::ser::SerializeMap for SerializeInlineTable {
where
T: serde::ser::Serialize,
{
- let res = value.serialize(super::ValueSerializer {});
+ let mut value_serializer = MapValueSerializer::new();
+ let res = value.serialize(&mut value_serializer);
match res {
Ok(item) => {
let key = self.key.take().unwrap();
@@ -185,7 +185,7 @@ impl serde::ser::SerializeMap for SerializeInlineTable {
self.items.insert(key, kv);
}
Err(e) => {
- if e != Error::UnsupportedNone {
+ if !(e == Error::UnsupportedNone && value_serializer.is_none) {
return Err(e);
}
}
@@ -210,7 +210,8 @@ impl serde::ser::SerializeStruct for SerializeInlineTable {
where
T: serde::ser::Serialize,
{
- let res = value.serialize(super::ValueSerializer {});
+ let mut value_serializer = MapValueSerializer::new();
+ let res = value.serialize(&mut value_serializer);
match res {
Ok(item) => {
let kv = crate::table::TableKeyValue::new(
@@ -220,7 +221,7 @@ impl serde::ser::SerializeStruct for SerializeInlineTable {
self.items.insert(crate::InternalString::from(key), kv);
}
Err(e) => {
- if e != Error::UnsupportedNone {
+ if !(e == Error::UnsupportedNone && value_serializer.is_none) {
return Err(e);
}
}
@@ -403,3 +404,261 @@ impl serde::ser::Serializer for DatetimeFieldSerializer {
Err(Error::DateInvalid)
}
}
+
+#[derive(Default)]
+struct MapValueSerializer {
+ is_none: bool,
+}
+
+impl MapValueSerializer {
+ fn new() -> Self {
+ Self { is_none: false }
+ }
+}
+
+impl serde::ser::Serializer for &mut MapValueSerializer {
+ 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<Self::Ok, Self::Error> {
+ ValueSerializer::new().serialize_bool(v)
+ }
+
+ fn serialize_i8(self, v: i8) -> Result<Self::Ok, Self::Error> {
+ ValueSerializer::new().serialize_i8(v)
+ }
+
+ fn serialize_i16(self, v: i16) -> Result<Self::Ok, Self::Error> {
+ ValueSerializer::new().serialize_i16(v)
+ }
+
+ fn serialize_i32(self, v: i32) -> Result<Self::Ok, Self::Error> {
+ ValueSerializer::new().serialize_i32(v)
+ }
+
+ fn serialize_i64(self, v: i64) -> Result<Self::Ok, Self::Error> {
+ ValueSerializer::new().serialize_i64(v)
+ }
+
+ fn serialize_u8(self, v: u8) -> Result<Self::Ok, Self::Error> {
+ ValueSerializer::new().serialize_u8(v)
+ }
+
+ fn serialize_u16(self, v: u16) -> Result<Self::Ok, Self::Error> {
+ ValueSerializer::new().serialize_u16(v)
+ }
+
+ fn serialize_u32(self, v: u32) -> Result<Self::Ok, Self::Error> {
+ ValueSerializer::new().serialize_u32(v)
+ }
+
+ fn serialize_u64(self, v: u64) -> Result<Self::Ok, Self::Error> {
+ ValueSerializer::new().serialize_u64(v)
+ }
+
+ fn serialize_f32(self, v: f32) -> Result<Self::Ok, Self::Error> {
+ ValueSerializer::new().serialize_f32(v)
+ }
+
+ fn serialize_f64(self, v: f64) -> Result<Self::Ok, Self::Error> {
+ ValueSerializer::new().serialize_f64(v)
+ }
+
+ fn serialize_char(self, v: char) -> Result<Self::Ok, Self::Error> {
+ ValueSerializer::new().serialize_char(v)
+ }
+
+ fn serialize_str(self, v: &str) -> Result<Self::Ok, Self::Error> {
+ ValueSerializer::new().serialize_str(v)
+ }
+
+ fn serialize_bytes(self, value: &[u8]) -> Result<Self::Ok, Self::Error> {
+ ValueSerializer::new().serialize_bytes(value)
+ }
+
+ fn serialize_none(self) -> Result<Self::Ok, Self::Error> {
+ self.is_none = true;
+ Err(Error::UnsupportedNone)
+ }
+
+ fn serialize_some<T: ?Sized>(self, value: &T) -> Result<Self::Ok, Self::Error>
+ where
+ T: serde::ser::Serialize,
+ {
+ ValueSerializer::new().serialize_some(value)
+ }
+
+ fn serialize_unit(self) -> Result<Self::Ok, Self::Error> {
+ ValueSerializer::new().serialize_unit()
+ }
+
+ fn serialize_unit_struct(self, name: &'static str) -> Result<Self::Ok, Self::Error> {
+ ValueSerializer::new().serialize_unit_struct(name)
+ }
+
+ fn serialize_unit_variant(
+ self,
+ name: &'static str,
+ variant_index: u32,
+ variant: &'static str,
+ ) -> Result<Self::Ok, Self::Error> {
+ ValueSerializer::new().serialize_unit_variant(name, variant_index, variant)
+ }
+
+ fn serialize_newtype_struct<T: ?Sized>(
+ self,
+ name: &'static str,
+ value: &T,
+ ) -> Result<Self::Ok, Self::Error>
+ where
+ T: serde::ser::Serialize,
+ {
+ ValueSerializer::new().serialize_newtype_struct(name, value)
+ }
+
+ fn serialize_newtype_variant<T: ?Sized>(
+ self,
+ name: &'static str,
+ variant_index: u32,
+ variant: &'static str,
+ value: &T,
+ ) -> Result<Self::Ok, Self::Error>
+ where
+ T: serde::ser::Serialize,
+ {
+ ValueSerializer::new().serialize_newtype_variant(name, variant_index, variant, value)
+ }
+
+ fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {
+ ValueSerializer::new().serialize_seq(len)
+ }
+
+ fn serialize_tuple(self, len: usize) -> Result<Self::SerializeTuple, Self::Error> {
+ ValueSerializer::new().serialize_tuple(len)
+ }
+
+ fn serialize_tuple_struct(
+ self,
+ name: &'static str,
+ len: usize,
+ ) -> Result<Self::SerializeTupleStruct, Self::Error> {
+ ValueSerializer::new().serialize_tuple_struct(name, len)
+ }
+
+ fn serialize_tuple_variant(
+ self,
+ name: &'static str,
+ variant_index: u32,
+ variant: &'static str,
+ len: usize,
+ ) -> Result<Self::SerializeTupleVariant, Self::Error> {
+ ValueSerializer::new().serialize_tuple_variant(name, variant_index, variant, len)
+ }
+
+ fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
+ ValueSerializer::new().serialize_map(len)
+ }
+
+ fn serialize_struct(
+ self,
+ name: &'static str,
+ len: usize,
+ ) -> Result<Self::SerializeStruct, Self::Error> {
+ ValueSerializer::new().serialize_struct(name, len)
+ }
+
+ fn serialize_struct_variant(
+ self,
+ name: &'static str,
+ variant_index: u32,
+ variant: &'static str,
+ len: usize,
+ ) -> Result<Self::SerializeStructVariant, Self::Error> {
+ ValueSerializer::new().serialize_struct_variant(name, variant_index, variant, len)
+ }
+}
+
+pub type SerializeTupleVariant = SerializeVariant<SerializeValueArray>;
+pub type SerializeStructVariant = SerializeVariant<SerializeMap>;
+
+pub struct SerializeVariant<T> {
+ variant: &'static str,
+ inner: T,
+}
+
+impl SerializeVariant<SerializeValueArray> {
+ pub(crate) fn tuple(variant: &'static str, len: usize) -> Self {
+ Self {
+ variant,
+ inner: SerializeValueArray::with_capacity(len),
+ }
+ }
+}
+
+impl SerializeVariant<SerializeMap> {
+ pub(crate) fn struct_(variant: &'static str, len: usize) -> Self {
+ Self {
+ variant,
+ inner: SerializeMap::table_with_capacity(len),
+ }
+ }
+}
+
+impl serde::ser::SerializeTupleVariant for SerializeVariant<SerializeValueArray> {
+ type Ok = crate::Value;
+ type Error = Error;
+
+ fn serialize_field<T: ?Sized>(&mut self, value: &T) -> Result<(), Error>
+ where
+ T: serde::ser::Serialize,
+ {
+ serde::ser::SerializeSeq::serialize_element(&mut self.inner, value)
+ }
+
+ fn end(self) -> Result<Self::Ok, Self::Error> {
+ let inner = serde::ser::SerializeSeq::end(self.inner)?;
+ let mut items = crate::table::KeyValuePairs::new();
+ let kv = crate::table::TableKeyValue::new(
+ crate::Key::new(self.variant),
+ crate::Item::Value(inner),
+ );
+ items.insert(crate::InternalString::from(self.variant), kv);
+ Ok(crate::Value::InlineTable(crate::InlineTable::with_pairs(
+ items,
+ )))
+ }
+}
+
+impl serde::ser::SerializeStructVariant for SerializeVariant<SerializeMap> {
+ type Ok = crate::Value;
+ type Error = Error;
+
+ #[inline]
+ fn serialize_field<T>(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error>
+ where
+ T: serde::ser::Serialize + ?Sized,
+ {
+ serde::ser::SerializeStruct::serialize_field(&mut self.inner, key, value)
+ }
+
+ #[inline]
+ fn end(self) -> Result<Self::Ok, Self::Error> {
+ let inner = serde::ser::SerializeStruct::end(self.inner)?;
+ let mut items = crate::table::KeyValuePairs::new();
+ let kv = crate::table::TableKeyValue::new(
+ crate::Key::new(self.variant),
+ crate::Item::Value(inner),
+ );
+ items.insert(crate::InternalString::from(self.variant), kv);
+ Ok(crate::Value::InlineTable(crate::InlineTable::with_pairs(
+ items,
+ )))
+ }
+}
diff --git a/src/ser/mod.rs b/src/ser/mod.rs
index 2c31020..ba31708 100644
--- a/src/ser/mod.rs
+++ b/src/ser/mod.rs
@@ -24,7 +24,7 @@ pub enum Error {
OutOfRange(Option<&'static str>),
/// `None` could not be serialized to TOML
UnsupportedNone,
- /// Key was not convertable to `String` for serializing to TOML
+ /// Key was not convertible to `String` for serializing to TOML
KeyNotString,
/// A serialized date was invalid
DateInvalid,
@@ -84,6 +84,7 @@ impl std::error::Error for Error {}
/// Serialization can fail if `T`'s implementation of `Serialize` decides to
/// fail, if `T` contains a map with non-string keys, or if `T` attempts to
/// serialize an unsupported datatype such as an enum, tuple, or tuple struct.
+#[cfg(feature = "display")]
pub fn to_vec<T: ?Sized>(value: &T) -> Result<Vec<u8>, Error>
where
T: serde::ser::Serialize,
@@ -127,6 +128,7 @@ where
/// let toml = toml_edit::ser::to_string(&config).unwrap();
/// println!("{}", toml)
/// ```
+#[cfg(feature = "display")]
pub fn to_string<T: ?Sized>(value: &T) -> Result<String, Error>
where
T: serde::ser::Serialize,
@@ -138,6 +140,7 @@ where
///
/// This is identical to `to_string` except the output string has a more
/// "pretty" output. See `ValueSerializer::pretty` for more details.
+#[cfg(feature = "display")]
pub fn to_string_pretty<T: ?Sized>(value: &T) -> Result<String, Error>
where
T: serde::ser::Serialize,
diff --git a/src/ser/value.rs b/src/ser/value.rs
index d29390a..47a17a3 100644
--- a/src/ser/value.rs
+++ b/src/ser/value.rs
@@ -60,10 +60,10 @@ impl serde::ser::Serializer for ValueSerializer {
type SerializeSeq = super::SerializeValueArray;
type SerializeTuple = super::SerializeValueArray;
type SerializeTupleStruct = super::SerializeValueArray;
- type SerializeTupleVariant = super::SerializeValueArray;
+ type SerializeTupleVariant = super::SerializeTupleVariant;
type SerializeMap = super::SerializeMap;
type SerializeStruct = super::SerializeMap;
- type SerializeStructVariant = serde::ser::Impossible<Self::Ok, Self::Error>;
+ type SerializeStructVariant = super::SerializeStructVariant;
fn serialize_bool(self, v: bool) -> Result<Self::Ok, Self::Error> {
Ok(v.into())
@@ -108,7 +108,17 @@ impl serde::ser::Serializer for ValueSerializer {
self.serialize_f64(v as f64)
}
- fn serialize_f64(self, v: f64) -> Result<Self::Ok, Self::Error> {
+ fn serialize_f64(self, mut v: f64) -> Result<Self::Ok, Self::Error> {
+ // 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())
}
@@ -205,10 +215,10 @@ impl serde::ser::Serializer for ValueSerializer {
self,
_name: &'static str,
_variant_index: u32,
- _variant: &'static str,
+ variant: &'static str,
len: usize,
) -> Result<Self::SerializeTupleVariant, Self::Error> {
- self.serialize_seq(Some(len))
+ Ok(super::SerializeTupleVariant::tuple(variant, len))
}
fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {
@@ -233,11 +243,11 @@ impl serde::ser::Serializer for ValueSerializer {
fn serialize_struct_variant(
self,
- name: &'static str,
+ _name: &'static str,
_variant_index: u32,
- _variant: &'static str,
- _len: usize,
+ variant: &'static str,
+ len: usize,
) -> Result<Self::SerializeStructVariant, Self::Error> {
- Err(Error::UnsupportedType(Some(name)))
+ Ok(super::SerializeStructVariant::struct_(variant, len))
}
}