aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEdward Barnard2015-12-24 19:39:07 +0000
committerEdward Barnard2015-12-24 22:22:31 +0000
commit8868a6880b67fce7c7147526b2973ba59376d93a (patch)
tree054a80244ccdc78406d7b35afe3eed31a85c26e0
parent816ca9ed5db5b42c19dd9e53e3af903e8efec00b (diff)
downloadrust-plist-8868a6880b67fce7c7147526b2973ba59376d93a.tar.bz2
Implement serde serialization
-rw-r--r--Cargo.toml1
-rw-r--r--src/de.rs286
-rw-r--r--src/lib.rs11
-rw-r--r--src/ser.rs173
4 files changed, 471 insertions, 0 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 2b51b62..9cd4ec8 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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),
+ }
+ }
+}
diff --git a/src/lib.rs b/src/lib.rs
index 682b11c..7c699c7 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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))
+ }
+}