diff options
| author | Edward Barnard | 2017-05-03 12:29:21 +0100 |
|---|---|---|
| committer | Edward Barnard | 2017-05-03 12:29:48 +0100 |
| commit | 56e2c5d4ca34b2e40d15ac5b2ceb98f34add6b1b (patch) | |
| tree | 53447eb26505f2c671da06c8e8f4e4fd5e60a138 /src | |
| parent | a9f71a02928fd275221ce5fc12c8dc2cfc55407e (diff) | |
| download | rust-plist-56e2c5d4ca34b2e40d15ac5b2ceb98f34add6b1b.tar.bz2 | |
Serialise Option<T> struct fields as T if value if Some and ignore field if value is None.
Diffstat (limited to 'src')
| -rw-r--r-- | src/serde/de.rs | 130 | ||||
| -rw-r--r-- | src/serde/ser.rs | 49 |
2 files changed, 141 insertions, 38 deletions
diff --git a/src/serde/de.rs b/src/serde/de.rs index 72a81bd..1b9838a 100644 --- a/src/serde/de.rs +++ b/src/serde/de.rs @@ -69,7 +69,7 @@ impl<'de, 'a, I> de::Deserializer<'de> for &'a mut Deserializer<I> match try_next!(self.events.next()) { PlistEvent::StartArray(len) => { let len = try!(u64_option_to_usize(len)); - let ret = visitor.visit_seq(MapAndSeqAccess::new(self, len))?; + let ret = visitor.visit_seq(MapAndSeqAccess::new(self, false, len))?; expect!(self.events.next(), PlistEvent::EndArray); Ok(ret) } @@ -77,7 +77,7 @@ impl<'de, 'a, I> de::Deserializer<'de> for &'a mut Deserializer<I> PlistEvent::StartDictionary(len) => { let len = try!(u64_option_to_usize(len)); - let ret = visitor.visit_map(MapAndSeqAccess::new(self, len))?; + let ret = visitor.visit_map(MapAndSeqAccess::new(self, false, len))?; expect!(self.events.next(), PlistEvent::EndDictionary); Ok(ret) } @@ -96,7 +96,7 @@ impl<'de, 'a, I> de::Deserializer<'de> for &'a mut Deserializer<I> forward_to_deserialize_any! { bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string seq bytes byte_buf map unit_struct - tuple_struct struct tuple ignored_any identifier + tuple_struct tuple ignored_any identifier } fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error> @@ -113,18 +113,11 @@ impl<'de, 'a, I> de::Deserializer<'de> for &'a mut Deserializer<I> let ret = match try_next!(self.events.next()) { PlistEvent::StringValue(ref s) if &s[..] == "None" => { - let ret = match visitor.visit_none() { - Ok(ret) => ret, - Err(e) => return Err(e), - }; - // For some reason the try! below doesn't work - probably a macro hygene issue - // with Error and ::Error - // let ret = try!(visitor.visit_none()); expect!(self.events.next(), PlistEvent::StringValue(_)); - ret + visitor.visit_none::<Self::Error>()? } PlistEvent::StringValue(ref s) if &s[..] == "Some" => { - try!(visitor.visit_some(&mut *self)) + visitor.visit_some(&mut *self)? } _ => return Err(event_mismatch_error()), }; @@ -143,6 +136,19 @@ impl<'de, 'a, I> de::Deserializer<'de> for &'a mut Deserializer<I> visitor.visit_newtype_struct(self) } + fn deserialize_struct<V>(self, + _name: &'static str, + _fields: &'static [&'static str], + visitor: V) + -> Result<V::Value, Self::Error> + where V: de::Visitor<'de> + { + expect!(self.events.next(), PlistEvent::StartDictionary(_)); + let ret = visitor.visit_map(MapAndSeqAccess::new(self, true, None))?; + expect!(self.events.next(), PlistEvent::EndDictionary); + Ok(ret) + } + fn deserialize_enum<V>(self, _enum: &'static str, _variants: &'static [&'static str], @@ -202,19 +208,87 @@ impl<'de, 'a, I> de::VariantAccess<'de> for &'a mut Deserializer<I> } } +pub struct StructValueDeserializer<'a, I: 'a> + where I: IntoIterator<Item = Result<PlistEvent, Error>> +{ + de: &'a mut Deserializer<I> +} + +impl<'de, 'a, I> de::Deserializer<'de> for StructValueDeserializer<'a, I> + where I: IntoIterator<Item = Result<PlistEvent, Error>> +{ + type Error = Error; + + fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error> + where V: de::Visitor<'de> + { + self.de.deserialize_any(visitor) + } + + forward_to_deserialize_any! { + bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string + seq bytes byte_buf map unit_struct + tuple_struct tuple ignored_any identifier + } + + fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error> + where V: de::Visitor<'de> + { + self.de.deserialize_unit(visitor) + } + + fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error> + where V: de::Visitor<'de> + { + // None struct values are ignored so if we're here the value must be Some. + visitor.visit_some(self.de) + } + + fn deserialize_newtype_struct<V>(self, + name: &'static str, + visitor: V) + -> Result<V::Value, Self::Error> + where V: de::Visitor<'de> + { + self.de.deserialize_newtype_struct(name, visitor) + } + + fn deserialize_struct<V>(self, + name: &'static str, + fields: &'static [&'static str], + visitor: V) + -> Result<V::Value, Self::Error> + where V: de::Visitor<'de> + { + self.de.deserialize_struct(name, fields, visitor) + } + + fn deserialize_enum<V>(self, + enum_: &'static str, + variants: &'static [&'static str], + visitor: V) + -> Result<V::Value, Self::Error> + where V: de::Visitor<'de> + { + self.de.deserialize_enum(enum_, variants, visitor) + } +} + struct MapAndSeqAccess<'a, I> where I: 'a + IntoIterator<Item = Result<PlistEvent, Error>> { de: &'a mut Deserializer<I>, + is_struct: bool, remaining: Option<usize>, } impl<'a, I> MapAndSeqAccess<'a, I> where I: 'a + IntoIterator<Item = Result<PlistEvent, Error>> { - fn new(de: &'a mut Deserializer<I>, len: Option<usize>) -> MapAndSeqAccess<'a, I> { + fn new(de: &'a mut Deserializer<I>, is_struct: bool, len: Option<usize>) -> MapAndSeqAccess<'a, I> { MapAndSeqAccess { de: de, + is_struct: is_struct, remaining: len, } } @@ -228,14 +302,12 @@ impl<'de, 'a, I> de::SeqAccess<'de> for MapAndSeqAccess<'a, I> fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Self::Error> where T: de::DeserializeSeed<'de> { - match self.de.events.peek() { - Some(&Ok(PlistEvent::EndArray)) => Ok(None), - _ => { - let ret = seed.deserialize(&mut *self.de).map(|k| Some(k)); - self.remaining = self.remaining.map(|r| r.saturating_sub(1)); - ret - } + if let Some(&Ok(PlistEvent::EndArray)) = self.de.events.peek() { + return Ok(None); } + + self.remaining = self.remaining.map(|r| r.saturating_sub(1)); + seed.deserialize(&mut *self.de).map(Some) } fn size_hint(&self) -> Option<usize> { @@ -251,20 +323,22 @@ impl<'de, 'a, I> de::MapAccess<'de> for MapAndSeqAccess<'a, I> fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Self::Error> where K: de::DeserializeSeed<'de> { - match self.de.events.peek() { - Some(&Ok(PlistEvent::EndDictionary)) => return Ok(None), - _ => { - let ret = seed.deserialize(&mut *self.de).map(|k| Some(k)); - self.remaining = self.remaining.map(|r| r.saturating_sub(1)); - ret - } + if let Some(&Ok(PlistEvent::EndDictionary)) = self.de.events.peek() { + return Ok(None); } + + self.remaining = self.remaining.map(|r| r.saturating_sub(1)); + seed.deserialize(&mut *self.de).map(Some) } fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error> where V: de::DeserializeSeed<'de> { - seed.deserialize(&mut *self.de) + if self.is_struct { + seed.deserialize(StructValueDeserializer { de: &mut *self.de }) + } else { + seed.deserialize(&mut *self.de) + } } fn size_hint(&self) -> Option<usize> { diff --git a/src/serde/ser.rs b/src/serde/ser.rs index 48ad39f..3772d7f 100644 --- a/src/serde/ser.rs +++ b/src/serde/ser.rs @@ -14,14 +14,26 @@ impl ser::Error for Error { pub struct Serializer<W: EventWriter> { writer: W, + // We don't want to serialize None if the Option is in a struct field as this is how null + // fields are represented in plists. This is fragile but results in minimal code duplication. + // TODO: This is fragile. Use distinct types instead. + maybe_option_field_name: Option<&'static str> } impl<W: EventWriter> Serializer<W> { pub fn new(writer: W) -> Serializer<W> { - Serializer { writer: writer } + Serializer { + writer: writer, + maybe_option_field_name: None + } } fn emit(&mut self, event: PlistEvent) -> Result<(), Error> { + // Write a waiting struct field name. + // TODO: This is fragile. Use distinct types instead. + if let Some(field_name) = self.maybe_option_field_name.take() { + self.emit(PlistEvent::StringValue(field_name.to_owned()))?; + } Ok(self.writer.write(&event)?) } @@ -111,15 +123,28 @@ impl<'a, W: EventWriter> ser::Serializer for &'a mut Serializer<W> { } fn serialize_none(self) -> Result<(), Self::Error> { - self.single_key_dict("None".to_owned())?; - self.serialize_unit()?; - self.single_key_dict_end() + // Don't write a dict for None if the Option is a struct field. + // TODO: This is fragile. Use distinct types instead. + if let None = self.maybe_option_field_name.take() { + self.single_key_dict("None".to_owned())?; + self.serialize_unit()?; + self.single_key_dict_end()?; + } + Ok(()) } fn serialize_some<T: ?Sized + ser::Serialize>(self, value: &T) -> Result<(), Self::Error> { - self.single_key_dict("Some".to_owned())?; - value.serialize(&mut *self)?; - self.single_key_dict_end() + // Don't write a dict for None if the Option is a struct field. + // Can't use the write in emit here in case there is a Some(None). + // TODO: This is fragile. Use distinct types instead. + if let Some(field_name) = self.maybe_option_field_name.take() { + self.emit(PlistEvent::StringValue(field_name.to_owned()))?; + value.serialize(&mut *self) + } else { + self.single_key_dict("Some".to_owned())?; + value.serialize(&mut *self)?; + self.single_key_dict_end() + } } fn serialize_unit(self) -> Result<(), Self::Error> { @@ -195,9 +220,10 @@ impl<'a, W: EventWriter> ser::Serializer for &'a mut Serializer<W> { fn serialize_struct(self, _name: &'static str, - len: usize) + _len: usize) -> Result<Self::SerializeStruct, Self::Error> { - self.serialize_map(Some(len)) + // The number of struct fields is not known as fields with None values are ignored. + self.serialize_map(None) } fn serialize_struct_variant(self, @@ -304,7 +330,10 @@ impl<'a, W: EventWriter> ser::SerializeStruct for Compound<'a, W> { key: &'static str, value: &T) -> Result<(), Self::Error> { - <Self as ser::SerializeMap>::serialize_entry(self, key, value) + // Don't write a dict for None if the Option is a struct field. + // TODO: This is fragile. Use distinct types instead. + self.ser.maybe_option_field_name = Some(key); + value.serialize(&mut *self.ser) } fn end(self) -> Result<Self::Ok, Self::Error> { |
