diff --git a/duper/src/ast.rs b/duper/src/ast.rs index b3f902d..b09147c 100644 --- a/duper/src/ast.rs +++ b/duper/src/ast.rs @@ -4,7 +4,7 @@ use crate::visitor::DuperVisitor; #[derive(Debug, Clone)] pub struct DuperValue<'a> { - pub identifier: Option<&'a str>, + pub identifier: Option>, pub inner: DuperInner<'a>, } diff --git a/duper/src/builder.rs b/duper/src/builder.rs index d574baa..079c190 100644 --- a/duper/src/builder.rs +++ b/duper/src/builder.rs @@ -1,7 +1,7 @@ use std::borrow::Cow; use json_escape::explicit::unescape; -use pest::{Parser as _, error::Error, iterators::Pair}; +use pest::{error::Error, iterators::Pair}; use crate::{ ast::{DuperInner, DuperValue}, @@ -30,7 +30,7 @@ impl DuperBuilder { Rule::identifier => { let identifier = next.as_str(); next = duper_trunk.next().unwrap(); - Some(identifier) + Some(Cow::Borrowed(identifier)) } _ => None, }; @@ -85,7 +85,7 @@ impl DuperBuilder { Rule::identifier => { let identifier = next.as_str(); next = inner_pair.next().unwrap(); - Some(identifier) + Some(Cow::Borrowed(identifier)) } _ => None, }; diff --git a/duper/src/serializer.rs b/duper/src/serializer.rs index 4547900..23bdc3f 100644 --- a/duper/src/serializer.rs +++ b/duper/src/serializer.rs @@ -25,14 +25,14 @@ impl DuperVisitor for DuperSerializer { fn visit_object<'a>( &mut self, - identifier: Option<&'a str>, + identifier: Option>, object: Vec<(Cow<'a, str>, DuperValue<'a>)>, ) -> Self::Value { let mut string = String::new(); let len = object.len(); if let Some(identifier) = identifier { - string.push_str(identifier); + string.push_str(identifier.as_ref()); string.push_str("({"); for (i, (key, value)) in object.into_iter().enumerate() { string.push_str(&format_key(key)); @@ -61,14 +61,14 @@ impl DuperVisitor for DuperSerializer { fn visit_array<'a>( &mut self, - identifier: Option<&str>, + identifier: Option>, array: Vec>, ) -> Self::Value { let mut string = String::new(); let len = array.len(); if let Some(identifier) = identifier { - string.push_str(identifier); + string.push_str(identifier.as_ref()); string.push_str("(["); for (i, value) in array.into_iter().enumerate() { string.push_str(&value.accept(self)); @@ -91,7 +91,11 @@ impl DuperVisitor for DuperSerializer { string } - fn visit_string<'a>(&mut self, identifier: Option<&str>, value: Cow<'a, str>) -> Self::Value { + fn visit_string<'a>( + &mut self, + identifier: Option>, + value: Cow<'a, str>, + ) -> Self::Value { if let Some(identifier) = identifier { let value = format_string(value); format!("{identifier}({value})") @@ -100,7 +104,11 @@ impl DuperVisitor for DuperSerializer { } } - fn visit_bytes<'a>(&mut self, identifier: Option<&str>, bytes: Cow<'a, [u8]>) -> Self::Value { + fn visit_bytes<'a>( + &mut self, + identifier: Option>, + bytes: Cow<'a, [u8]>, + ) -> Self::Value { if let Some(identifier) = identifier { let bytes = format_bytes(bytes); format!("{identifier}({bytes})") @@ -109,25 +117,25 @@ impl DuperVisitor for DuperSerializer { } } - fn visit_integer(&mut self, identifier: Option<&str>, integer: i64) -> Self::Value { + fn visit_integer(&mut self, identifier: Option>, integer: i64) -> Self::Value { if let Some(identifier) = identifier { - let value = format_integer(integer, identifier.try_into().ok()); + let value = format_integer(integer, identifier.as_ref().try_into().ok()); format!("{identifier}({value})") } else { format_integer(integer, None) } } - fn visit_float(&mut self, identifier: Option<&str>, float: f64) -> Self::Value { + fn visit_float(&mut self, identifier: Option>, float: f64) -> Self::Value { if let Some(identifier) = identifier { - let value = format_float(float, identifier.try_into().ok()); + let value = format_float(float, identifier.as_ref().try_into().ok()); format!("{identifier}({value})") } else { format_float(float, None) } } - fn visit_boolean(&mut self, identifier: Option<&str>, boolean: bool) -> Self::Value { + fn visit_boolean(&mut self, identifier: Option>, boolean: bool) -> Self::Value { if let Some(identifier) = identifier { let value = format_boolean(boolean); format!("{identifier}({value})") @@ -136,7 +144,7 @@ impl DuperVisitor for DuperSerializer { } } - fn visit_null(&mut self, identifier: Option<&str>) -> Self::Value { + fn visit_null(&mut self, identifier: Option>) -> Self::Value { if let Some(identifier) = identifier { format!("{identifier}(null)") } else { diff --git a/duper/src/visitor.rs b/duper/src/visitor.rs index 429dcfa..65a87e3 100644 --- a/duper/src/visitor.rs +++ b/duper/src/visitor.rs @@ -7,23 +7,27 @@ pub trait DuperVisitor { fn visit_object<'a>( &mut self, - identifier: Option<&'a str>, + identifier: Option>, object: Vec<(Cow<'a, str>, DuperValue<'a>)>, ) -> Self::Value; fn visit_array<'a>( &mut self, - identifier: Option<&'a str>, + identifier: Option>, array: Vec>, ) -> Self::Value; fn visit_string<'a>( &mut self, - identifier: Option<&'a str>, + identifier: Option>, string: Cow<'a, str>, ) -> Self::Value; - fn visit_bytes<'a>(&mut self, identifier: Option<&'a str>, bytes: Cow<'a, [u8]>) + fn visit_bytes<'a>( + &mut self, + identifier: Option>, + bytes: Cow<'a, [u8]>, + ) -> Self::Value; + fn visit_integer<'a>(&mut self, identifier: Option>, integer: i64) -> Self::Value; + fn visit_float<'a>(&mut self, identifier: Option>, float: f64) -> Self::Value; + fn visit_boolean<'a>(&mut self, identifier: Option>, boolean: bool) -> Self::Value; - fn visit_integer<'a>(&mut self, identifier: Option<&'a str>, integer: i64) -> Self::Value; - fn visit_float<'a>(&mut self, identifier: Option<&'a str>, float: f64) -> Self::Value; - fn visit_boolean<'a>(&mut self, identifier: Option<&'a str>, boolean: bool) -> Self::Value; - fn visit_null<'a>(&mut self, identifier: Option<&'a str>) -> Self::Value; + fn visit_null<'a>(&mut self, identifier: Option>) -> Self::Value; } diff --git a/serde_duper/Cargo.toml b/serde_duper/Cargo.toml new file mode 100644 index 0000000..8ed26bb --- /dev/null +++ b/serde_duper/Cargo.toml @@ -0,0 +1,8 @@ +[package] +name = "serde_duper" +version = "0.1.0" +edition = "2024" + +[dependencies] +serde_core = "1.0.228" +duper = { path = "../duper" } diff --git a/serde_duper/src/deserializer.rs b/serde_duper/src/deserializer.rs new file mode 100644 index 0000000..a0e8bb5 --- /dev/null +++ b/serde_duper/src/deserializer.rs @@ -0,0 +1,495 @@ +use std::borrow::Cow; + +use duper::{DuperInner, DuperParser, DuperValue}; +use serde_core::Deserialize; +use serde_core::de::{self, DeserializeSeed, IntoDeserializer, Visitor}; + +pub struct Deserializer<'de> { + value: Option>, +} + +impl<'de> Deserializer<'de> { + pub fn from_str(input: &'de str) -> Result { + let value = DuperParser::parse_duper(input).map_err(|e| format!("Parse error: {e:?}"))?; + Ok(Self { value: Some(value) }) + } + + pub fn from_value(value: DuperValue<'de>) -> Self { + Self { value: Some(value) } + } +} + +pub fn from_str<'a, T>(input: &'a str) -> Result +where + T: Deserialize<'a>, +{ + let mut deserializer = Deserializer::from_str(input)?; + let t = + T::deserialize(&mut deserializer).map_err(|e| format!("Deserialization error: {e:?}"))?; + Ok(t) +} + +pub fn from_value<'a, T>(value: DuperValue<'a>) -> Result +where + T: Deserialize<'a>, +{ + let mut deserializer = Deserializer::from_value(value); + let t = + T::deserialize(&mut deserializer).map_err(|e| format!("Deserialization error: {e:?}"))?; + Ok(t) +} + +impl<'de, 'a> de::Deserializer<'de> for &'a mut Deserializer<'de> { + type Error = de::value::Error; + + // --- Deserialize DuperValue --- + + fn deserialize_any(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self.value.take() { + Some(DuperValue { + inner: DuperInner::Object(object), + .. + }) => { + let map = MapDeserializer::new(object); + visitor.visit_map(map) + } + Some(DuperValue { + inner: DuperInner::Array(array), + .. + }) => { + let seq = SequenceDeserializer::new(array); + visitor.visit_seq(seq) + } + Some(DuperValue { + inner: DuperInner::String(string), + .. + }) => visitor.visit_str(&string), + Some(DuperValue { + inner: DuperInner::Bytes(bytes), + .. + }) => visitor.visit_bytes(&bytes), + Some(DuperValue { + inner: DuperInner::Integer(integer), + .. + }) => visitor.visit_i64(integer), + Some(DuperValue { + inner: DuperInner::Float(float), + .. + }) => visitor.visit_f64(float), + Some(DuperValue { + inner: DuperInner::Boolean(boolean), + .. + }) => visitor.visit_bool(boolean), + Some(DuperValue { + inner: DuperInner::Null, + .. + }) => visitor.visit_none(), + None => Err(de::Error::custom("already consumed deserializer value")), + } + } + + // --- Known values --- + + fn deserialize_bool(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_any(visitor) + } + + fn deserialize_i64(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_any(visitor) + } + + fn deserialize_f64(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_any(visitor) + } + + fn deserialize_str(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_any(visitor) + } + + fn deserialize_bytes(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_any(visitor) + } + + fn deserialize_option(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self.value.take() { + Some(DuperValue { + inner: DuperInner::Null, + .. + }) + | None => visitor.visit_none(), + value => { + self.value = value; + visitor.visit_some(self) + } + } + } + + fn deserialize_newtype_struct( + self, + _name: &'static str, + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + visitor.visit_newtype_struct(self) + } + + fn deserialize_seq(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_any(visitor) + } + + fn deserialize_tuple(self, _len: usize, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_seq(visitor) + } + + fn deserialize_tuple_struct( + self, + _name: &'static str, + _len: usize, + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + self.deserialize_seq(visitor) + } + + fn deserialize_map(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_any(visitor) + } + + fn deserialize_struct( + self, + _name: &'static str, + _fields: &'static [&'static str], + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + self.deserialize_map(visitor) + } + + fn deserialize_enum( + self, + _name: &'static str, + _variants: &'static [&'static str], + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + match self.value.take() { + Some(DuperValue { + inner: DuperInner::String(string), + .. + }) => visitor.visit_enum(string.into_deserializer()), + Some(DuperValue { + inner: DuperInner::Object(mut object), + .. + }) if object.len() == 1 => { + let pair = object.remove(0); + visitor.visit_enum(EnumDeserializer { + variant: pair.0, + value: pair.1, + }) + } + value => Err(de::Error::custom(format!( + "expected string or single-keyed object for enum, found {:?}", + value + ))), + } + } + + fn deserialize_identifier(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_str(visitor) + } + + // --- Others --- + + fn deserialize_i8(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_i64(visitor) + } + + fn deserialize_i16(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_i64(visitor) + } + + fn deserialize_i32(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_i64(visitor) + } + + fn deserialize_u8(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_i64(visitor) + } + + fn deserialize_u16(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_i64(visitor) + } + + fn deserialize_u32(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_i64(visitor) + } + + fn deserialize_u64(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_i64(visitor) + } + + fn deserialize_f32(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_f64(visitor) + } + + fn deserialize_char(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_str(visitor) + } + + fn deserialize_string(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_str(visitor) + } + + fn deserialize_byte_buf(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_bytes(visitor) + } + + fn deserialize_unit(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + visitor.visit_unit() + } + + fn deserialize_unit_struct( + self, + _name: &'static str, + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + self.deserialize_unit(visitor) + } + + fn deserialize_ignored_any(self, visitor: V) -> Result + where + V: Visitor<'de>, + { + self.deserialize_any(visitor) + } +} + +struct SequenceDeserializer<'de> { + iter: std::vec::IntoIter>, +} + +impl<'de> SequenceDeserializer<'de> { + fn new(vec: Vec>) -> Self { + Self { + iter: vec.into_iter(), + } + } +} + +impl<'de> de::SeqAccess<'de> for SequenceDeserializer<'de> { + type Error = de::value::Error; + + fn next_element_seed(&mut self, seed: T) -> Result, Self::Error> + where + T: DeserializeSeed<'de>, + { + match self.iter.next() { + Some(value) => seed + .deserialize(&mut Deserializer::from_value(value)) + .map(Some), + None => Ok(None), + } + } +} + +struct MapDeserializer<'de> { + iter: std::vec::IntoIter<(Cow<'de, str>, DuperValue<'de>)>, + value: Option>, +} + +impl<'de> MapDeserializer<'de> { + fn new(vec: Vec<(Cow<'de, str>, DuperValue<'de>)>) -> Self { + Self { + iter: vec.into_iter(), + value: None, + } + } +} + +impl<'de> de::MapAccess<'de> for MapDeserializer<'de> { + type Error = de::value::Error; + + fn next_key_seed(&mut self, seed: K) -> Result, Self::Error> + where + K: DeserializeSeed<'de>, + { + match self.iter.next() { + Some((key, value)) => { + self.value = Some(value); + seed.deserialize(key.into_deserializer()).map(Some) + } + None => Ok(None), + } + } + + fn next_value_seed(&mut self, seed: V) -> Result + where + V: DeserializeSeed<'de>, + { + match self.value.take() { + Some(value) => seed.deserialize(&mut Deserializer::from_value(value)), + None => Err(de::Error::custom("value is missing")), + } + } +} + +struct EnumDeserializer<'de> { + variant: Cow<'de, str>, + value: DuperValue<'de>, +} + +impl<'de> de::EnumAccess<'de> for EnumDeserializer<'de> { + type Error = de::value::Error; + type Variant = VariantDeserializer<'de>; + + fn variant_seed(self, seed: V) -> Result<(V::Value, Self::Variant), Self::Error> + where + V: DeserializeSeed<'de>, + { + let variant = seed.deserialize(self.variant.into_deserializer())?; + Ok(( + variant, + VariantDeserializer { + value: Some(self.value), + }, + )) + } +} + +struct VariantDeserializer<'de> { + value: Option>, +} + +impl<'de> de::VariantAccess<'de> for VariantDeserializer<'de> { + type Error = de::value::Error; + + fn unit_variant(self) -> Result<(), Self::Error> { + match self.value.map(|value| value.inner) { + Some(DuperInner::Null) => Ok(()), + Some(_) => Err(de::Error::custom("expected null for unit variant")), + None => Ok(()), + } + } + + fn newtype_variant_seed(self, seed: T) -> Result + where + T: DeserializeSeed<'de>, + { + match self.value { + Some(value) => seed.deserialize(&mut Deserializer::from_value(value)), + None => Err(de::Error::custom("expected value for newtype variant")), + } + } + + fn tuple_variant(self, _len: usize, visitor: V) -> Result + where + V: Visitor<'de>, + { + match self.value.map(|value| value.inner) { + Some(DuperInner::Array(vec)) => { + let seq = SequenceDeserializer::new(vec); + visitor.visit_seq(seq) + } + Some(_) => Err(de::Error::custom("expected array for tuple variant")), + None => Err(de::Error::custom("expected value for tuple variant")), + } + } + + fn struct_variant( + self, + _fields: &'static [&'static str], + visitor: V, + ) -> Result + where + V: Visitor<'de>, + { + match self.value.map(|value| value.inner) { + Some(DuperInner::Object(obj)) => { + let map = MapDeserializer::new(obj); + visitor.visit_map(map) + } + Some(_) => Err(de::Error::custom("expected object for struct variant")), + None => Err(de::Error::custom("expected value for struct variant")), + } + } +} diff --git a/serde_duper/src/error.rs b/serde_duper/src/error.rs new file mode 100644 index 0000000..2dad98a --- /dev/null +++ b/serde_duper/src/error.rs @@ -0,0 +1,74 @@ +use std::fmt::{self, Display}; + +#[derive(Debug, Clone)] +pub enum ErrorKind { + SerializationError, + InvalidValue, + UnsupportedType, + Custom(String), +} + +#[derive(Debug, Clone)] +struct ErrorImpl { + kind: ErrorKind, + message: String, +} + +#[derive(Debug, Clone)] +pub struct Error { + inner: Box, +} + +impl Error { + pub fn new(kind: ErrorKind, message: impl Into) -> Self { + Self { + inner: Box::new(ErrorImpl { + kind, + message: message.into(), + }), + } + } + + pub fn custom(msg: impl Into + Clone) -> Self { + Self::new(ErrorKind::Custom(msg.clone().into()), msg) + } + + pub fn serialization(msg: impl Into) -> Self { + Self::new(ErrorKind::SerializationError, msg) + } + + pub fn invalid_value(msg: impl Into) -> Self { + Self::new(ErrorKind::InvalidValue, msg) + } + + pub fn unsupported_type(msg: impl Into) -> Self { + Self::new(ErrorKind::UnsupportedType, msg) + } +} + +impl Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!( + f, + "{}: {}", + match self.inner.kind { + ErrorKind::SerializationError => "SerializationError", + ErrorKind::InvalidValue => "InvalidValue", + ErrorKind::UnsupportedType => "UnsupportedType", + ErrorKind::Custom(_) => "Custom", + }, + self.inner.message + ) + } +} + +impl std::error::Error for Error {} + +impl serde_core::ser::Error for Error { + fn custom(msg: T) -> Self + where + T: Display, + { + Self::custom(msg.to_string()) + } +} diff --git a/serde_duper/src/lib.rs b/serde_duper/src/lib.rs new file mode 100644 index 0000000..4da6974 --- /dev/null +++ b/serde_duper/src/lib.rs @@ -0,0 +1,7 @@ +mod deserializer; +mod error; +mod serializer; + +pub use deserializer::{Deserializer, from_str, from_value}; +pub use error::Error; +pub use serializer::{to_duper, to_string}; diff --git a/serde_duper/src/serializer.rs b/serde_duper/src/serializer.rs new file mode 100644 index 0000000..71e996f --- /dev/null +++ b/serde_duper/src/serializer.rs @@ -0,0 +1,533 @@ +use std::{borrow::Cow, marker::PhantomData}; + +use duper::{DuperInner, DuperSerializer, DuperValue}; +use serde_core::{Serialize, ser}; + +use crate::Error; + +#[derive(Clone)] +pub struct Serializer<'a> { + _phantom: PhantomData>, +} + +impl<'a> Serializer<'a> { + fn new() -> Self { + Self { + _phantom: Default::default(), + } + } +} + +pub fn to_string(value: &T) -> Result +where + T: Serialize, +{ + let mut serializer = Serializer::new(); + let value = value + .serialize(&mut serializer) + .map_err(|e| format!("Serialization error: {e:?}"))?; + Ok(DuperSerializer::new().serialize(value)) +} + +pub fn to_duper<'a, T>(value: &'a T) -> Result, String> +where + T: Serialize, +{ + let mut serializer = Serializer::new(); + let value = value + .serialize(&mut serializer) + .map_err(|e| format!("Serialization error: {e:?}"))?; + Ok(value) +} + +pub struct SerializeSeq<'a, 'b> { + serializer: &'a mut Serializer<'b>, + elements: Vec>, +} + +pub struct SerializeTuple<'a, 'b> { + serializer: &'a mut Serializer<'b>, + elements: Vec>, +} + +pub struct SerializeTupleStruct<'a, 'b> { + serializer: &'a mut Serializer<'b>, + name: &'static str, + elements: Vec>, +} + +pub struct SerializeTupleVariant<'a, 'b> { + serializer: &'a mut Serializer<'b>, + name: &'static str, + variant: &'static str, + elements: Vec>, +} + +pub struct SerializeMap<'a, 'b> { + serializer: &'a mut Serializer<'b>, + entries: Vec<(Cow<'b, str>, DuperValue<'b>)>, + next_key: Option>, +} + +pub struct SerializeStruct<'a, 'b> { + serializer: &'a mut Serializer<'b>, + name: &'static str, + fields: Vec<(Cow<'b, str>, DuperValue<'b>)>, +} + +pub struct SerializeStructVariant<'a, 'b> { + serializer: &'a mut Serializer<'b>, + name: &'static str, + variant: &'static str, + fields: Vec<(Cow<'b, str>, DuperValue<'b>)>, +} + +impl<'a, 'b> ser::Serializer for &'a mut Serializer<'b> { + type Ok = DuperValue<'b>; + + type Error = Error; + + type SerializeSeq = SerializeSeq<'a, 'b>; + type SerializeTuple = SerializeTuple<'a, 'b>; + type SerializeTupleStruct = SerializeTupleStruct<'a, 'b>; + type SerializeTupleVariant = SerializeTupleVariant<'a, 'b>; + type SerializeMap = SerializeMap<'a, 'b>; + type SerializeStruct = SerializeStruct<'a, 'b>; + type SerializeStructVariant = SerializeStructVariant<'a, 'b>; + + fn serialize_bool(self, v: bool) -> Result { + Ok(DuperValue { + identifier: None, + inner: DuperInner::Boolean(v), + }) + } + + fn serialize_i8(self, v: i8) -> Result { + Ok(DuperValue { + identifier: None, + inner: DuperInner::Integer(v.into()), + }) + } + + fn serialize_i16(self, v: i16) -> Result { + Ok(DuperValue { + identifier: None, + inner: DuperInner::Integer(v.into()), + }) + } + + fn serialize_i32(self, v: i32) -> Result { + Ok(DuperValue { + identifier: None, + inner: DuperInner::Integer(v.into()), + }) + } + + fn serialize_i64(self, v: i64) -> Result { + Ok(DuperValue { + identifier: None, + inner: DuperInner::Integer(v), + }) + } + + fn serialize_u8(self, v: u8) -> Result { + Ok(DuperValue { + identifier: None, + inner: DuperInner::Integer(v.into()), + }) + } + + fn serialize_u16(self, v: u16) -> Result { + Ok(DuperValue { + identifier: None, + inner: DuperInner::Integer(v.into()), + }) + } + + fn serialize_u32(self, v: u32) -> Result { + Ok(DuperValue { + identifier: None, + inner: DuperInner::Integer(v.into()), + }) + } + + fn serialize_u64(self, v: u64) -> Result { + Ok(DuperValue { + identifier: None, + inner: DuperInner::Integer( + v.try_into() + .map_err(|_| Error::invalid_value("integer must fit in i64"))?, + ), + }) + } + + fn serialize_f32(self, v: f32) -> Result { + Ok(DuperValue { + identifier: None, + inner: DuperInner::Float(v.into()), + }) + } + + fn serialize_f64(self, v: f64) -> Result { + Ok(DuperValue { + identifier: None, + inner: DuperInner::Float(v), + }) + } + + fn serialize_char(self, v: char) -> Result { + Ok(DuperValue { + identifier: None, + inner: DuperInner::String(Cow::Owned(v.into())), + }) + } + + fn serialize_str(self, v: &str) -> Result { + Ok(DuperValue { + identifier: None, + inner: DuperInner::String(Cow::Owned(v.into())), + }) + } + + fn serialize_bytes(self, v: &[u8]) -> Result { + Ok(DuperValue { + identifier: None, + inner: DuperInner::Bytes(Cow::Owned(v.into())), + }) + } + + fn serialize_none(self) -> Result { + Ok(DuperValue { + identifier: None, + inner: DuperInner::Null, + }) + } + + fn serialize_some(self, value: &T) -> Result + where + T: ?Sized + Serialize, + { + value.serialize(self) + } + + fn serialize_unit(self) -> Result { + Ok(DuperValue { + identifier: None, + inner: DuperInner::Null, + }) + } + + fn serialize_unit_struct(self, name: &'static str) -> Result { + Ok(DuperValue { + // TO-DO + identifier: Some(Cow::Owned(format!("X-{name}"))), + inner: DuperInner::Null, + }) + } + + fn serialize_unit_variant( + self, + name: &'static str, + _variant_index: u32, + variant: &'static str, + ) -> Result { + Ok(DuperValue { + // TO-DO + identifier: Some(Cow::Owned(format!("X-{name}"))), + inner: DuperInner::String(Cow::Borrowed(variant)), + }) + } + + fn serialize_newtype_struct( + self, + name: &'static str, + value: &T, + ) -> Result + where + T: ?Sized + Serialize, + { + let value = value.serialize(self)?; + Ok(DuperValue { + // TO-DO + identifier: Some(Cow::Owned(format!("X-{name}"))), + inner: value.inner, + }) + } + + fn serialize_newtype_variant( + self, + name: &'static str, + _variant_index: u32, + _variant: &'static str, + value: &T, + ) -> Result + where + T: ?Sized + Serialize, + { + let value = value.serialize(self)?; + Ok(DuperValue { + // TO-DO + identifier: Some(Cow::Owned(format!("X-{name}"))), + inner: value.inner, + }) + } + + fn serialize_seq(self, len: Option) -> Result { + Ok(Self::SerializeSeq { + serializer: self, + elements: len.map(|len| Vec::with_capacity(len)).unwrap_or(Vec::new()), + }) + } + + fn serialize_tuple(self, len: usize) -> Result { + Ok(Self::SerializeTuple { + serializer: self, + elements: Vec::with_capacity(len), + }) + } + + fn serialize_tuple_struct( + self, + name: &'static str, + len: usize, + ) -> Result { + Ok(Self::SerializeTupleStruct { + serializer: self, + name, + elements: Vec::with_capacity(len), + }) + } + + fn serialize_tuple_variant( + self, + name: &'static str, + _variant_index: u32, + variant: &'static str, + len: usize, + ) -> Result { + Ok(Self::SerializeTupleVariant { + serializer: self, + name, + variant, + elements: Vec::with_capacity(len), + }) + } + + fn serialize_map(self, len: Option) -> Result { + Ok(Self::SerializeMap { + serializer: self, + entries: len.map(|len| Vec::with_capacity(len)).unwrap_or(Vec::new()), + next_key: None, + }) + } + + fn serialize_struct( + self, + name: &'static str, + len: usize, + ) -> Result { + Ok(Self::SerializeStruct { + serializer: self, + name, + fields: Vec::with_capacity(len), + }) + } + + fn serialize_struct_variant( + self, + name: &'static str, + _variant_index: u32, + variant: &'static str, + len: usize, + ) -> Result { + Ok(Self::SerializeStructVariant { + serializer: self, + name, + variant, + fields: Vec::with_capacity(len), + }) + } +} + +impl<'a, 'b> ser::SerializeSeq for SerializeSeq<'a, 'b> { + type Ok = DuperValue<'b>; + type Error = Error; + + fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> + where + T: ?Sized + Serialize, + { + let value = value.serialize(&mut *self.serializer)?; + self.elements.push(value); + Ok(()) + } + + fn end(self) -> Result { + Ok(DuperValue { + identifier: None, + inner: DuperInner::Array(self.elements), + }) + } +} + +impl<'a, 'b> ser::SerializeTuple for SerializeTuple<'a, 'b> { + type Ok = DuperValue<'b>; + type Error = Error; + + fn serialize_element(&mut self, value: &T) -> Result<(), Self::Error> + where + T: ?Sized + Serialize, + { + let value = value.serialize(&mut *self.serializer)?; + self.elements.push(value); + Ok(()) + } + + fn end(self) -> Result { + Ok(DuperValue { + identifier: None, + inner: DuperInner::Array(self.elements), + }) + } +} + +impl<'a, 'b> ser::SerializeTupleStruct for SerializeTupleStruct<'a, 'b> { + type Ok = DuperValue<'b>; + type Error = Error; + + fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> + where + T: ?Sized + Serialize, + { + let value = value.serialize(&mut *self.serializer)?; + self.elements.push(value); + Ok(()) + } + + fn end(self) -> Result { + Ok(DuperValue { + identifier: Some(Cow::Owned(format!("X-{}", self.name))), + inner: DuperInner::Array(self.elements), + }) + } +} + +impl<'a, 'b> ser::SerializeTupleVariant for SerializeTupleVariant<'a, 'b> { + type Ok = DuperValue<'b>; + type Error = Error; + + fn serialize_field(&mut self, value: &T) -> Result<(), Self::Error> + where + T: ?Sized + Serialize, + { + let value = value.serialize(&mut *self.serializer)?; + self.elements.push(value); + Ok(()) + } + + fn end(self) -> Result { + let mut fields = Vec::new(); + fields.push(( + Cow::Borrowed(self.variant), + DuperValue { + identifier: None, + inner: DuperInner::Array(self.elements), + }, + )); + + Ok(DuperValue { + identifier: Some(Cow::Owned(format!("X-{}", self.name))), + inner: DuperInner::Object(fields), + }) + } +} + +impl<'a, 'b> ser::SerializeMap for SerializeMap<'a, 'b> { + type Ok = DuperValue<'b>; + type Error = Error; + + fn serialize_key(&mut self, key: &T) -> Result<(), Self::Error> + where + T: ?Sized + Serialize, + { + let key_value = key.serialize(&mut *self.serializer)?; + match key_value.inner { + DuperInner::String(s) => { + self.next_key = Some(s); + Ok(()) + } + _ => Err(Error::invalid_value("map key must be a string")), + } + } + + fn serialize_value(&mut self, value: &T) -> Result<(), Self::Error> + where + T: ?Sized + Serialize, + { + if let Some(key) = self.next_key.take() { + let value = value.serialize(&mut *self.serializer)?; + self.entries.push((key, value)); + Ok(()) + } else { + Err(Error::custom("serialize_value called before serialize_key")) + } + } + + fn end(self) -> Result { + Ok(DuperValue { + identifier: None, + inner: DuperInner::Object(self.entries), + }) + } +} + +impl<'a, 'b> ser::SerializeStruct for SerializeStruct<'a, 'b> { + type Ok = DuperValue<'b>; + type Error = Error; + + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> + where + T: ?Sized + Serialize, + { + let value = value.serialize(&mut *self.serializer)?; + self.fields.push((Cow::Borrowed(key), value)); + Ok(()) + } + + fn end(self) -> Result { + Ok(DuperValue { + identifier: Some(Cow::Owned(format!("X-{}", self.name))), + inner: DuperInner::Object(self.fields), + }) + } +} + +impl<'a, 'b> ser::SerializeStructVariant for SerializeStructVariant<'a, 'b> { + type Ok = DuperValue<'b>; + type Error = Error; + + fn serialize_field(&mut self, key: &'static str, value: &T) -> Result<(), Self::Error> + where + T: ?Sized + Serialize, + { + let value = value.serialize(&mut *self.serializer)?; + self.fields.push((Cow::Borrowed(key), value)); + Ok(()) + } + + fn end(self) -> Result { + let mut variant_obj = Vec::new(); + variant_obj.push(( + Cow::Borrowed(self.variant), + DuperValue { + identifier: None, + inner: DuperInner::Object(self.fields), + }, + )); + + Ok(DuperValue { + identifier: Some(Cow::Owned(format!("X-{}", self.name))), + inner: DuperInner::Object(variant_obj), + }) + } +}