// SPDX-License-Identifier: Apache-2.0 use super::{Error, Value}; use alloc::{vec, vec::Vec}; use ::serde::ser::{self, SerializeMap as _, SerializeSeq as _, SerializeTupleVariant as _}; impl ser::Serialize for Value { #[inline] fn serialize(&self, serializer: S) -> Result { match self { Value::Bytes(x) => serializer.serialize_bytes(x), Value::Bool(x) => serializer.serialize_bool(*x), Value::Text(x) => serializer.serialize_str(x), Value::Null => serializer.serialize_unit(), Value::Tag(t, v) => { let mut acc = serializer.serialize_tuple_variant("@@TAG@@", 0, "@@TAGGED@@", 2)?; acc.serialize_field(t)?; acc.serialize_field(v)?; acc.end() } Value::Float(x) => { let y = *x as f32; if (y as f64).to_bits() == x.to_bits() { serializer.serialize_f32(y) } else { serializer.serialize_f64(*x) } } Value::Integer(x) => { if let Ok(x) = u8::try_from(*x) { serializer.serialize_u8(x) } else if let Ok(x) = i8::try_from(*x) { serializer.serialize_i8(x) } else if let Ok(x) = u16::try_from(*x) { serializer.serialize_u16(x) } else if let Ok(x) = i16::try_from(*x) { serializer.serialize_i16(x) } else if let Ok(x) = u32::try_from(*x) { serializer.serialize_u32(x) } else if let Ok(x) = i32::try_from(*x) { serializer.serialize_i32(x) } else if let Ok(x) = u64::try_from(*x) { serializer.serialize_u64(x) } else if let Ok(x) = i64::try_from(*x) { serializer.serialize_i64(x) } else if let Ok(x) = u128::try_from(*x) { serializer.serialize_u128(x) } else if let Ok(x) = i128::try_from(*x) { serializer.serialize_i128(x) } else { unreachable!() } } Value::Array(x) => { let mut map = serializer.serialize_seq(Some(x.len()))?; for v in x { map.serialize_element(v)?; } map.end() } Value::Map(x) => { let mut map = serializer.serialize_map(Some(x.len()))?; for (k, v) in x { map.serialize_entry(k, v)?; } map.end() } } } } macro_rules! mkserialize { ($($f:ident($v:ty)),+ $(,)?) => { $( #[inline] fn $f(self, v: $v) -> Result { Ok(v.into()) } )+ }; } struct Tagged { tag: Option, val: Option, } struct Named { name: &'static str, data: T, tag: Option, } struct Map { data: Vec<(Value, Value)>, temp: Option, } struct Serializer(T); impl ser::Serializer for Serializer<()> { type Ok = Value; type Error = Error; type SerializeSeq = Serializer>; type SerializeTuple = Serializer>; type SerializeTupleStruct = Serializer>; type SerializeTupleVariant = Serializer>>; type SerializeMap = Serializer; type SerializeStruct = Serializer>; type SerializeStructVariant = Serializer>>; mkserialize! { serialize_bool(bool), serialize_f32(f32), serialize_f64(f64), serialize_i8(i8), serialize_i16(i16), serialize_i32(i32), serialize_i64(i64), serialize_i128(i128), serialize_u8(u8), serialize_u16(u16), serialize_u32(u32), serialize_u64(u64), serialize_u128(u128), serialize_char(char), serialize_str(&str), serialize_bytes(&[u8]), } #[inline] fn serialize_none(self) -> Result { Ok(Value::Null) } #[inline] fn serialize_some(self, value: &U) -> Result { value.serialize(self) } #[inline] fn serialize_unit(self) -> Result { self.serialize_none() } #[inline] fn serialize_unit_struct(self, _name: &'static str) -> Result { self.serialize_unit() } #[inline] fn serialize_unit_variant( self, _name: &'static str, _index: u32, variant: &'static str, ) -> Result { Ok(variant.into()) } #[inline] fn serialize_newtype_struct( self, _name: &'static str, value: &U, ) -> Result { value.serialize(self) } #[inline] fn serialize_newtype_variant( self, name: &'static str, _index: u32, variant: &'static str, value: &U, ) -> Result { Ok(match (name, variant) { ("@@TAG@@", "@@UNTAGGED@@") => Value::serialized(value)?, _ => vec![(variant.into(), Value::serialized(value)?)].into(), }) } #[inline] fn serialize_seq(self, length: Option) -> Result { Ok(Serializer(Vec::with_capacity(length.unwrap_or(0)))) } #[inline] fn serialize_tuple(self, length: usize) -> Result { self.serialize_seq(Some(length)) } #[inline] fn serialize_tuple_struct( self, _name: &'static str, length: usize, ) -> Result { self.serialize_seq(Some(length)) } #[inline] fn serialize_tuple_variant( self, name: &'static str, _index: u32, variant: &'static str, length: usize, ) -> Result { Ok(Serializer(Named { name: variant, data: Vec::with_capacity(length), tag: match (name, variant) { ("@@TAG@@", "@@TAGGED@@") => Some(Tagged { tag: None, val: None, }), _ => None, }, })) } #[inline] fn serialize_map(self, length: Option) -> Result { Ok(Serializer(Map { data: Vec::with_capacity(length.unwrap_or(0)), temp: None, })) } #[inline] fn serialize_struct( self, _name: &'static str, length: usize, ) -> Result { Ok(Serializer(Vec::with_capacity(length))) } #[inline] fn serialize_struct_variant( self, _name: &'static str, _index: u32, variant: &'static str, length: usize, ) -> Result { Ok(Serializer(Named { name: variant, data: Vec::with_capacity(length), tag: None, })) } } impl ser::SerializeSeq for Serializer> { type Ok = Value; type Error = Error; #[inline] fn serialize_element(&mut self, value: &U) -> Result<(), Error> { self.0.push(Value::serialized(&value)?); Ok(()) } #[inline] fn end(self) -> Result { Ok(self.0.into()) } } impl ser::SerializeTuple for Serializer> { type Ok = Value; type Error = Error; #[inline] fn serialize_element(&mut self, value: &U) -> Result<(), Error> { self.0.push(Value::serialized(&value)?); Ok(()) } #[inline] fn end(self) -> Result { Ok(self.0.into()) } } impl ser::SerializeTupleStruct for Serializer> { type Ok = Value; type Error = Error; #[inline] fn serialize_field(&mut self, value: &U) -> Result<(), Error> { self.0.push(Value::serialized(&value)?); Ok(()) } #[inline] fn end(self) -> Result { Ok(self.0.into()) } } impl ser::SerializeTupleVariant for Serializer>> { type Ok = Value; type Error = Error; #[inline] fn serialize_field(&mut self, value: &U) -> Result<(), Error> { match self.0.tag.as_mut() { Some(tag) => match tag.tag { None => match value.serialize(crate::tag::Serializer) { Ok(t) => tag.tag = Some(t), Err(..) => return Err(ser::Error::custom("expected tag")), }, Some(..) => tag.val = Some(Value::serialized(value)?), }, None => self.0.data.push(Value::serialized(value)?), } Ok(()) } #[inline] fn end(self) -> Result { Ok(match self.0.tag { Some(tag) => match tag { Tagged { tag: Some(t), val: Some(v), } => Value::Tag(t, v.into()), _ => return Err(ser::Error::custom("invalid tag input")), }, None => vec![(self.0.name.into(), self.0.data.into())].into(), }) } } impl ser::SerializeMap for Serializer { type Ok = Value; type Error = Error; #[inline] fn serialize_key(&mut self, key: &U) -> Result<(), Error> { self.0.temp = Some(Value::serialized(key)?); Ok(()) } #[inline] fn serialize_value(&mut self, value: &U) -> Result<(), Error> { let key = self.0.temp.take().unwrap(); let val = Value::serialized(&value)?; self.0.data.push((key, val)); Ok(()) } #[inline] fn end(self) -> Result { Ok(self.0.data.into()) } } impl ser::SerializeStruct for Serializer> { type Ok = Value; type Error = Error; #[inline] fn serialize_field( &mut self, key: &'static str, value: &U, ) -> Result<(), Error> { let k = Value::serialized(&key)?; let v = Value::serialized(&value)?; self.0.push((k, v)); Ok(()) } #[inline] fn end(self) -> Result { Ok(self.0.into()) } } impl ser::SerializeStructVariant for Serializer>> { type Ok = Value; type Error = Error; #[inline] fn serialize_field( &mut self, key: &'static str, value: &U, ) -> Result<(), Self::Error> { let k = Value::serialized(&key)?; let v = Value::serialized(&value)?; self.0.data.push((k, v)); Ok(()) } #[inline] fn end(self) -> Result { Ok(vec![(self.0.name.into(), self.0.data.into())].into()) } } impl Value { /// Serializes an object into a `Value` #[inline] pub fn serialized(value: &T) -> Result { value.serialize(Serializer(())) } }