diff --git a/src/de/mod.rs b/src/de/mod.rs index 7a7e93e4e..ab0eb058e 100644 --- a/src/de/mod.rs +++ b/src/de/mod.rs @@ -527,22 +527,7 @@ impl<'a, 'de> de::Deserializer<'de> for &'a mut Deserializer<'de> { self.deserialize_seq(visitor) } - /// Unsupported. Can’t make an arbitrary-sized map in no-std. Use a struct with a - /// known format, or implement a custom map deserializer / visitor: - /// https://serde.rs/deserialize-map.html - fn deserialize_map(self, _visitor: V) -> Result - where - V: Visitor<'de>, - { - unreachable!() - } - - fn deserialize_struct( - self, - _name: &'static str, - _fields: &'static [&'static str], - visitor: V, - ) -> Result + fn deserialize_map(self, visitor: V) -> Result where V: Visitor<'de>, { @@ -561,6 +546,18 @@ impl<'a, 'de> de::Deserializer<'de> for &'a mut Deserializer<'de> { } } + 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, diff --git a/src/ser/map.rs b/src/ser/map.rs new file mode 100644 index 000000000..dd1bfde79 --- /dev/null +++ b/src/ser/map.rs @@ -0,0 +1,56 @@ +use serde::ser; + +use heapless::ArrayLength; + +use crate::ser::{Error, Result, Serializer}; + +pub struct SerializeMap<'a, B> +where + B: ArrayLength, +{ + ser: &'a mut Serializer, + first: bool, +} + +impl<'a, B> SerializeMap<'a, B> +where + B: ArrayLength, +{ + pub(crate) fn new(ser: &'a mut Serializer) -> Self { + SerializeMap { ser, first: true } + } +} + +impl<'a, B> ser::SerializeMap for SerializeMap<'a, B> +where + B: ArrayLength, +{ + type Ok = (); + type Error = Error; + + fn end(self) -> Result { + self.ser.buf.push(b'}')?; + Ok(()) + } + + fn serialize_key(&mut self, key: &T) -> Result<()> + where + T: ser::Serialize, + { + if !self.first { + self.ser.buf.push(b',')?; + } + self.first = false; + key.serialize(&mut *self.ser)?; + self.ser.buf.extend_from_slice(b":")?; + Ok(()) + } + + fn serialize_value(&mut self, value: &T) -> Result<()> + where + T: ser::Serialize, + { + value.serialize(&mut *self.ser)?; + Ok(()) + } +} diff --git a/src/ser/mod.rs b/src/ser/mod.rs index 25f953d17..bd4556608 100644 --- a/src/ser/mod.rs +++ b/src/ser/mod.rs @@ -6,9 +6,11 @@ use serde::ser; use heapless::{consts::*, String, Vec}; +use self::map::SerializeMap; use self::seq::SerializeSeq; use self::struct_::SerializeStruct; +mod map; mod seq; mod struct_; @@ -142,7 +144,7 @@ where type SerializeTuple = SerializeSeq<'a, B>; type SerializeTupleStruct = Unreachable; type SerializeTupleVariant = Unreachable; - type SerializeMap = Unreachable; + type SerializeMap = SerializeMap<'a, B>; type SerializeStruct = SerializeStruct<'a, B>; type SerializeStructVariant = Unreachable; @@ -301,7 +303,9 @@ where } fn serialize_map(self, _len: Option) -> Result { - unreachable!() + self.buf.push(b'{')?; + + Ok(SerializeMap::new(self)) } fn serialize_struct(self, _name: &'static str, _len: usize) -> Result { diff --git a/src/ser/struct_.rs b/src/ser/struct_.rs index 2ff9421ad..b76826766 100644 --- a/src/ser/struct_.rs +++ b/src/ser/struct_.rs @@ -8,7 +8,7 @@ pub struct SerializeStruct<'a, B> where B: ArrayLength, { - de: &'a mut Serializer, + ser: &'a mut Serializer, first: bool, } @@ -16,8 +16,8 @@ impl<'a, B> SerializeStruct<'a, B> where B: ArrayLength, { - pub(crate) fn new(de: &'a mut Serializer) -> Self { - SerializeStruct { de, first: true } + pub(crate) fn new(ser: &'a mut Serializer) -> Self { + SerializeStruct { ser, first: true } } } @@ -34,21 +34,21 @@ where { // XXX if `value` is `None` we not produce any output for this field if !self.first { - self.de.buf.push(b',')?; + self.ser.buf.push(b',')?; } self.first = false; - self.de.buf.push(b'"')?; - self.de.buf.extend_from_slice(key.as_bytes())?; - self.de.buf.extend_from_slice(b"\":")?; + self.ser.buf.push(b'"')?; + self.ser.buf.extend_from_slice(key.as_bytes())?; + self.ser.buf.extend_from_slice(b"\":")?; - value.serialize(&mut *self.de)?; + value.serialize(&mut *self.ser)?; Ok(()) } fn end(self) -> Result { - self.de.buf.push(b'}')?; + self.ser.buf.push(b'}')?; Ok(()) } }