diff options
| author | Edward Barnard | 2015-12-24 19:39:07 +0000 |
|---|---|---|
| committer | Edward Barnard | 2015-12-24 22:22:31 +0000 |
| commit | 8868a6880b67fce7c7147526b2973ba59376d93a (patch) | |
| tree | 054a80244ccdc78406d7b35afe3eed31a85c26e0 /src | |
| parent | 816ca9ed5db5b42c19dd9e53e3af903e8efec00b (diff) | |
| download | rust-plist-8868a6880b67fce7c7147526b2973ba59376d93a.tar.bz2 | |
Implement serde serialization
Diffstat (limited to 'src')
| -rw-r--r-- | src/de.rs | 286 | ||||
| -rw-r--r-- | src/lib.rs | 11 | ||||
| -rw-r--r-- | src/ser.rs | 173 |
3 files changed, 470 insertions, 0 deletions
diff --git a/src/de.rs b/src/de.rs new file mode 100644 index 0000000..9d77e4d --- /dev/null +++ b/src/de.rs @@ -0,0 +1,286 @@ +use serde::de::{Deserializer as SerdeDeserializer, Error as SerdeError, Visitor, SeqVisitor, + MapVisitor, VariantVisitor, Deserialize, EnumVisitor}; +use std::iter::Peekable; + +use PlistEvent; + +macro_rules! expect { + ($next:expr, $pat:pat) => { + match $next { + Some(Ok(v@$pat)) => v, + None => return Err(Error::end_of_stream()), + _ => return Err(Error::syntax("")) + } + }; + ($next:expr, $pat:pat => $save:expr) => { + match $next { + Some(Ok($pat)) => $save, + None => return Err(Error::end_of_stream()), + _ => return Err(Error::syntax("")) + } + }; +} + +macro_rules! try_next { + ($next:expr) => { + match $next { + Some(Ok(v)) => v, + Some(Err(_)) => return Err(Error::syntax("")), + None => return Err(Error::end_of_stream()) + } + } +} + +#[derive(Debug)] +pub enum Error { + None, +} + +impl SerdeError for Error { + fn syntax(_msg: &str) -> Self { + panic!("stx"); + Error::None + } + + fn end_of_stream() -> Self { + panic!("eos"); + Error::None + } + + fn unknown_field(_field: &str) -> Self { + panic!("uf"); + Error::None + } + + fn missing_field(_field: &'static str) -> Self { + panic!("mf"); + Error::None + } +} + +pub struct Deserializer<I, E> + where I: IntoIterator<Item = Result<PlistEvent, E>> +{ + events: Peekable<<I as IntoIterator>::IntoIter>, +} + +impl<I, E> Deserializer<I, E> where I: IntoIterator<Item = Result<PlistEvent, E>> +{ + pub fn new(iter: I) -> Deserializer<I, E> { + Deserializer { events: iter.into_iter().peekable() } + } +} + +impl<I, E> SerdeDeserializer for Deserializer<I, E> + where I: IntoIterator<Item = Result<PlistEvent, E>> +{ + type Error = Error; + + fn visit<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error> + where V: Visitor + { + match try_next!(self.events.next()) { + PlistEvent::StartPlist => panic!(), + PlistEvent::EndPlist => panic!(), + + PlistEvent::StartArray(len) => { + visitor.visit_seq(MapSeq::new(self, len.map(|l| l as usize))) + } + PlistEvent::EndArray => return Err(Error::syntax("")), + + PlistEvent::StartDictionary(len) => { + visitor.visit_map(MapSeq::new(self, len.map(|l| l as usize))) + } + PlistEvent::EndDictionary => return Err(Error::syntax("")), + + PlistEvent::BooleanValue(v) => visitor.visit_bool(v), + PlistEvent::DataValue(v) => visitor.visit_byte_buf(v), + PlistEvent::DateValue(v) => visitor.visit_string(v.to_rfc3339()), + PlistEvent::IntegerValue(v) if v.is_positive() => visitor.visit_u64(v as u64), + PlistEvent::IntegerValue(v) => visitor.visit_i64(v as i64), + PlistEvent::RealValue(v) => visitor.visit_f64(v), + PlistEvent::StringValue(v) => visitor.visit_string(v), + } + } + + fn visit_unit<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error> + where V: Visitor + { + expect!(self.events.next(), PlistEvent::StringValue(_)); + visitor.visit_unit() + } + + fn visit_option<V>(&mut self, mut visitor: V) -> Result<V::Value, Self::Error> + where V: Visitor + { + expect!(self.events.next(), PlistEvent::StartDictionary(_)); + + let ret = match try_next!(self.events.next()) { + PlistEvent::StringValue(ref s) if &s[..] == "None" => { + let ret = try!(visitor.visit_none()); + expect!(self.events.next(), PlistEvent::StringValue(_)); + ret + } + PlistEvent::StringValue(ref s) if &s[..] == "Some" => try!(visitor.visit_some(self)), + _ => return Err(Error::syntax("")), + }; + + expect!(self.events.next(), PlistEvent::EndDictionary); + + Ok(ret) + } + + fn visit_newtype_struct<V>(&mut self, + _name: &'static str, + mut visitor: V) + -> Result<V::Value, Self::Error> + where V: Visitor + { + visitor.visit_newtype_struct(self) + } + + fn visit_enum<V>(&mut self, + _enum: &'static str, + _variants: &'static [&'static str], + mut visitor: V) + -> Result<V::Value, Self::Error> + where V: EnumVisitor + { + expect!(self.events.next(), PlistEvent::StartDictionary(_)); + let ret = try!(visitor.visit(&mut *self)); + expect!(self.events.next(), PlistEvent::EndDictionary); + Ok(ret) + } +} + +impl<I, E> VariantVisitor for Deserializer<I, E> where I: IntoIterator<Item = Result<PlistEvent, E>> +{ + type Error = Error; + + fn visit_variant<V>(&mut self) -> Result<V, Self::Error> + where V: Deserialize + { + <V as Deserialize>::deserialize(self) + } + + fn visit_unit(&mut self) -> Result<(), Self::Error> { + <() as Deserialize>::deserialize(self) + } + + fn visit_newtype<T>(&mut self) -> Result<T, Self::Error> + where T: Deserialize + { + <T as Deserialize>::deserialize(self) + } + + fn visit_tuple<V>(&mut self, len: usize, visitor: V) -> Result<V::Value, Self::Error> + where V: Visitor + { + <Self as SerdeDeserializer>::visit_tuple(self, len, visitor) + } + + fn visit_struct<V>(&mut self, + fields: &'static [&'static str], + visitor: V) + -> Result<V::Value, Self::Error> + where V: Visitor + { + let name = ""; + <Self as SerdeDeserializer>::visit_struct(self, name, fields, visitor) + } +} + +struct MapSeq<'a, I, E> + where E: 'a, + I: 'a + IntoIterator<Item = Result<PlistEvent, E>> +{ + de: &'a mut Deserializer<I, E>, + remaining: Option<usize>, + finished: bool, +} + +impl<'a, I, E> MapSeq<'a, I, E> + where E: 'a, + I: 'a + IntoIterator<Item = Result<PlistEvent, E>> +{ + fn new(de: &'a mut Deserializer<I, E>, len: Option<usize>) -> MapSeq<'a, I, E> { + MapSeq { + de: de, + remaining: len, + finished: false, + } + } +} + +impl<'a, I, E> SeqVisitor for MapSeq<'a, I, E> + where E: 'a, + I: 'a + IntoIterator<Item = Result<PlistEvent, E>> +{ + type Error = Error; + + fn visit<T>(&mut self) -> Result<Option<T>, Self::Error> + where T: Deserialize + { + match self.de.events.peek() { + Some(&Ok(PlistEvent::EndArray)) => { + self.de.events.next(); + self.finished = true; + return Ok(None); + } + _ => <T as Deserialize>::deserialize(self.de).map(|k| Some(k)), + } + } + + fn end(&mut self) -> Result<(), Self::Error> { + if !self.finished { + self.finished = true; + expect!(self.de.events.next(), PlistEvent::EndArray); + } + Ok(()) + } + + fn size_hint(&self) -> (usize, Option<usize>) { + <Self as MapVisitor>::size_hint(self) + } +} + +impl<'a, I, E> MapVisitor for MapSeq<'a, I, E> + where E: 'a, + I: 'a + IntoIterator<Item = Result<PlistEvent, E>> +{ + type Error = Error; + + fn visit_key<K>(&mut self) -> Result<Option<K>, Self::Error> + where K: Deserialize + { + match self.de.events.peek() { + Some(&Ok(PlistEvent::EndDictionary)) => { + self.de.events.next(); + self.finished = true; + return Ok(None); + } + _ => <K as Deserialize>::deserialize(self.de).map(|k| Some(k)), + } + } + + fn visit_value<V>(&mut self) -> Result<V, Self::Error> + where V: Deserialize + { + <V as Deserialize>::deserialize(self.de) + } + + fn end(&mut self) -> Result<(), Self::Error> { + if !self.finished { + self.finished = true; + expect!(self.de.events.next(), PlistEvent::EndDictionary); + } + Ok(()) + } + + fn size_hint(&self) -> (usize, Option<usize>) { + match self.remaining { + Some(len) => (len, Some(len)), + None => (0, None), + } + } +} @@ -38,11 +38,18 @@ extern crate byteorder; extern crate chrono; extern crate rustc_serialize; +extern crate serde; extern crate xml as xml_rs; pub mod binary; pub mod xml; + mod builder; +mod de; +mod ser; + +pub use de::Deserializer; +pub use ser::Serializer; use chrono::{DateTime, UTC}; use chrono::format::ParseError as ChronoParseError; @@ -241,3 +248,7 @@ impl<R: Read + Seek> Iterator for EventReader<R> { self.next() } } + +pub trait EventWriter { + fn write(&mut self, event: &PlistEvent) -> Result<(), ()>; +} diff --git a/src/ser.rs b/src/ser.rs new file mode 100644 index 0000000..059bbd7 --- /dev/null +++ b/src/ser.rs @@ -0,0 +1,173 @@ +use serde::ser::{MapVisitor, Serialize, Serializer as SerdeSerializer, SeqVisitor}; + +use {EventWriter, PlistEvent}; + +pub struct Serializer<W: EventWriter> { + writer: W, +} + +impl<W: EventWriter> Serializer<W> { + pub fn new(writer: W) -> Serializer<W> { + Serializer { writer: writer } + } + + #[inline] + fn emit(&mut self, event: PlistEvent) -> Result<(), ()> { + self.writer.write(&event) + } + + pub fn into_inner(self) -> W { + self.writer + } + + fn single_key_dict<F>(&mut self, + key: String, + value_fn: F) + -> Result<(), <Self as SerdeSerializer>::Error> + where F: FnOnce(&mut Serializer<W>) -> Result<(), <Self as SerdeSerializer>::Error> + { + // Emit {key: value} + try!(self.emit(PlistEvent::StartDictionary(Some(1)))); + try!(self.emit(PlistEvent::StringValue(key))); + try!(value_fn(self)); + try!(self.emit(PlistEvent::EndDictionary)); + Ok(()) + } +} + +impl<W: EventWriter> SerdeSerializer for Serializer<W> { + type Error = (); + + fn visit_bool(&mut self, v: bool) -> Result<(), Self::Error> { + self.emit(PlistEvent::BooleanValue(v)) + } + + fn visit_i64(&mut self, v: i64) -> Result<(), Self::Error> { + self.emit(PlistEvent::IntegerValue(v)) + } + + fn visit_u64(&mut self, v: u64) -> Result<(), Self::Error> { + self.emit(PlistEvent::IntegerValue(v as i64)) + } + + fn visit_f64(&mut self, v: f64) -> Result<(), Self::Error> { + self.emit(PlistEvent::RealValue(v)) + } + + fn visit_str(&mut self, value: &str) -> Result<(), Self::Error> { + self.emit(PlistEvent::StringValue(value.to_owned())) + } + + fn visit_bytes(&mut self, value: &[u8]) -> Result<(), Self::Error> { + self.emit(PlistEvent::DataValue(value.to_owned())) + } + + fn visit_unit(&mut self) -> Result<(), Self::Error> { + // Emit empty string + self.emit(PlistEvent::StringValue(String::new())) + } + + fn visit_none(&mut self) -> Result<(), Self::Error> { + self.single_key_dict("None".to_owned(), |this| this.visit_unit()) + } + + fn visit_some<V>(&mut self, value: V) -> Result<(), Self::Error> + where V: Serialize + { + self.single_key_dict("Some".to_owned(), |this| value.serialize(this)) + } + + fn visit_seq<V>(&mut self, mut visitor: V) -> Result<(), Self::Error> + where V: SeqVisitor + { + let len = visitor.len().map(|len| len as u64); + try!(self.emit(PlistEvent::StartArray(len))); + loop { + match try!(visitor.visit(self)) { + Some(()) => (), + None => break, + } + } + try!(self.emit(PlistEvent::EndArray)); + Ok(()) + } + + fn visit_seq_elt<T>(&mut self, value: T) -> Result<(), Self::Error> + where T: Serialize + { + value.serialize(self) + } + + fn visit_map<V>(&mut self, mut visitor: V) -> Result<(), Self::Error> + where V: MapVisitor + { + let len = visitor.len().map(|len| len as u64); + try!(self.emit(PlistEvent::StartDictionary(len))); + loop { + match try!(visitor.visit(self)) { + Some(()) => (), + None => break, + } + } + try!(self.emit(PlistEvent::EndDictionary)); + Ok(()) + } + + fn visit_map_elt<K, V>(&mut self, key: K, value: V) -> Result<(), Self::Error> + where K: Serialize, + V: Serialize + { + try!(key.serialize(self)); + try!(value.serialize(self)); + Ok(()) + } + + fn visit_unit_variant(&mut self, + _name: &'static str, + _variant_index: usize, + variant: &'static str) + -> Result<(), Self::Error> { + self.single_key_dict(variant.to_owned(), |this| this.visit_unit()) + } + + fn visit_newtype_struct<T>(&mut self, _name: &'static str, value: T) -> Result<(), Self::Error> + where T: Serialize + { + value.serialize(self) + } + + fn visit_newtype_variant<T>(&mut self, + _name: &'static str, + _variant_index: usize, + variant: &'static str, + value: T) + -> Result<(), Self::Error> + where T: Serialize + { + self.single_key_dict(variant.to_owned(), |this| value.serialize(this)) + } + + fn visit_tuple_variant<V>(&mut self, + _name: &'static str, + _variant_index: usize, + variant: &'static str, + visitor: V) + -> Result<(), Self::Error> + where V: SeqVisitor + { + self.single_key_dict(variant.to_owned(), + |this| this.visit_tuple_struct(variant, visitor)) + } + + fn visit_struct_variant<V>(&mut self, + _name: &'static str, + _variant_index: usize, + variant: &'static str, + visitor: V) + -> Result<(), Self::Error> + where V: MapVisitor + { + self.single_key_dict(variant.to_owned(), + |this| this.visit_struct(variant, visitor)) + } +} |
