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 | |
| parent | 816ca9ed5db5b42c19dd9e53e3af903e8efec00b (diff) | |
| download | rust-plist-8868a6880b67fce7c7147526b2973ba59376d93a.tar.bz2 | |
Implement serde serialization
| -rw-r--r-- | Cargo.toml | 1 | ||||
| -rw-r--r-- | src/de.rs | 286 | ||||
| -rw-r--r-- | src/lib.rs | 11 | ||||
| -rw-r--r-- | src/ser.rs | 173 | 
4 files changed, 471 insertions, 0 deletions
| @@ -13,3 +13,4 @@ rustc-serialize = "0.3.16"  xml-rs = "0.2.2"  byteorder = "0.4.2"  chrono = "0.2.17" +serde = "0.6.6" 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)) +    } +} | 
