From 2af279c344a6a917ce4102fec82e6cba8cf8b37c Mon Sep 17 00:00:00 2001 From: Edward Barnard Date: Thu, 17 May 2018 20:30:41 +0100 Subject: Reorganise crate. --- src/binary/mod.rs | 3 - src/binary/reader.rs | 386 ------------------------ src/builder.rs | 62 ++-- src/date.rs | 4 +- src/de.rs | 393 ++++++++++++++++++++++++ src/events/binary_reader.rs | 385 ++++++++++++++++++++++++ src/events/mod.rs | 95 ++++++ src/events/xml_reader.rs | 199 +++++++++++++ src/events/xml_writer.rs | 259 ++++++++++++++++ src/lib.rs | 111 +------ src/plist.rs | 376 ----------------------- src/ser.rs | 712 ++++++++++++++++++++++++++++++++++++++++++++ src/serde/de.rs | 385 ------------------------ src/serde/mod.rs | 25 -- src/serde/ser.rs | 704 ------------------------------------------- src/value.rs | 377 +++++++++++++++++++++++ src/xml/mod.rs | 5 - src/xml/reader.rs | 199 ------------- src/xml/writer.rs | 259 ---------------- tests/fuzzer.rs | 6 +- tests/serde_tests/mod.rs | 31 +- 21 files changed, 2486 insertions(+), 2490 deletions(-) delete mode 100644 src/binary/mod.rs delete mode 100644 src/binary/reader.rs create mode 100644 src/de.rs create mode 100644 src/events/binary_reader.rs create mode 100644 src/events/mod.rs create mode 100644 src/events/xml_reader.rs create mode 100644 src/events/xml_writer.rs delete mode 100644 src/plist.rs create mode 100644 src/ser.rs delete mode 100644 src/serde/de.rs delete mode 100644 src/serde/mod.rs delete mode 100644 src/serde/ser.rs create mode 100644 src/value.rs delete mode 100644 src/xml/mod.rs delete mode 100644 src/xml/reader.rs delete mode 100644 src/xml/writer.rs diff --git a/src/binary/mod.rs b/src/binary/mod.rs deleted file mode 100644 index 7c9ae75..0000000 --- a/src/binary/mod.rs +++ /dev/null @@ -1,3 +0,0 @@ -mod reader; - -pub use self::reader::EventReader; diff --git a/src/binary/reader.rs b/src/binary/reader.rs deleted file mode 100644 index bee34f7..0000000 --- a/src/binary/reader.rs +++ /dev/null @@ -1,386 +0,0 @@ -use byteorder::{BigEndian, ReadBytesExt}; -use std::io::{Read, Seek, SeekFrom}; -use std::mem::size_of; -use std::string::{FromUtf16Error, FromUtf8Error}; - -use {Date, Error, PlistEvent, Result, u64_to_usize}; - -impl From for Error { - fn from(_: FromUtf8Error) -> Error { - Error::InvalidData - } -} - -impl From for Error { - fn from(_: FromUtf16Error) -> Error { - Error::InvalidData - } -} - -struct StackItem { - object_refs: Vec, - ty: StackType, -} - -enum StackType { - Array, - Dict, - Root, -} - -/// https://opensource.apple.com/source/CF/CF-550/CFBinaryPList.c -/// https://hg.python.org/cpython/file/3.4/Lib/plistlib.py -pub struct EventReader { - stack: Vec, - object_offsets: Vec, - reader: R, - ref_size: u8, - finished: bool, - // The largest single allocation allowed for this Plist. - // Equal to the number of bytes in the Plist minus the magic and trailer. - max_allocation_bytes: usize, - // The maximum number of nested arrays and dicts allowed in the plist. - max_stack_depth: usize, - // The maximum number of objects that can be created. Default 10 * object_offsets.len(). - // Binary plists can contain circular references. - max_objects: usize, - // The number of objects created so far. - current_objects: usize, -} - -impl EventReader { - pub fn new(reader: R) -> EventReader { - EventReader { - stack: Vec::new(), - object_offsets: Vec::new(), - reader: reader, - ref_size: 0, - finished: false, - max_allocation_bytes: 0, - max_stack_depth: 200, - max_objects: 0, - current_objects: 0, - } - } - - fn can_allocate(&self, len: u64, size: usize) -> bool { - let byte_len = len.saturating_mul(size as u64); - byte_len <= self.max_allocation_bytes as u64 - } - - fn allocate_vec(&self, len: u64, size: usize) -> Result> { - if self.can_allocate(len, size) { - Ok(Vec::with_capacity(len as usize)) - } else { - Err(Error::InvalidData) - } - } - - fn read_trailer(&mut self) -> Result<()> { - self.reader.seek(SeekFrom::Start(0))?; - let mut magic = [0; 8]; - self.reader.read_exact(&mut magic)?; - if &magic != b"bplist00" { - return Err(Error::InvalidData); - } - - // Trailer starts with 6 bytes of padding - let trailer_start = self.reader.seek(SeekFrom::End(-32 + 6))?; - - let offset_size = self.reader.read_u8()?; - match offset_size { - 1 | 2 | 4 | 8 => (), - _ => return Err(Error::InvalidData), - } - - self.ref_size = self.reader.read_u8()?; - match self.ref_size { - 1 | 2 | 4 | 8 => (), - _ => return Err(Error::InvalidData), - } - - let num_objects = self.reader.read_u64::()?; - let top_object = self.reader.read_u64::()?; - let offset_table_offset = self.reader.read_u64::()?; - - // File size minus trailer and header - // Truncated to max(usize) - self.max_allocation_bytes = trailer_start.saturating_sub(8) as usize; - - // Read offset table - self.reader.seek(SeekFrom::Start(offset_table_offset))?; - self.object_offsets = self.read_ints(num_objects, offset_size)?; - - self.max_objects = self.object_offsets.len() * 10; - - // Seek to top object - self.stack.push(StackItem { - object_refs: vec![top_object], - ty: StackType::Root, - }); - - Ok(()) - } - - fn read_ints(&mut self, len: u64, size: u8) -> Result> { - let mut ints = self.allocate_vec(len, size as usize)?; - for _ in 0..len { - match size { - 1 => ints.push(self.reader.read_u8()? as u64), - 2 => ints.push(self.reader.read_u16::()? as u64), - 4 => ints.push(self.reader.read_u32::()? as u64), - 8 => ints.push(self.reader.read_u64::()? as u64), - _ => return Err(Error::InvalidData), - } - } - Ok(ints) - } - - fn read_refs(&mut self, len: u64) -> Result> { - let ref_size = self.ref_size; - self.read_ints(len, ref_size) - } - - fn read_object_len(&mut self, len: u8) -> Result { - if (len & 0x0f) == 0x0f { - let len_power_of_two = self.reader.read_u8()? & 0x03; - Ok(match len_power_of_two { - 0 => self.reader.read_u8()? as u64, - 1 => self.reader.read_u16::()? as u64, - 2 => self.reader.read_u32::()? as u64, - 3 => self.reader.read_u64::()?, - _ => return Err(Error::InvalidData), - }) - } else { - Ok(len as u64) - } - } - - fn read_data(&mut self, len: u64) -> Result> { - let mut data = self.allocate_vec(len, size_of::())?; - data.resize(len as usize, 0); - self.reader.read_exact(&mut data)?; - Ok(data) - } - - fn seek_to_object(&mut self, object_ref: u64) -> Result { - let object_ref = u64_to_usize(object_ref)?; - let offset = *self.object_offsets - .get(object_ref) - .ok_or(Error::InvalidData)?; - Ok(self.reader.seek(SeekFrom::Start(offset))?) - } - - fn read_next(&mut self) -> Result> { - if self.ref_size == 0 { - // Initialise here rather than in new - self.read_trailer()?; - } - - let object_ref = match self.stack.last_mut() { - Some(stack_item) => stack_item.object_refs.pop(), - // Reached the end of the plist - None => return Ok(None), - }; - - match object_ref { - Some(object_ref) => { - if self.current_objects > self.max_objects { - return Err(Error::InvalidData); - } - self.current_objects += 1; - self.seek_to_object(object_ref)?; - } - None => { - // We're at the end of an array or dict. Pop the top stack item and return - let item = self.stack.pop().unwrap(); - match item.ty { - StackType::Array => return Ok(Some(PlistEvent::EndArray)), - StackType::Dict => return Ok(Some(PlistEvent::EndDictionary)), - // We're at the end of the plist - StackType::Root => return Ok(None), - } - } - } - - let token = self.reader.read_u8()?; - let ty = (token & 0xf0) >> 4; - let size = token & 0x0f; - - let result = match (ty, size) { - (0x0, 0x00) => return Err(Error::InvalidData), // null - (0x0, 0x08) => Some(PlistEvent::BooleanValue(false)), - (0x0, 0x09) => Some(PlistEvent::BooleanValue(true)), - (0x0, 0x0f) => return Err(Error::InvalidData), // fill - (0x1, 0) => Some(PlistEvent::IntegerValue(self.reader.read_u8()? as i64)), - (0x1, 1) => Some(PlistEvent::IntegerValue( - self.reader.read_u16::()? as i64, - )), - (0x1, 2) => Some(PlistEvent::IntegerValue( - self.reader.read_u32::()? as i64, - )), - (0x1, 3) => Some(PlistEvent::IntegerValue(self.reader.read_i64::()?)), - (0x1, 4) => return Err(Error::InvalidData), // 128 bit int - (0x1, _) => return Err(Error::InvalidData), // variable length int - (0x2, 2) => Some(PlistEvent::RealValue(self.reader.read_f32::()? as f64)), - (0x2, 3) => Some(PlistEvent::RealValue(self.reader.read_f64::()?)), - (0x2, _) => return Err(Error::InvalidData), // odd length float - (0x3, 3) => { - // Date. Seconds since 1/1/2001 00:00:00. - let secs = self.reader.read_f64::()?; - Some(PlistEvent::DateValue(Date::from_seconds_since_plist_epoch( - secs, - )?)) - } - (0x4, n) => { - // Data - let len = self.read_object_len(n)?; - Some(PlistEvent::DataValue(self.read_data(len)?)) - } - (0x5, n) => { - // ASCII string - let len = self.read_object_len(n)?; - let raw = self.read_data(len)?; - let string = String::from_utf8(raw)?; - Some(PlistEvent::StringValue(string)) - } - (0x6, n) => { - // UTF-16 string - let len_utf16_codepoints = self.read_object_len(n)?; - let mut raw_utf16 = self.allocate_vec(len_utf16_codepoints, size_of::())?; - - for _ in 0..len_utf16_codepoints { - raw_utf16.push(self.reader.read_u16::()?); - } - - let string = String::from_utf16(&raw_utf16)?; - Some(PlistEvent::StringValue(string)) - } - (0xa, n) => { - // Array - let len = self.read_object_len(n)?; - let mut object_refs = self.read_refs(len)?; - // Reverse so we can pop off the end of the stack in order - object_refs.reverse(); - - self.stack.push(StackItem { - ty: StackType::Array, - object_refs: object_refs, - }); - - Some(PlistEvent::StartArray(Some(len))) - } - (0xd, n) => { - // Dict - let len = self.read_object_len(n)?; - let key_refs = self.read_refs(len)?; - let value_refs = self.read_refs(len)?; - - let mut object_refs = self.allocate_vec(len * 2, self.ref_size as usize)?; - let len = key_refs.len(); - for i in 1..len + 1 { - // Reverse so we can pop off the end of the stack in order - object_refs.push(value_refs[len - i]); - object_refs.push(key_refs[len - i]); - } - - self.stack.push(StackItem { - ty: StackType::Dict, - object_refs: object_refs, - }); - - Some(PlistEvent::StartDictionary(Some(len as u64))) - } - (_, _) => return Err(Error::InvalidData), - }; - - // Prevent stack overflows when recursively parsing plist. - if self.stack.len() > self.max_stack_depth { - return Err(Error::InvalidData); - } - - Ok(result) - } -} - -impl Iterator for EventReader { - type Item = Result; - - fn next(&mut self) -> Option> { - if self.finished { - None - } else { - match self.read_next() { - Ok(Some(event)) => Some(Ok(event)), - Err(err) => { - self.finished = true; - Some(Err(err)) - } - Ok(None) => { - self.finished = true; - None - } - } - } - } -} - -#[cfg(test)] -mod tests { - use humantime::parse_rfc3339_weak; - use std::fs::File; - use std::path::Path; - - use super::*; - use PlistEvent; - - #[test] - fn streaming_parser() { - use PlistEvent::*; - - let reader = File::open(&Path::new("./tests/data/binary.plist")).unwrap(); - let streaming_parser = EventReader::new(reader); - let events: Vec = streaming_parser.map(|e| e.unwrap()).collect(); - - let comparison = &[ - StartDictionary(Some(6)), - StringValue("Lines".to_owned()), - StartArray(Some(2)), - StringValue("It is a tale told by an idiot,".to_owned()), - StringValue("Full of sound and fury, signifying nothing.".to_owned()), - EndArray, - StringValue("Death".to_owned()), - IntegerValue(1564), - StringValue("Height".to_owned()), - RealValue(1.60), - StringValue("Birthdate".to_owned()), - DateValue(parse_rfc3339_weak("1981-05-16 11:32:06").unwrap().into()), - StringValue("Author".to_owned()), - StringValue("William Shakespeare".to_owned()), - StringValue("Data".to_owned()), - DataValue(vec![0, 0, 0, 190, 0, 0, 0, 3, 0, 0, 0, 30, 0, 0, 0]), - EndDictionary, - ]; - - assert_eq!(events, comparison); - } - - #[test] - fn utf16_plist() { - use PlistEvent::*; - - let reader = File::open(&Path::new("./tests/data/utf16_bplist.plist")).unwrap(); - let streaming_parser = EventReader::new(reader); - let mut events: Vec = streaming_parser.map(|e| e.unwrap()).collect(); - - assert_eq!(events[2], StringValue("\u{2605} or better".to_owned())); - - let poem = if let StringValue(ref mut poem) = events[4] { - poem - } else { - panic!("not a string") - }; - assert_eq!(poem.len(), 643); - assert_eq!(poem.pop().unwrap(), '\u{2605}'); - } -} diff --git a/src/builder.rs b/src/builder.rs index 6f448e8..8cd580e 100644 --- a/src/builder.rs +++ b/src/builder.rs @@ -1,13 +1,14 @@ use std::collections::BTreeMap; -use {Error, Plist, PlistEvent, Result, u64_option_to_usize}; +use events::Event; +use {u64_option_to_usize, Error, Result, Value}; pub struct Builder { stream: T, - token: Option, + token: Option, } -impl>> Builder { +impl>> Builder { pub fn new(stream: T) -> Builder { Builder { stream: stream, @@ -15,7 +16,7 @@ impl>> Builder { } } - pub fn build(mut self) -> Result { + pub fn build(mut self) -> Result { self.bump()?; let plist = self.build_value()?; @@ -37,27 +38,27 @@ impl>> Builder { Ok(()) } - fn build_value(&mut self) -> Result { + fn build_value(&mut self) -> Result { match self.token.take() { - Some(PlistEvent::StartArray(len)) => Ok(Plist::Array(self.build_array(len)?)), - Some(PlistEvent::StartDictionary(len)) => Ok(Plist::Dictionary(self.build_dict(len)?)), + Some(Event::StartArray(len)) => Ok(Value::Array(self.build_array(len)?)), + Some(Event::StartDictionary(len)) => Ok(Value::Dictionary(self.build_dict(len)?)), - Some(PlistEvent::BooleanValue(b)) => Ok(Plist::Boolean(b)), - Some(PlistEvent::DataValue(d)) => Ok(Plist::Data(d)), - Some(PlistEvent::DateValue(d)) => Ok(Plist::Date(d)), - Some(PlistEvent::IntegerValue(i)) => Ok(Plist::Integer(i)), - Some(PlistEvent::RealValue(f)) => Ok(Plist::Real(f)), - Some(PlistEvent::StringValue(s)) => Ok(Plist::String(s)), + Some(Event::BooleanValue(b)) => Ok(Value::Boolean(b)), + Some(Event::DataValue(d)) => Ok(Value::Data(d)), + Some(Event::DateValue(d)) => Ok(Value::Date(d)), + Some(Event::IntegerValue(i)) => Ok(Value::Integer(i)), + Some(Event::RealValue(f)) => Ok(Value::Real(f)), + Some(Event::StringValue(s)) => Ok(Value::String(s)), - Some(PlistEvent::EndArray) => Err(Error::InvalidData), - Some(PlistEvent::EndDictionary) => Err(Error::InvalidData), + Some(Event::EndArray) => Err(Error::InvalidData), + Some(Event::EndDictionary) => Err(Error::InvalidData), // The stream should not have ended here None => Err(Error::InvalidData), } } - fn build_array(&mut self, len: Option) -> Result> { + fn build_array(&mut self, len: Option) -> Result> { let len = u64_option_to_usize(len)?; let mut values = match len { Some(len) => Vec::with_capacity(len), @@ -66,7 +67,7 @@ impl>> Builder { loop { self.bump()?; - if let Some(PlistEvent::EndArray) = self.token { + if let Some(Event::EndArray) = self.token { self.token.take(); return Ok(values); } @@ -74,14 +75,14 @@ impl>> Builder { } } - fn build_dict(&mut self, _len: Option) -> Result> { + fn build_dict(&mut self, _len: Option) -> Result> { let mut values = BTreeMap::new(); loop { self.bump()?; match self.token.take() { - Some(PlistEvent::EndDictionary) => return Ok(values), - Some(PlistEvent::StringValue(s)) => { + Some(Event::EndDictionary) => return Ok(values), + Some(Event::StringValue(s)) => { self.bump()?; values.insert(s, self.build_value()?); } @@ -99,14 +100,12 @@ mod tests { use std::collections::BTreeMap; use super::*; - use Plist; + use events::Event::*; + use Value; #[test] fn builder() { - use PlistEvent::*; - // Input - let events = vec![ StartDictionary(None), StringValue("Author".to_owned()), @@ -127,22 +126,21 @@ mod tests { let plist = builder.build(); // Expected output - let mut lines = Vec::new(); - lines.push(Plist::String("It is a tale told by an idiot,".to_owned())); - lines.push(Plist::String( + lines.push(Value::String("It is a tale told by an idiot,".to_owned())); + lines.push(Value::String( "Full of sound and fury, signifying nothing.".to_owned(), )); let mut dict = BTreeMap::new(); dict.insert( "Author".to_owned(), - Plist::String("William Shakespeare".to_owned()), + Value::String("William Shakespeare".to_owned()), ); - dict.insert("Lines".to_owned(), Plist::Array(lines)); - dict.insert("Birthdate".to_owned(), Plist::Integer(1564)); - dict.insert("Height".to_owned(), Plist::Real(1.60)); + dict.insert("Lines".to_owned(), Value::Array(lines)); + dict.insert("Birthdate".to_owned(), Value::Integer(1564)); + dict.insert("Height".to_owned(), Value::Real(1.60)); - assert_eq!(plist.unwrap(), Plist::Dictionary(dict)); + assert_eq!(plist.unwrap(), Value::Dictionary(dict)); } } diff --git a/src/date.rs b/src/date.rs index 509dfac..3c83c9b 100644 --- a/src/date.rs +++ b/src/date.rs @@ -70,8 +70,8 @@ impl Into for Date { #[cfg(feature = "serde")] pub mod serde_impls { - use serde_base::de::{Deserialize, Deserializer, Error, Unexpected, Visitor}; - use serde_base::ser::{Serialize, Serializer}; + use serde::de::{Deserialize, Deserializer, Error, Unexpected, Visitor}; + use serde::ser::{Serialize, Serializer}; use std::fmt; use Date; diff --git a/src/de.rs b/src/de.rs new file mode 100644 index 0000000..148b7b7 --- /dev/null +++ b/src/de.rs @@ -0,0 +1,393 @@ +use serde::de; +use std::fmt::Display; +use std::io::{Read, Seek}; +use std::iter::Peekable; + +use events::{self, Event}; +use {u64_option_to_usize, Error}; + +macro_rules! expect { + ($next:expr, $pat:pat) => { + match $next { + Some(Ok(v @ $pat)) => v, + None => return Err(Error::UnexpectedEof), + _ => return Err(event_mismatch_error()), + } + }; + ($next:expr, $pat:pat => $save:expr) => { + match $next { + Some(Ok($pat)) => $save, + None => return Err(Error::UnexpectedEof), + _ => return Err(event_mismatch_error()), + } + }; +} + +macro_rules! try_next { + ($next:expr) => { + match $next { + Some(Ok(v)) => v, + Some(Err(_)) => return Err(event_mismatch_error()), + None => return Err(Error::UnexpectedEof), + } + }; +} + +fn event_mismatch_error() -> Error { + Error::InvalidData +} + +impl de::Error for Error { + fn custom(msg: T) -> Self { + Error::Serde(msg.to_string()) + } +} + +pub struct Deserializer +where + I: IntoIterator>, +{ + events: Peekable<::IntoIter>, +} + +impl Deserializer +where + I: IntoIterator>, +{ + pub fn new(iter: I) -> Deserializer { + Deserializer { + events: iter.into_iter().peekable(), + } + } +} + +impl<'de, 'a, I> de::Deserializer<'de> for &'a mut Deserializer +where + I: IntoIterator>, +{ + type Error = Error; + + fn deserialize_any(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + match try_next!(self.events.next()) { + Event::StartArray(len) => { + let len = u64_option_to_usize(len)?; + let ret = visitor.visit_seq(MapAndSeqAccess::new(self, false, len))?; + expect!(self.events.next(), Event::EndArray); + Ok(ret) + } + Event::EndArray => Err(event_mismatch_error()), + + Event::StartDictionary(len) => { + let len = u64_option_to_usize(len)?; + let ret = visitor.visit_map(MapAndSeqAccess::new(self, false, len))?; + expect!(self.events.next(), Event::EndDictionary); + Ok(ret) + } + Event::EndDictionary => Err(event_mismatch_error()), + + Event::BooleanValue(v) => visitor.visit_bool(v), + Event::DataValue(v) => visitor.visit_byte_buf(v), + Event::DateValue(v) => visitor.visit_string(v.to_rfc3339()), + Event::IntegerValue(v) if v.is_positive() => visitor.visit_u64(v as u64), + Event::IntegerValue(v) => visitor.visit_i64(v as i64), + Event::RealValue(v) => visitor.visit_f64(v), + Event::StringValue(v) => visitor.visit_string(v), + } + } + + 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(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + expect!(self.events.next(), Event::StringValue(_)); + visitor.visit_unit() + } + + fn deserialize_option(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + expect!(self.events.next(), Event::StartDictionary(_)); + + let ret = match try_next!(self.events.next()) { + Event::StringValue(ref s) if &s[..] == "None" => { + expect!(self.events.next(), Event::StringValue(_)); + visitor.visit_none::()? + } + Event::StringValue(ref s) if &s[..] == "Some" => visitor.visit_some(&mut *self)?, + _ => return Err(event_mismatch_error()), + }; + + expect!(self.events.next(), Event::EndDictionary); + + Ok(ret) + } + + fn deserialize_newtype_struct( + self, + _name: &'static str, + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + visitor.visit_newtype_struct(self) + } + + fn deserialize_struct( + self, + _name: &'static str, + _fields: &'static [&'static str], + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + expect!(self.events.next(), Event::StartDictionary(_)); + let ret = visitor.visit_map(MapAndSeqAccess::new(self, true, None))?; + expect!(self.events.next(), Event::EndDictionary); + Ok(ret) + } + + fn deserialize_enum( + self, + _enum: &'static str, + _variants: &'static [&'static str], + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + expect!(self.events.next(), Event::StartDictionary(_)); + let ret = visitor.visit_enum(&mut *self)?; + expect!(self.events.next(), Event::EndDictionary); + Ok(ret) + } +} + +impl<'de, 'a, I> de::EnumAccess<'de> for &'a mut Deserializer +where + I: IntoIterator>, +{ + type Error = Error; + type Variant = Self; + + fn variant_seed(self, seed: V) -> Result<(V::Value, Self), Self::Error> + where + V: de::DeserializeSeed<'de>, + { + Ok((seed.deserialize(&mut *self)?, self)) + } +} + +impl<'de, 'a, I> de::VariantAccess<'de> for &'a mut Deserializer +where + I: IntoIterator>, +{ + type Error = Error; + + fn unit_variant(self) -> Result<(), Self::Error> { + <() as de::Deserialize>::deserialize(self) + } + + fn newtype_variant_seed(self, seed: T) -> Result + where + T: de::DeserializeSeed<'de>, + { + seed.deserialize(self) + } + + fn tuple_variant(self, len: usize, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + ::deserialize_tuple(self, len, visitor) + } + + fn struct_variant( + self, + fields: &'static [&'static str], + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + let name = ""; + ::deserialize_struct(self, name, fields, visitor) + } +} + +pub struct StructValueDeserializer<'a, I: 'a> +where + I: IntoIterator>, +{ + de: &'a mut Deserializer, +} + +impl<'de, 'a, I> de::Deserializer<'de> for StructValueDeserializer<'a, I> +where + I: IntoIterator>, +{ + type Error = Error; + + fn deserialize_any(self, visitor: V) -> Result + 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(self, visitor: V) -> Result + where + V: de::Visitor<'de>, + { + self.de.deserialize_unit(visitor) + } + + fn deserialize_option(self, visitor: V) -> Result + 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( + self, + name: &'static str, + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + self.de.deserialize_newtype_struct(name, visitor) + } + + fn deserialize_struct( + self, + name: &'static str, + fields: &'static [&'static str], + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + self.de.deserialize_struct(name, fields, visitor) + } + + fn deserialize_enum( + self, + enum_: &'static str, + variants: &'static [&'static str], + visitor: V, + ) -> Result + where + V: de::Visitor<'de>, + { + self.de.deserialize_enum(enum_, variants, visitor) + } +} + +struct MapAndSeqAccess<'a, I> +where + I: 'a + IntoIterator>, +{ + de: &'a mut Deserializer, + is_struct: bool, + remaining: Option, +} + +impl<'a, I> MapAndSeqAccess<'a, I> +where + I: 'a + IntoIterator>, +{ + fn new( + de: &'a mut Deserializer, + is_struct: bool, + len: Option, + ) -> MapAndSeqAccess<'a, I> { + MapAndSeqAccess { + de: de, + is_struct: is_struct, + remaining: len, + } + } +} + +impl<'de, 'a, I> de::SeqAccess<'de> for MapAndSeqAccess<'a, I> +where + I: 'a + IntoIterator>, +{ + type Error = Error; + + fn next_element_seed(&mut self, seed: T) -> Result, Self::Error> + where + T: de::DeserializeSeed<'de>, + { + if let Some(&Ok(Event::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 { + self.remaining + } +} + +impl<'de, 'a, I> de::MapAccess<'de> for MapAndSeqAccess<'a, I> +where + I: 'a + IntoIterator>, +{ + type Error = Error; + + fn next_key_seed(&mut self, seed: K) -> Result, Self::Error> + where + K: de::DeserializeSeed<'de>, + { + if let Some(&Ok(Event::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(&mut self, seed: V) -> Result + where + V: de::DeserializeSeed<'de>, + { + if self.is_struct { + seed.deserialize(StructValueDeserializer { de: &mut *self.de }) + } else { + seed.deserialize(&mut *self.de) + } + } + + fn size_hint(&self) -> Option { + self.remaining + } +} + +pub fn deserialize(reader: R) -> Result { + let reader = events::Reader::new(reader); + let mut de = Deserializer::new(reader); + de::Deserialize::deserialize(&mut de) +} diff --git a/src/events/binary_reader.rs b/src/events/binary_reader.rs new file mode 100644 index 0000000..e077904 --- /dev/null +++ b/src/events/binary_reader.rs @@ -0,0 +1,385 @@ +use byteorder::{BigEndian, ReadBytesExt}; +use std::io::{Read, Seek, SeekFrom}; +use std::mem::size_of; +use std::string::{FromUtf16Error, FromUtf8Error}; + +use events::Event; +use {u64_to_usize, Date, Error, Result}; + +impl From for Error { + fn from(_: FromUtf8Error) -> Error { + Error::InvalidData + } +} + +impl From for Error { + fn from(_: FromUtf16Error) -> Error { + Error::InvalidData + } +} + +struct StackItem { + object_refs: Vec, + ty: StackType, +} + +enum StackType { + Array, + Dict, + Root, +} + +/// https://opensource.apple.com/source/CF/CF-550/CFBinaryPList.c +/// https://hg.python.org/cpython/file/3.4/Lib/plistlib.py +pub struct BinaryReader { + stack: Vec, + object_offsets: Vec, + reader: R, + ref_size: u8, + finished: bool, + // The largest single allocation allowed for this Plist. + // Equal to the number of bytes in the Plist minus the magic and trailer. + max_allocation_bytes: usize, + // The maximum number of nested arrays and dicts allowed in the plist. + max_stack_depth: usize, + // The maximum number of objects that can be created. Default 10 * object_offsets.len(). + // Binary plists can contain circular references. + max_objects: usize, + // The number of objects created so far. + current_objects: usize, +} + +impl BinaryReader { + pub fn new(reader: R) -> BinaryReader { + BinaryReader { + stack: Vec::new(), + object_offsets: Vec::new(), + reader: reader, + ref_size: 0, + finished: false, + max_allocation_bytes: 0, + max_stack_depth: 200, + max_objects: 0, + current_objects: 0, + } + } + + fn can_allocate(&self, len: u64, size: usize) -> bool { + let byte_len = len.saturating_mul(size as u64); + byte_len <= self.max_allocation_bytes as u64 + } + + fn allocate_vec(&self, len: u64, size: usize) -> Result> { + if self.can_allocate(len, size) { + Ok(Vec::with_capacity(len as usize)) + } else { + Err(Error::InvalidData) + } + } + + fn read_trailer(&mut self) -> Result<()> { + self.reader.seek(SeekFrom::Start(0))?; + let mut magic = [0; 8]; + self.reader.read_exact(&mut magic)?; + if &magic != b"bplist00" { + return Err(Error::InvalidData); + } + + // Trailer starts with 6 bytes of padding + let trailer_start = self.reader.seek(SeekFrom::End(-32 + 6))?; + + let offset_size = self.reader.read_u8()?; + match offset_size { + 1 | 2 | 4 | 8 => (), + _ => return Err(Error::InvalidData), + } + + self.ref_size = self.reader.read_u8()?; + match self.ref_size { + 1 | 2 | 4 | 8 => (), + _ => return Err(Error::InvalidData), + } + + let num_objects = self.reader.read_u64::()?; + let top_object = self.reader.read_u64::()?; + let offset_table_offset = self.reader.read_u64::()?; + + // File size minus trailer and header + // Truncated to max(usize) + self.max_allocation_bytes = trailer_start.saturating_sub(8) as usize; + + // Read offset table + self.reader.seek(SeekFrom::Start(offset_table_offset))?; + self.object_offsets = self.read_ints(num_objects, offset_size)?; + + self.max_objects = self.object_offsets.len() * 10; + + // Seek to top object + self.stack.push(StackItem { + object_refs: vec![top_object], + ty: StackType::Root, + }); + + Ok(()) + } + + fn read_ints(&mut self, len: u64, size: u8) -> Result> { + let mut ints = self.allocate_vec(len, size as usize)?; + for _ in 0..len { + match size { + 1 => ints.push(self.reader.read_u8()? as u64), + 2 => ints.push(self.reader.read_u16::()? as u64), + 4 => ints.push(self.reader.read_u32::()? as u64), + 8 => ints.push(self.reader.read_u64::()? as u64), + _ => return Err(Error::InvalidData), + } + } + Ok(ints) + } + + fn read_refs(&mut self, len: u64) -> Result> { + let ref_size = self.ref_size; + self.read_ints(len, ref_size) + } + + fn read_object_len(&mut self, len: u8) -> Result { + if (len & 0x0f) == 0x0f { + let len_power_of_two = self.reader.read_u8()? & 0x03; + Ok(match len_power_of_two { + 0 => self.reader.read_u8()? as u64, + 1 => self.reader.read_u16::()? as u64, + 2 => self.reader.read_u32::()? as u64, + 3 => self.reader.read_u64::()?, + _ => return Err(Error::InvalidData), + }) + } else { + Ok(len as u64) + } + } + + fn read_data(&mut self, len: u64) -> Result> { + let mut data = self.allocate_vec(len, size_of::())?; + data.resize(len as usize, 0); + self.reader.read_exact(&mut data)?; + Ok(data) + } + + fn seek_to_object(&mut self, object_ref: u64) -> Result { + let object_ref = u64_to_usize(object_ref)?; + let offset = *self + .object_offsets + .get(object_ref) + .ok_or(Error::InvalidData)?; + Ok(self.reader.seek(SeekFrom::Start(offset))?) + } + + fn read_next(&mut self) -> Result> { + if self.ref_size == 0 { + // Initialise here rather than in new + self.read_trailer()?; + } + + let object_ref = match self.stack.last_mut() { + Some(stack_item) => stack_item.object_refs.pop(), + // Reached the end of the plist + None => return Ok(None), + }; + + match object_ref { + Some(object_ref) => { + if self.current_objects > self.max_objects { + return Err(Error::InvalidData); + } + self.current_objects += 1; + self.seek_to_object(object_ref)?; + } + None => { + // We're at the end of an array or dict. Pop the top stack item and return + let item = self.stack.pop().unwrap(); + match item.ty { + StackType::Array => return Ok(Some(Event::EndArray)), + StackType::Dict => return Ok(Some(Event::EndDictionary)), + // We're at the end of the plist + StackType::Root => return Ok(None), + } + } + } + + let token = self.reader.read_u8()?; + let ty = (token & 0xf0) >> 4; + let size = token & 0x0f; + + let result = match (ty, size) { + (0x0, 0x00) => return Err(Error::InvalidData), // null + (0x0, 0x08) => Some(Event::BooleanValue(false)), + (0x0, 0x09) => Some(Event::BooleanValue(true)), + (0x0, 0x0f) => return Err(Error::InvalidData), // fill + (0x1, 0) => Some(Event::IntegerValue(self.reader.read_u8()? as i64)), + (0x1, 1) => Some(Event::IntegerValue( + self.reader.read_u16::()? as i64 + )), + (0x1, 2) => Some(Event::IntegerValue( + self.reader.read_u32::()? as i64 + )), + (0x1, 3) => Some(Event::IntegerValue(self.reader.read_i64::()?)), + (0x1, 4) => return Err(Error::InvalidData), // 128 bit int + (0x1, _) => return Err(Error::InvalidData), // variable length int + (0x2, 2) => Some(Event::RealValue(self.reader.read_f32::()? as f64)), + (0x2, 3) => Some(Event::RealValue(self.reader.read_f64::()?)), + (0x2, _) => return Err(Error::InvalidData), // odd length float + (0x3, 3) => { + // Date. Seconds since 1/1/2001 00:00:00. + let secs = self.reader.read_f64::()?; + Some(Event::DateValue(Date::from_seconds_since_plist_epoch( + secs, + )?)) + } + (0x4, n) => { + // Data + let len = self.read_object_len(n)?; + Some(Event::DataValue(self.read_data(len)?)) + } + (0x5, n) => { + // ASCII string + let len = self.read_object_len(n)?; + let raw = self.read_data(len)?; + let string = String::from_utf8(raw)?; + Some(Event::StringValue(string)) + } + (0x6, n) => { + // UTF-16 string + let len_utf16_codepoints = self.read_object_len(n)?; + let mut raw_utf16 = self.allocate_vec(len_utf16_codepoints, size_of::())?; + + for _ in 0..len_utf16_codepoints { + raw_utf16.push(self.reader.read_u16::()?); + } + + let string = String::from_utf16(&raw_utf16)?; + Some(Event::StringValue(string)) + } + (0xa, n) => { + // Array + let len = self.read_object_len(n)?; + let mut object_refs = self.read_refs(len)?; + // Reverse so we can pop off the end of the stack in order + object_refs.reverse(); + + self.stack.push(StackItem { + ty: StackType::Array, + object_refs: object_refs, + }); + + Some(Event::StartArray(Some(len))) + } + (0xd, n) => { + // Dict + let len = self.read_object_len(n)?; + let key_refs = self.read_refs(len)?; + let value_refs = self.read_refs(len)?; + + let mut object_refs = self.allocate_vec(len * 2, self.ref_size as usize)?; + let len = key_refs.len(); + for i in 1..len + 1 { + // Reverse so we can pop off the end of the stack in order + object_refs.push(value_refs[len - i]); + object_refs.push(key_refs[len - i]); + } + + self.stack.push(StackItem { + ty: StackType::Dict, + object_refs: object_refs, + }); + + Some(Event::StartDictionary(Some(len as u64))) + } + (_, _) => return Err(Error::InvalidData), + }; + + // Prevent stack overflows when recursively parsing plist. + if self.stack.len() > self.max_stack_depth { + return Err(Error::InvalidData); + } + + Ok(result) + } +} + +impl Iterator for BinaryReader { + type Item = Result; + + fn next(&mut self) -> Option> { + if self.finished { + None + } else { + match self.read_next() { + Ok(Some(event)) => Some(Ok(event)), + Err(err) => { + self.finished = true; + Some(Err(err)) + } + Ok(None) => { + self.finished = true; + None + } + } + } + } +} + +#[cfg(test)] +mod tests { + use humantime::parse_rfc3339_weak; + use std::fs::File; + use std::path::Path; + + use super::*; + use events::Event; + use events::Event::*; + + #[test] + fn streaming_parser() { + let reader = File::open(&Path::new("./tests/data/binary.plist")).unwrap(); + let streaming_parser = BinaryReader::new(reader); + let events: Vec = streaming_parser.map(|e| e.unwrap()).collect(); + + let comparison = &[ + StartDictionary(Some(6)), + StringValue("Lines".to_owned()), + StartArray(Some(2)), + StringValue("It is a tale told by an idiot,".to_owned()), + StringValue("Full of sound and fury, signifying nothing.".to_owned()), + EndArray, + StringValue("Death".to_owned()), + IntegerValue(1564), + StringValue("Height".to_owned()), + RealValue(1.60), + StringValue("Birthdate".to_owned()), + DateValue(parse_rfc3339_weak("1981-05-16 11:32:06").unwrap().into()), + StringValue("Author".to_owned()), + StringValue("William Shakespeare".to_owned()), + StringValue("Data".to_owned()), + DataValue(vec![0, 0, 0, 190, 0, 0, 0, 3, 0, 0, 0, 30, 0, 0, 0]), + EndDictionary, + ]; + + assert_eq!(events, comparison); + } + + #[test] + fn utf16_plist() { + let reader = File::open(&Path::new("./tests/data/utf16_bplist.plist")).unwrap(); + let streaming_parser = BinaryReader::new(reader); + let mut events: Vec = streaming_parser.map(|e| e.unwrap()).collect(); + + assert_eq!(events[2], StringValue("\u{2605} or better".to_owned())); + + let poem = if let StringValue(ref mut poem) = events[4] { + poem + } else { + panic!("not a string") + }; + assert_eq!(poem.len(), 643); + assert_eq!(poem.pop().unwrap(), '\u{2605}'); + } +} diff --git a/src/events/mod.rs b/src/events/mod.rs new file mode 100644 index 0000000..b933ceb --- /dev/null +++ b/src/events/mod.rs @@ -0,0 +1,95 @@ +mod binary_reader; +pub use self::binary_reader::BinaryReader; + +mod xml_reader; +pub use self::xml_reader::XmlReader; + +mod xml_writer; +pub use self::xml_writer::XmlWriter; + +use std::io::{Read, Seek, SeekFrom}; +use {Date, Result}; + +/// An encoding of a plist as a flat structure. +/// +/// Output by the event readers. +/// +/// Dictionary keys and values are represented as pairs of values e.g.: +/// +/// ```ignore rust +/// StartDictionary +/// StringValue("Height") // Key +/// RealValue(181.2) // Value +/// StringValue("Age") // Key +/// IntegerValue(28) // Value +/// EndDictionary +/// ``` +#[derive(Clone, Debug, PartialEq)] +pub enum Event { + // While the length of an array or dict cannot be feasably greater than max(usize) this better + // conveys the concept of an effectively unbounded event stream. + StartArray(Option), + EndArray, + + StartDictionary(Option), + EndDictionary, + + BooleanValue(bool), + DataValue(Vec), + DateValue(Date), + IntegerValue(i64), + RealValue(f64), + StringValue(String), +} + +pub struct Reader(ReaderInner); + +enum ReaderInner { + Uninitialized(Option), + Xml(XmlReader), + Binary(BinaryReader), +} + +impl Reader { + pub fn new(reader: R) -> Reader { + Reader(ReaderInner::Uninitialized(Some(reader))) + } + + fn is_binary(reader: &mut R) -> Result { + reader.seek(SeekFrom::Start(0))?; + let mut magic = [0; 8]; + reader.read_exact(&mut magic)?; + reader.seek(SeekFrom::Start(0))?; + + Ok(&magic == b"bplist00") + } +} + +impl Iterator for Reader { + type Item = Result; + + fn next(&mut self) -> Option> { + let mut reader = match self.0 { + ReaderInner::Xml(ref mut parser) => return parser.next(), + ReaderInner::Binary(ref mut parser) => return parser.next(), + ReaderInner::Uninitialized(ref mut reader) => reader.take().unwrap(), + }; + + let event_reader = match Reader::is_binary(&mut reader) { + Ok(true) => ReaderInner::Binary(BinaryReader::new(reader)), + Ok(false) => ReaderInner::Xml(XmlReader::new(reader)), + Err(err) => { + ::std::mem::replace(&mut self.0, ReaderInner::Uninitialized(Some(reader))); + return Some(Err(err)); + } + }; + + ::std::mem::replace(&mut self.0, event_reader); + + self.next() + } +} + +pub trait Writer { + fn write(&mut self, event: &Event) -> Result<()>; +} diff --git a/src/events/xml_reader.rs b/src/events/xml_reader.rs new file mode 100644 index 0000000..46e0062 --- /dev/null +++ b/src/events/xml_reader.rs @@ -0,0 +1,199 @@ +use base64; +use std::io::Read; +use std::str::FromStr; +use xml_rs::reader::{EventReader, ParserConfig, XmlEvent}; + +use events::Event; +use {Date, Error, Result}; + +pub struct XmlReader { + xml_reader: EventReader, + queued_event: Option, + element_stack: Vec, + finished: bool, +} + +impl XmlReader { + pub fn new(reader: R) -> XmlReader { + let config = ParserConfig::new() + .trim_whitespace(false) + .whitespace_to_characters(true) + .cdata_to_characters(true) + .ignore_comments(true) + .coalesce_characters(true); + + XmlReader { + xml_reader: EventReader::new_with_config(reader, config), + queued_event: None, + element_stack: Vec::new(), + finished: false, + } + } + + fn read_content(&mut self, f: F) -> Result + where + F: FnOnce(String) -> Result, + { + match self.xml_reader.next() { + Ok(XmlEvent::Characters(s)) => f(s), + Ok(event @ XmlEvent::EndElement { .. }) => { + self.queued_event = Some(event); + f("".to_owned()) + } + _ => Err(Error::InvalidData), + } + } + + fn next_event(&mut self) -> ::std::result::Result { + if let Some(event) = self.queued_event.take() { + Ok(event) + } else { + self.xml_reader.next().map_err(|_| ()) + } + } + + fn read_next(&mut self) -> Option> { + loop { + match self.next_event() { + Ok(XmlEvent::StartElement { name, .. }) => { + // Add the current element to the element stack + self.element_stack.push(name.local_name.clone()); + + match &name.local_name[..] { + "plist" => (), + "array" => return Some(Ok(Event::StartArray(None))), + "dict" => return Some(Ok(Event::StartDictionary(None))), + "key" => return Some(self.read_content(|s| Ok(Event::StringValue(s)))), + "true" => return Some(Ok(Event::BooleanValue(true))), + "false" => return Some(Ok(Event::BooleanValue(false))), + "data" => { + return Some(self.read_content(|s| { + let data = base64::decode_config(&s, base64::MIME) + .map_err(|_| Error::InvalidData)?; + Ok(Event::DataValue(data)) + })) + } + "date" => { + return Some( + self.read_content(|s| { + Ok(Event::DateValue(Date::from_rfc3339(&s)?)) + }), + ) + } + "integer" => { + return Some(self.read_content(|s| match FromStr::from_str(&s) { + Ok(i) => Ok(Event::IntegerValue(i)), + Err(_) => Err(Error::InvalidData), + })) + } + "real" => { + return Some(self.read_content(|s| match FromStr::from_str(&s) { + Ok(f) => Ok(Event::RealValue(f)), + Err(_) => Err(Error::InvalidData), + })) + } + "string" => return Some(self.read_content(|s| Ok(Event::StringValue(s)))), + _ => return Some(Err(Error::InvalidData)), + } + } + Ok(XmlEvent::EndElement { name, .. }) => { + // Check the corrent element is being closed + match self.element_stack.pop() { + Some(ref open_name) if &name.local_name == open_name => (), + Some(ref _open_name) => return Some(Err(Error::InvalidData)), + None => return Some(Err(Error::InvalidData)), + } + + match &name.local_name[..] { + "array" => return Some(Ok(Event::EndArray)), + "dict" => return Some(Ok(Event::EndDictionary)), + "plist" => (), + _ => (), + } + } + Ok(XmlEvent::EndDocument) => { + if self.element_stack.is_empty() { + return None; + } else { + return Some(Err(Error::UnexpectedEof)); + } + } + Err(_) => return Some(Err(Error::InvalidData)), + _ => (), + } + } + } +} + +impl Iterator for XmlReader { + type Item = Result; + + fn next(&mut self) -> Option> { + if self.finished { + None + } else { + match self.read_next() { + Some(Ok(event)) => Some(Ok(event)), + Some(Err(err)) => { + self.finished = true; + Some(Err(err)) + } + None => { + self.finished = true; + None + } + } + } + } +} + +#[cfg(test)] +mod tests { + use humantime::parse_rfc3339_weak; + use std::fs::File; + use std::path::Path; + + use super::*; + use events::Event; + use events::Event::*; + + #[test] + fn streaming_parser() { + let reader = File::open(&Path::new("./tests/data/xml.plist")).unwrap(); + let streaming_parser = XmlReader::new(reader); + let events: Vec = streaming_parser.map(|e| e.unwrap()).collect(); + + let comparison = &[ + StartDictionary(None), + StringValue("Author".to_owned()), + StringValue("William Shakespeare".to_owned()), + StringValue("Lines".to_owned()), + StartArray(None), + StringValue("It is a tale told by an idiot,".to_owned()), + StringValue("Full of sound and fury, signifying nothing.".to_owned()), + EndArray, + StringValue("Death".to_owned()), + IntegerValue(1564), + StringValue("Height".to_owned()), + RealValue(1.60), + StringValue("Data".to_owned()), + DataValue(vec![0, 0, 0, 190, 0, 0, 0, 3, 0, 0, 0, 30, 0, 0, 0]), + StringValue("Birthdate".to_owned()), + DateValue(parse_rfc3339_weak("1981-05-16 11:32:06").unwrap().into()), + StringValue("Blank".to_owned()), + StringValue("".to_owned()), + EndDictionary, + ]; + + assert_eq!(events, comparison); + } + + #[test] + fn bad_data() { + let reader = File::open(&Path::new("./tests/data/xml_error.plist")).unwrap(); + let streaming_parser = XmlReader::new(reader); + let events: Vec<_> = streaming_parser.collect(); + + assert!(events.last().unwrap().is_err()); + } +} diff --git a/src/events/xml_writer.rs b/src/events/xml_writer.rs new file mode 100644 index 0000000..f89ea81 --- /dev/null +++ b/src/events/xml_writer.rs @@ -0,0 +1,259 @@ +use base64; +use std::borrow::Cow; +use std::io::Write; +use xml_rs::name::Name; +use xml_rs::namespace::Namespace; +use xml_rs::writer::{EmitterConfig, Error as XmlWriterError, EventWriter, XmlEvent}; + +use events::{Event, Writer}; +use {Error, Result}; + +impl From for Error { + fn from(err: XmlWriterError) -> Error { + match err { + XmlWriterError::Io(err) => Error::Io(err), + _ => Error::InvalidData, + } + } +} + +enum Element { + Dictionary(DictionaryState), + Array, + Root, +} + +enum DictionaryState { + ExpectKey, + ExpectValue, +} + +pub struct XmlWriter { + xml_writer: EventWriter, + stack: Vec, + // Not very nice + empty_namespace: Namespace, +} + +impl XmlWriter { + pub fn new(writer: W) -> XmlWriter { + let config = EmitterConfig::new() + .line_separator("\n") + .indent_string("\t") + .perform_indent(true) + .write_document_declaration(false) + .normalize_empty_elements(true) + .cdata_to_characters(true) + .keep_element_names_stack(false) + .autopad_comments(true); + + XmlWriter { + xml_writer: EventWriter::new_with_config(writer, config), + stack: Vec::new(), + empty_namespace: Namespace::empty(), + } + } + + fn write_element_and_value(&mut self, name: &str, value: &str) -> Result<()> { + self.start_element(name)?; + self.write_value(value)?; + self.end_element(name)?; + Ok(()) + } + + fn start_element(&mut self, name: &str) -> Result<()> { + self.xml_writer.write(XmlEvent::StartElement { + name: Name::local(name), + attributes: Cow::Borrowed(&[]), + namespace: Cow::Borrowed(&self.empty_namespace), + })?; + Ok(()) + } + + fn end_element(&mut self, name: &str) -> Result<()> { + self.xml_writer.write(XmlEvent::EndElement { + name: Some(Name::local(name)), + })?; + Ok(()) + } + + fn write_value(&mut self, value: &str) -> Result<()> { + self.xml_writer.write(XmlEvent::Characters(value))?; + Ok(()) + } + + fn maybe_end_plist(&mut self) -> Result<()> { + // If there are no more open tags then write the element + if self.stack.len() == 1 { + // We didn't tell the xml_writer about the tag so we'll skip telling it + // about the tag as well. + self.xml_writer.inner_mut().write(b"\n")?; + if let Some(Element::Root) = self.stack.pop() { + } else { + return Err(Error::InvalidData); + } + } + Ok(()) + } + + pub fn write(&mut self, event: &Event) -> Result<()> { + ::write(self, event) + } +} + +impl Writer for XmlWriter { + fn write(&mut self, event: &Event) -> Result<()> { + match self.stack.pop() { + Some(Element::Dictionary(DictionaryState::ExpectKey)) => { + match *event { + Event::StringValue(ref value) => { + self.write_element_and_value("key", &*value)?; + self.stack + .push(Element::Dictionary(DictionaryState::ExpectValue)); + } + Event::EndDictionary => { + self.end_element("dict")?; + // We might be closing the last tag here as well + self.maybe_end_plist()?; + } + _ => return Err(Error::InvalidData), + }; + return Ok(()); + } + Some(Element::Dictionary(DictionaryState::ExpectValue)) => self + .stack + .push(Element::Dictionary(DictionaryState::ExpectKey)), + Some(other) => self.stack.push(other), + None => { + // Write prologue + let prologue = r#" + + +"#; + self.xml_writer.inner_mut().write(prologue.as_bytes())?; + + self.stack.push(Element::Root); + } + } + + match *event { + Event::StartArray(_) => { + self.start_element("array")?; + self.stack.push(Element::Array); + } + Event::EndArray => { + self.end_element("array")?; + if let Some(Element::Array) = self.stack.pop() { + } else { + return Err(Error::InvalidData); + } + } + + Event::StartDictionary(_) => { + self.start_element("dict")?; + self.stack + .push(Element::Dictionary(DictionaryState::ExpectKey)); + } + Event::EndDictionary => return Err(Error::InvalidData), + + Event::BooleanValue(true) => { + self.start_element("true")?; + self.end_element("true")?; + } + Event::BooleanValue(false) => { + self.start_element("false")?; + self.end_element("false")?; + } + Event::DataValue(ref value) => { + let base64_data = base64::encode_config(&value, base64::MIME); + self.write_element_and_value("data", &base64_data)?; + } + Event::DateValue(ref value) => { + self.write_element_and_value("date", &value.to_rfc3339())? + } + Event::IntegerValue(ref value) => { + self.write_element_and_value("integer", &value.to_string())? + } + Event::RealValue(ref value) => { + self.write_element_and_value("real", &value.to_string())? + } + Event::StringValue(ref value) => self.write_element_and_value("string", &*value)?, + }; + + self.maybe_end_plist()?; + + Ok(()) + } +} + +#[cfg(test)] +mod tests { + use humantime::parse_rfc3339_weak; + use std::io::Cursor; + + use super::*; + use events::Event::*; + + #[test] + fn streaming_parser() { + let plist = &[ + StartDictionary(None), + StringValue("Author".to_owned()), + StringValue("William Shakespeare".to_owned()), + StringValue("Lines".to_owned()), + StartArray(None), + StringValue("It is a tale told by an idiot,".to_owned()), + StringValue("Full of sound and fury, signifying nothing.".to_owned()), + EndArray, + StringValue("Death".to_owned()), + IntegerValue(1564), + StringValue("Height".to_owned()), + RealValue(1.60), + StringValue("Data".to_owned()), + DataValue(vec![0, 0, 0, 190, 0, 0, 0, 3, 0, 0, 0, 30, 0, 0, 0]), + StringValue("Birthdate".to_owned()), + DateValue(parse_rfc3339_weak("1981-05-16 11:32:06").unwrap().into()), + StringValue("Comment".to_owned()), + StringValue("2 < 3".to_owned()), // make sure characters are escaped + EndDictionary, + ]; + + let mut cursor = Cursor::new(Vec::new()); + + { + let mut plist_w = XmlWriter::new(&mut cursor); + + for item in plist { + plist_w.write(item).unwrap(); + } + } + + let comparison = " + + + +\tAuthor +\tWilliam Shakespeare +\tLines +\t +\t\tIt is a tale told by an idiot, +\t\tFull of sound and fury, signifying nothing. +\t +\tDeath +\t1564 +\tHeight +\t1.6 +\tData +\tAAAAvgAAAAMAAAAeAAAA +\tBirthdate +\t1981-05-16T11:32:06Z +\tComment +\t2 < 3 + +"; + + let s = String::from_utf8(cursor.into_inner()).unwrap(); + + assert_eq!(s, comparison); + } +} diff --git a/src/lib.rs b/src/lib.rs index ddcce58..c129400 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -20,14 +20,14 @@ //! ## Examples //! //! ```rust -//! use plist::Plist; +//! use plist::Value; //! use std::fs::File; //! //! let file = File::open("tests/data/xml.plist").unwrap(); -//! let plist = Plist::read(file).unwrap(); +//! let plist = Value::read(file).unwrap(); //! //! match plist { -//! Plist::Array(_array) => (), +//! Value::Array(_array) => (), //! _ => () //! } //! ``` @@ -40,7 +40,7 @@ //! //! # #[cfg(feature = "serde")] //! # fn main() { -//! use plist::serde::deserialize; +//! use plist::deserialize; //! use std::fs::File; //! //! #[derive(Deserialize)] @@ -63,57 +63,30 @@ extern crate byteorder; extern crate humantime; extern crate xml as xml_rs; -pub mod binary; -pub mod xml; +pub mod events; mod builder; mod date; -mod plist; +mod value; pub use date::Date; -pub use plist::Plist; +pub use value::Value; // Optional serde module #[cfg(feature = "serde")] #[macro_use] -extern crate serde as serde_base; +extern crate serde; #[cfg(feature = "serde")] -pub mod serde; +mod de; +#[cfg(feature = "serde")] +mod ser; +#[cfg(feature = "serde")] +pub use self::de::{deserialize, Deserializer}; +#[cfg(feature = "serde")] +pub use self::ser::{serialize_to_xml, Serializer}; use std::fmt; -use std::io::{self, Read, Seek, SeekFrom}; - -/// An encoding of a plist as a flat structure. -/// -/// Output by the event readers. -/// -/// Dictionary keys and values are represented as pairs of values e.g.: -/// -/// ```ignore rust -/// StartDictionary -/// StringValue("Height") // Key -/// RealValue(181.2) // Value -/// StringValue("Age") // Key -/// IntegerValue(28) // Value -/// EndDictionary -/// ``` -#[derive(Clone, Debug, PartialEq)] -pub enum PlistEvent { - // While the length of an array or dict cannot be feasably greater than max(usize) this better - // conveys the concept of an effectively unbounded event stream. - StartArray(Option), - EndArray, - - StartDictionary(Option), - EndDictionary, - - BooleanValue(bool), - DataValue(Vec), - DateValue(Date), - IntegerValue(i64), - RealValue(f64), - StringValue(String), -} +use std::io; type Result = ::std::result::Result; @@ -158,58 +131,6 @@ impl From for Error { } } -pub struct EventReader(EventReaderInner); - -enum EventReaderInner { - Uninitialized(Option), - Xml(xml::EventReader), - Binary(binary::EventReader), -} - -impl EventReader { - pub fn new(reader: R) -> EventReader { - EventReader(EventReaderInner::Uninitialized(Some(reader))) - } - - fn is_binary(reader: &mut R) -> Result { - reader.seek(SeekFrom::Start(0))?; - let mut magic = [0; 8]; - reader.read_exact(&mut magic)?; - reader.seek(SeekFrom::Start(0))?; - - Ok(&magic == b"bplist00") - } -} - -impl Iterator for EventReader { - type Item = Result; - - fn next(&mut self) -> Option> { - let mut reader = match self.0 { - EventReaderInner::Xml(ref mut parser) => return parser.next(), - EventReaderInner::Binary(ref mut parser) => return parser.next(), - EventReaderInner::Uninitialized(ref mut reader) => reader.take().unwrap(), - }; - - let event_reader = match EventReader::is_binary(&mut reader) { - Ok(true) => EventReaderInner::Binary(binary::EventReader::new(reader)), - Ok(false) => EventReaderInner::Xml(xml::EventReader::new(reader)), - Err(err) => { - ::std::mem::replace(&mut self.0, EventReaderInner::Uninitialized(Some(reader))); - return Some(Err(err)); - } - }; - - ::std::mem::replace(&mut self.0, event_reader); - - self.next() - } -} - -pub trait EventWriter { - fn write(&mut self, event: &PlistEvent) -> Result<()>; -} - fn u64_to_usize(len_u64: u64) -> Result { let len = len_u64 as usize; if len as u64 != len_u64 { diff --git a/src/plist.rs b/src/plist.rs deleted file mode 100644 index f0646f5..0000000 --- a/src/plist.rs +++ /dev/null @@ -1,376 +0,0 @@ -use std::collections::BTreeMap; -use std::io::{Read, Seek}; - -use {builder, Date, EventReader, PlistEvent, Result}; - -#[derive(Clone, Debug, PartialEq)] -pub enum Plist { - Array(Vec), - Dictionary(BTreeMap), - Boolean(bool), - Data(Vec), - Date(Date), - Real(f64), - Integer(i64), - String(String), -} - -impl Plist { - pub fn read(reader: R) -> Result { - let reader = EventReader::new(reader); - Plist::from_events(reader) - } - - pub fn from_events(events: T) -> Result - where - T: IntoIterator>, - { - let iter = events.into_iter(); - let builder = builder::Builder::new(iter); - builder.build() - } - - pub fn into_events(self) -> Vec { - let mut events = Vec::new(); - self.into_events_inner(&mut events); - events - } - - fn into_events_inner(self, events: &mut Vec) { - match self { - Plist::Array(array) => { - events.push(PlistEvent::StartArray(Some(array.len() as u64))); - for value in array { - value.into_events_inner(events); - } - events.push(PlistEvent::EndArray); - } - Plist::Dictionary(dict) => { - events.push(PlistEvent::StartDictionary(Some(dict.len() as u64))); - for (key, value) in dict { - events.push(PlistEvent::StringValue(key)); - value.into_events_inner(events); - } - events.push(PlistEvent::EndDictionary); - } - Plist::Boolean(value) => events.push(PlistEvent::BooleanValue(value)), - Plist::Data(value) => events.push(PlistEvent::DataValue(value)), - Plist::Date(value) => events.push(PlistEvent::DateValue(value)), - Plist::Real(value) => events.push(PlistEvent::RealValue(value)), - Plist::Integer(value) => events.push(PlistEvent::IntegerValue(value)), - Plist::String(value) => events.push(PlistEvent::StringValue(value)), - } - } - - /// If the `Plist` is an Array, returns the associated Vec. - /// Returns None otherwise. - pub fn as_array(&self) -> Option<&Vec> { - match *self { - Plist::Array(ref array) => Some(array), - _ => None, - } - } - - /// If the `Plist` is an Array, returns the associated mutable Vec. - /// Returns None otherwise. - pub fn as_array_mut(&mut self) -> Option<&mut Vec> { - match *self { - Plist::Array(ref mut array) => Some(array), - _ => None, - } - } - - /// If the `Plist` is a Dictionary, returns the associated BTreeMap. - /// Returns None otherwise. - pub fn as_dictionary(&self) -> Option<&BTreeMap> { - match *self { - Plist::Dictionary(ref map) => Some(map), - _ => None, - } - } - - /// If the `Plist` is a Dictionary, returns the associated mutable BTreeMap. - /// Returns None otherwise. - pub fn as_dictionary_mut(&mut self) -> Option<&mut BTreeMap> { - match *self { - Plist::Dictionary(ref mut map) => Some(map), - _ => None, - } - } - - /// If the `Plist` is a Boolean, returns the associated bool. - /// Returns None otherwise. - pub fn as_boolean(&self) -> Option { - match *self { - Plist::Boolean(v) => Some(v), - _ => None, - } - } - - /// If the `Plist` is a Data, returns the underlying Vec. - /// Returns None otherwise. - /// - /// This method consumes the `Plist`. If this is not desired, please use - /// `as_data` method. - pub fn into_data(self) -> Option> { - match self { - Plist::Data(data) => Some(data), - _ => None, - } - } - - /// If the `Plist` is a Data, returns the associated Vec. - /// Returns None otherwise. - pub fn as_data(&self) -> Option<&[u8]> { - match *self { - Plist::Data(ref data) => Some(data), - _ => None, - } - } - - /// If the `Plist` is a Date, returns the associated DateTime. - /// Returns None otherwise. - pub fn as_date(&self) -> Option<&Date> { - match *self { - Plist::Date(ref date) => Some(date), - _ => None, - } - } - - /// If the `Plist` is a Real, returns the associated f64. - /// Returns None otherwise. - pub fn as_real(&self) -> Option { - match *self { - Plist::Real(v) => Some(v), - _ => None, - } - } - - /// If the `Plist` is an Integer, returns the associated i64. - /// Returns None otherwise. - pub fn as_integer(&self) -> Option { - match *self { - Plist::Integer(v) => Some(v), - _ => None, - } - } - - /// If the `Plist` is a String, returns the underlying String. - /// Returns None otherwise. - /// - /// This method consumes the `Plist`. If this is not desired, please use - /// `as_string` method. - pub fn into_string(self) -> Option { - match self { - Plist::String(v) => Some(v), - _ => None, - } - } - - /// If the `Plist` is a String, returns the associated str. - /// Returns None otherwise. - pub fn as_string(&self) -> Option<&str> { - match *self { - Plist::String(ref v) => Some(v), - _ => None, - } - } -} - -impl From> for Plist { - fn from(from: Vec) -> Plist { - Plist::Array(from) - } -} - -impl From> for Plist { - fn from(from: BTreeMap) -> Plist { - Plist::Dictionary(from) - } -} - -impl From for Plist { - fn from(from: bool) -> Plist { - Plist::Boolean(from) - } -} - -impl<'a> From<&'a bool> for Plist { - fn from(from: &'a bool) -> Plist { - Plist::Boolean(*from) - } -} - -impl From for Plist { - fn from(from: Date) -> Plist { - Plist::Date(from) - } -} - -impl<'a> From<&'a Date> for Plist { - fn from(from: &'a Date) -> Plist { - Plist::Date(from.clone()) - } -} - -impl From for Plist { - fn from(from: f64) -> Plist { - Plist::Real(from) - } -} - -impl From for Plist { - fn from(from: f32) -> Plist { - Plist::Real(from as f64) - } -} - -impl From for Plist { - fn from(from: i64) -> Plist { - Plist::Integer(from) - } -} - -impl From for Plist { - fn from(from: i32) -> Plist { - Plist::Integer(from as i64) - } -} - -impl From for Plist { - fn from(from: i16) -> Plist { - Plist::Integer(from as i64) - } -} - -impl From for Plist { - fn from(from: i8) -> Plist { - Plist::Integer(from as i64) - } -} - -impl From for Plist { - fn from(from: u32) -> Plist { - Plist::Integer(from as i64) - } -} - -impl From for Plist { - fn from(from: u16) -> Plist { - Plist::Integer(from as i64) - } -} - -impl From for Plist { - fn from(from: u8) -> Plist { - Plist::Integer(from as i64) - } -} - -impl<'a> From<&'a f64> for Plist { - fn from(from: &'a f64) -> Plist { - Plist::Real(*from) - } -} - -impl<'a> From<&'a f32> for Plist { - fn from(from: &'a f32) -> Plist { - Plist::Real(*from as f64) - } -} - -impl<'a> From<&'a i64> for Plist { - fn from(from: &'a i64) -> Plist { - Plist::Integer(*from) - } -} - -impl<'a> From<&'a i32> for Plist { - fn from(from: &'a i32) -> Plist { - Plist::Integer(*from as i64) - } -} - -impl<'a> From<&'a i16> for Plist { - fn from(from: &'a i16) -> Plist { - Plist::Integer(*from as i64) - } -} - -impl<'a> From<&'a i8> for Plist { - fn from(from: &'a i8) -> Plist { - Plist::Integer(*from as i64) - } -} - -impl<'a> From<&'a u32> for Plist { - fn from(from: &'a u32) -> Plist { - Plist::Integer(*from as i64) - } -} - -impl<'a> From<&'a u16> for Plist { - fn from(from: &'a u16) -> Plist { - Plist::Integer(*from as i64) - } -} - -impl<'a> From<&'a u8> for Plist { - fn from(from: &'a u8) -> Plist { - Plist::Integer(*from as i64) - } -} - -impl From for Plist { - fn from(from: String) -> Plist { - Plist::String(from) - } -} - -impl<'a> From<&'a str> for Plist { - fn from(from: &'a str) -> Plist { - Plist::String(from.into()) - } -} - -#[cfg(test)] -mod tests { - use std::collections::BTreeMap; - use std::time::SystemTime; - - use {Date, Plist}; - - #[test] - fn test_plist_access() { - let vec = vec![Plist::Real(0.0)]; - let mut array = Plist::Array(vec.clone()); - assert_eq!(array.as_array(), Some(&vec.clone())); - assert_eq!(array.as_array_mut(), Some(&mut vec.clone())); - - let mut map = BTreeMap::new(); - map.insert("key1".to_owned(), Plist::String("value1".to_owned())); - let mut dict = Plist::Dictionary(map.clone()); - assert_eq!(dict.as_dictionary(), Some(&map.clone())); - assert_eq!(dict.as_dictionary_mut(), Some(&mut map.clone())); - - assert_eq!(Plist::Boolean(true).as_boolean(), Some(true)); - - let slice: &[u8] = &[1, 2, 3]; - assert_eq!(Plist::Data(slice.to_vec()).as_data(), Some(slice)); - assert_eq!( - Plist::Data(slice.to_vec()).into_data(), - Some(slice.to_vec()) - ); - - let date: Date = SystemTime::now().into(); - assert_eq!(Plist::Date(date.clone()).as_date(), Some(&date)); - - assert_eq!(Plist::Real(0.0).as_real(), Some(0.0)); - assert_eq!(Plist::Integer(1).as_integer(), Some(1)); - assert_eq!(Plist::String("2".to_owned()).as_string(), Some("2")); - assert_eq!( - Plist::String("t".to_owned()).into_string(), - Some("t".to_owned()) - ); - } -} diff --git a/src/ser.rs b/src/ser.rs new file mode 100644 index 0000000..4a2a42b --- /dev/null +++ b/src/ser.rs @@ -0,0 +1,712 @@ +use serde::ser; +use std::fmt::Display; +use std::io::Write; + +use date::serde_impls::DATE_NEWTYPE_STRUCT_NAME; +use events::{self, Event, Writer}; +use {Date, Error}; + +impl ser::Error for Error { + fn custom(msg: T) -> Self { + Error::Serde(msg.to_string()) + } +} + +pub struct Serializer { + writer: W, +} + +impl Serializer { + pub fn new(writer: W) -> Serializer { + Serializer { writer: writer } + } + + fn emit(&mut self, event: Event) -> Result<(), Error> { + self.writer.write(&event)?; + Ok(()) + } + + pub fn into_inner(self) -> W { + self.writer + } + + // Emit {key: value} + fn single_key_dict(&mut self, key: String) -> Result<(), Error> { + self.emit(Event::StartDictionary(Some(1)))?; + self.emit(Event::StringValue(key))?; + Ok(()) + } + + fn single_key_dict_end(&mut self) -> Result<(), Error> { + self.emit(Event::EndDictionary)?; + Ok(()) + } +} + +impl<'a, W: Writer> ser::Serializer for &'a mut Serializer { + type Ok = (); + type Error = Error; + + type SerializeSeq = Compound<'a, W>; + type SerializeTuple = Compound<'a, W>; + type SerializeTupleStruct = Compound<'a, W>; + type SerializeTupleVariant = Compound<'a, W>; + type SerializeMap = Compound<'a, W>; + type SerializeStruct = Compound<'a, W>; + type SerializeStructVariant = Compound<'a, W>; + + fn serialize_bool(self, v: bool) -> Result<(), Self::Error> { + self.emit(Event::BooleanValue(v)) + } + + fn serialize_i8(self, v: i8) -> Result<(), Self::Error> { + self.serialize_i64(v as i64) + } + + fn serialize_i16(self, v: i16) -> Result<(), Self::Error> { + self.serialize_i64(v as i64) + } + + fn serialize_i32(self, v: i32) -> Result<(), Self::Error> { + self.serialize_i64(v as i64) + } + + fn serialize_i64(self, v: i64) -> Result<(), Self::Error> { + self.emit(Event::IntegerValue(v)) + } + + fn serialize_u8(self, v: u8) -> Result<(), Self::Error> { + self.serialize_u64(v as u64) + } + + fn serialize_u16(self, v: u16) -> Result<(), Self::Error> { + self.serialize_u64(v as u64) + } + + fn serialize_u32(self, v: u32) -> Result<(), Self::Error> { + self.serialize_u64(v as u64) + } + + fn serialize_u64(self, v: u64) -> Result<(), Self::Error> { + self.emit(Event::IntegerValue(v as i64)) + } + + fn serialize_f32(self, v: f32) -> Result<(), Self::Error> { + self.serialize_f64(v as f64) + } + + fn serialize_f64(self, v: f64) -> Result<(), Self::Error> { + self.emit(Event::RealValue(v)) + } + + fn serialize_char(self, v: char) -> Result<(), Self::Error> { + self.emit(Event::StringValue(v.to_string())) + } + + fn serialize_str(self, v: &str) -> Result<(), Self::Error> { + self.emit(Event::StringValue(v.to_owned())) + } + + fn serialize_bytes(self, v: &[u8]) -> Result<(), Self::Error> { + self.emit(Event::DataValue(v.to_owned())) + } + + fn serialize_none(self) -> Result<(), Self::Error> { + self.single_key_dict("None".to_owned())?; + self.serialize_unit()?; + self.single_key_dict_end() + } + + fn serialize_some(self, value: &T) -> Result<(), Self::Error> { + self.single_key_dict("Some".to_owned())?; + value.serialize(&mut *self)?; + self.single_key_dict_end() + } + + fn serialize_unit(self) -> Result<(), Self::Error> { + // Emit empty string + self.emit(Event::StringValue(String::new())) + } + + fn serialize_unit_struct(self, _name: &'static str) -> Result<(), Self::Error> { + self.serialize_unit() + } + + fn serialize_unit_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + ) -> Result<(), Self::Error> { + self.single_key_dict(variant.to_owned())?; + self.serialize_unit()?; + self.single_key_dict_end()?; + Ok(()) + } + + fn serialize_newtype_struct( + self, + name: &'static str, + value: &T, + ) -> Result<(), Self::Error> { + if name == DATE_NEWTYPE_STRUCT_NAME { + value.serialize(DateSerializer { ser: &mut *self }) + } else { + value.serialize(self) + } + } + + fn serialize_newtype_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + value: &T, + ) -> Result<(), Self::Error> { + self.single_key_dict(variant.to_owned())?; + value.serialize(&mut *self)?; + self.single_key_dict_end() + } + + fn serialize_seq(self, len: Option) -> Result { + let len = len.map(|len| len as u64); + self.emit(Event::StartArray(len))?; + Ok(Compound { ser: self }) + } + + fn serialize_tuple(self, len: usize) -> Result { + self.serialize_seq(Some(len)) + } + + fn serialize_tuple_struct( + self, + _name: &'static str, + len: usize, + ) -> Result { + self.serialize_tuple(len) + } + + fn serialize_tuple_variant( + self, + _name: &'static str, + _variant_index: u32, + variant: &'static str, + len: usize, + ) -> Result { + self.single_key_dict(variant.to_owned())?; + self.serialize_tuple(len) + } + + fn serialize_map(self, len: Option) -> Result { + let len = len.map(|len| len as u64); + self.emit(Event::StartDictionary(len))?; + Ok(Compound { ser: self }) + } + + fn serialize_struct( + self, + _name: &'static str, + _len: usize, + ) -> Result { + // The number of struct fields is not known as fields with None values are ignored. + self.serialize_map(None) + } + + fn serialize_struct_variant( + self, + name: &'static str, + _variant_index: u32, + variant: &'static str, + len: usize, + ) -> Result { + self.single_key_dict(variant.to_owned())?; + self.serialize_struct(name, len) + } +} + +struct StructFieldSerializer<'a, W: 'a + Writer> { + ser: &'a mut Serializer, + field_name: &'static str, +} + +impl<'a, W: Writer> StructFieldSerializer<'a, W> { + fn use_ser(self) -> Result<&'a mut Serializer, Error> { + // We are going to serialize something so write the struct field name. + self.ser + .emit(Event::StringValue(self.field_name.to_owned()))?; + Ok(self.ser) + } +} + +impl<'a, W: Writer> ser::Serializer for StructFieldSerializer<'a, W> { + type Ok = (); + type Error = Error; + + type SerializeSeq = Compound<'a, W>; + type SerializeTuple = Compound<'a, W>; + type SerializeTupleStruct = Compound<'a, W>; + type SerializeTupleVariant = Compound<'a, W>; + type SerializeMap = Compound<'a, W>; + type SerializeStruct = Compound<'a, W>; + type SerializeStructVariant = Compound<'a, W>; + + fn serialize_bool(self, v: bool) -> Result<(), Self::Error> { + self.use_ser()?.serialize_bool(v) + } + + fn serialize_i8(self, v: i8) -> Result<(), Self::Error> { + self.use_ser()?.serialize_i8(v) + } + + fn serialize_i16(self, v: i16) -> Result<(), Self::Error> { + self.use_ser()?.serialize_i16(v) + } + + fn serialize_i32(self, v: i32) -> Result<(), Self::Error> { + self.use_ser()?.serialize_i32(v) + } + + fn serialize_i64(self, v: i64) -> Result<(), Self::Error> { + self.use_ser()?.serialize_i64(v) + } + + fn serialize_u8(self, v: u8) -> Result<(), Self::Error> { + self.use_ser()?.serialize_u8(v) + } + + fn serialize_u16(self, v: u16) -> Result<(), Self::Error> { + self.use_ser()?.serialize_u16(v) + } + + fn serialize_u32(self, v: u32) -> Result<(), Self::Error> { + self.use_ser()?.serialize_u32(v) + } + + fn serialize_u64(self, v: u64) -> Result<(), Self::Error> { + self.use_ser()?.serialize_u64(v) + } + + fn serialize_f32(self, v: f32) -> Result<(), Self::Error> { + self.use_ser()?.serialize_f32(v) + } + + fn serialize_f64(self, v: f64) -> Result<(), Self::Error> { + self.use_ser()?.serialize_f64(v) + } + + fn serialize_char(self, v: char) -> Result<(), Self::Error> { + self.use_ser()?.serialize_char(v) + } + + fn serialize_str(self, v: &str) -> Result<(), Self::Error> { + self.use_ser()?.serialize_str(v) + } + + fn serialize_bytes(self, v: &[u8]) -> Result<(), Self::Error> { + self.use_ser()?.serialize_bytes(v) + } + + fn serialize_none(self) -> Result<(), Self::Error> { + // Don't write a dict for None if the Option is in a struct. + Ok(()) + } + + fn serialize_some(self, value: &T) -> Result<(), Self::Error> { + let ser = self.use_ser()?; + value.serialize(ser) + } + + fn serialize_unit(self) -> Result<(), Self::Error> { + self.use_ser()?.serialize_unit() + } + + fn serialize_unit_struct(self, name: &'static str) -> Result<(), Self::Error> { + self.use_ser()?.serialize_unit_struct(name) + } + + fn serialize_unit_variant( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + ) -> Result<(), Self::Error> { + self.use_ser()? + .serialize_unit_variant(name, variant_index, variant) + } + + fn serialize_newtype_struct( + self, + name: &'static str, + value: &T, + ) -> Result<(), Self::Error> { + self.use_ser()?.serialize_newtype_struct(name, value) + } + + fn serialize_newtype_variant( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + value: &T, + ) -> Result<(), Self::Error> { + self.use_ser()? + .serialize_newtype_variant(name, variant_index, variant, value) + } + + fn serialize_seq(self, len: Option) -> Result { + self.use_ser()?.serialize_seq(len) + } + + fn serialize_tuple(self, len: usize) -> Result { + self.use_ser()?.serialize_tuple(len) + } + + fn serialize_tuple_struct( + self, + name: &'static str, + len: usize, + ) -> Result { + self.use_ser()?.serialize_tuple_struct(name, len) + } + + fn serialize_tuple_variant( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + len: usize, + ) -> Result { + self.use_ser()? + .serialize_tuple_variant(name, variant_index, variant, len) + } + + fn serialize_map(self, len: Option) -> Result { + self.use_ser()?.serialize_map(len) + } + + fn serialize_struct( + self, + name: &'static str, + len: usize, + ) -> Result { + self.use_ser()?.serialize_struct(name, len) + } + + fn serialize_struct_variant( + self, + name: &'static str, + variant_index: u32, + variant: &'static str, + len: usize, + ) -> Result { + self.use_ser()? + .serialize_struct_variant(name, variant_index, variant, len) + } +} + +struct DateSerializer<'a, W: 'a + Writer> { + ser: &'a mut Serializer, +} + +impl<'a, W: Writer> DateSerializer<'a, W> { + fn expecting_date_error(&self) -> Error { + ser::Error::custom("plist date string expected") + } +} + +impl<'a, W: Writer> ser::Serializer for DateSerializer<'a, W> { + type Ok = (); + type Error = Error; + + type SerializeSeq = ser::Impossible<(), Error>; + type SerializeTuple = ser::Impossible<(), Error>; + type SerializeTupleStruct = ser::Impossible<(), Error>; + type SerializeTupleVariant = ser::Impossible<(), Error>; + type SerializeMap = ser::Impossible<(), Error>; + type SerializeStruct = ser::Impossible<(), Error>; + type SerializeStructVariant = ser::Impossible<(), Error>; + + fn serialize_bool(self, _: bool) -> Result<(), Self::Error> { + Err(self.expecting_date_error()) + } + + fn serialize_i8(self, _: i8) -> Result<(), Self::Error> { + Err(self.expecting_date_error()) + } + + fn serialize_i16(self, _: i16) -> Result<(), Self::Error> { + Err(self.expecting_date_error()) + } + + fn serialize_i32(self, _: i32) -> Result<(), Self::Error> { + Err(self.expecting_date_error()) + } + + fn serialize_i64(self, _: i64) -> Result<(), Self::Error> { + Err(self.expecting_date_error()) + } + + fn serialize_u8(self, _: u8) -> Result<(), Self::Error> { + Err(self.expecting_date_error()) + } + + fn serialize_u16(self, _: u16) -> Result<(), Self::Error> { + Err(self.expecting_date_error()) + } + + fn serialize_u32(self, _: u32) -> Result<(), Self::Error> { + Err(self.expecting_date_error()) + } + + fn serialize_u64(self, _: u64) -> Result<(), Self::Error> { + Err(self.expecting_date_error()) + } + + fn serialize_f32(self, _: f32) -> Result<(), Self::Error> { + Err(self.expecting_date_error()) + } + + fn serialize_f64(self, _: f64) -> Result<(), Self::Error> { + Err(self.expecting_date_error()) + } + + fn serialize_char(self, _: char) -> Result<(), Self::Error> { + Err(self.expecting_date_error()) + } + + fn serialize_str(self, v: &str) -> Result<(), Self::Error> { + let date = Date::from_rfc3339(v).map_err(|_| self.expecting_date_error())?; + self.ser.emit(Event::DateValue(date)) + } + + fn serialize_bytes(self, _: &[u8]) -> Result<(), Self::Error> { + Err(self.expecting_date_error()) + } + + fn serialize_none(self) -> Result<(), Self::Error> { + Err(self.expecting_date_error()) + } + + fn serialize_some(self, _: &T) -> Result<(), Self::Error> { + Err(self.expecting_date_error()) + } + + fn serialize_unit(self) -> Result<(), Self::Error> { + Err(self.expecting_date_error()) + } + + fn serialize_unit_struct(self, _: &'static str) -> Result<(), Self::Error> { + Err(self.expecting_date_error()) + } + + fn serialize_unit_variant( + self, + _: &'static str, + _: u32, + _: &'static str, + ) -> Result<(), Self::Error> { + Err(self.expecting_date_error()) + } + + fn serialize_newtype_struct( + self, + _: &'static str, + _: &T, + ) -> Result<(), Self::Error> { + Err(self.expecting_date_error()) + } + + fn serialize_newtype_variant( + self, + _: &'static str, + _: u32, + _: &'static str, + _: &T, + ) -> Result<(), Self::Error> { + Err(self.expecting_date_error()) + } + + fn serialize_seq(self, _: Option) -> Result { + Err(self.expecting_date_error()) + } + + fn serialize_tuple(self, _: usize) -> Result { + Err(self.expecting_date_error()) + } + + fn serialize_tuple_struct( + self, + _: &'static str, + _: usize, + ) -> Result { + Err(self.expecting_date_error()) + } + + fn serialize_tuple_variant( + self, + _: &'static str, + _: u32, + _: &'static str, + _: usize, + ) -> Result { + Err(self.expecting_date_error()) + } + + fn serialize_map(self, _: Option) -> Result { + Err(self.expecting_date_error()) + } + + fn serialize_struct( + self, + _: &'static str, + _: usize, + ) -> Result { + Err(self.expecting_date_error()) + } + + fn serialize_struct_variant( + self, + _: &'static str, + _: u32, + _: &'static str, + _: usize, + ) -> Result { + Err(self.expecting_date_error()) + } +} + +#[doc(hidden)] +pub struct Compound<'a, W: 'a + Writer> { + ser: &'a mut Serializer, +} + +impl<'a, W: Writer> ser::SerializeSeq for Compound<'a, W> { + type Ok = (); + type Error = Error; + + fn serialize_element( + &mut self, + value: &T, + ) -> Result<(), Self::Error> { + value.serialize(&mut *self.ser) + } + + fn end(self) -> Result { + self.ser.emit(Event::EndArray) + } +} + +impl<'a, W: Writer> ser::SerializeTuple for Compound<'a, W> { + type Ok = (); + type Error = Error; + + fn serialize_element( + &mut self, + value: &T, + ) -> Result<(), Self::Error> { + ::serialize_element(self, value) + } + + fn end(self) -> Result { + ::end(self) + } +} + +impl<'a, W: Writer> ser::SerializeTupleStruct for Compound<'a, W> { + type Ok = (); + type Error = Error; + + fn serialize_field( + &mut self, + value: &T, + ) -> Result<(), Self::Error> { + ::serialize_element(self, value) + } + + fn end(self) -> Result { + ::end(self) + } +} + +impl<'a, W: Writer> ser::SerializeTupleVariant for Compound<'a, W> { + type Ok = (); + type Error = Error; + + fn serialize_field( + &mut self, + value: &T, + ) -> Result<(), Self::Error> { + ::serialize_element(self, value) + } + + fn end(self) -> Result { + self.ser.emit(Event::EndArray)?; + self.ser.single_key_dict_end() + } +} + +impl<'a, W: Writer> ser::SerializeMap for Compound<'a, W> { + type Ok = (); + type Error = Error; + + fn serialize_key(&mut self, key: &T) -> Result<(), Self::Error> { + key.serialize(&mut *self.ser) + } + + fn serialize_value( + &mut self, + value: &T, + ) -> Result<(), Self::Error> { + value.serialize(&mut *self.ser) + } + + fn end(self) -> Result { + self.ser.emit(Event::EndDictionary) + } +} + +impl<'a, W: Writer> ser::SerializeStruct for Compound<'a, W> { + type Ok = (); + type Error = Error; + + fn serialize_field( + &mut self, + key: &'static str, + value: &T, + ) -> Result<(), Self::Error> { + // We don't want to serialize None if the Option is a struct field as this is how null + // fields are represented in plists. + value.serialize(StructFieldSerializer { + field_name: key, + ser: &mut *self.ser, + }) + } + + fn end(self) -> Result { + ::end(self) + } +} + +impl<'a, W: Writer> ser::SerializeStructVariant for Compound<'a, W> { + type Ok = (); + type Error = Error; + + fn serialize_field( + &mut self, + key: &'static str, + value: &T, + ) -> Result<(), Self::Error> { + ::serialize_field(self, key, value) + } + + fn end(self) -> Result { + self.ser.emit(Event::EndDictionary)?; + self.ser.single_key_dict_end() + } +} + +pub fn serialize_to_xml(writer: W, value: &T) -> Result<(), Error> { + let writer = events::XmlWriter::new(writer); + let mut ser = Serializer::new(writer); + value.serialize(&mut ser) +} diff --git a/src/serde/de.rs b/src/serde/de.rs deleted file mode 100644 index 58e0973..0000000 --- a/src/serde/de.rs +++ /dev/null @@ -1,385 +0,0 @@ -use serde_base::de; -use std::fmt::Display; -use std::iter::Peekable; - -use {Error, PlistEvent, u64_option_to_usize}; - -macro_rules! expect { - ($next:expr, $pat:pat) => { - match $next { - Some(Ok(v @ $pat)) => v, - None => return Err(Error::UnexpectedEof), - _ => return Err(event_mismatch_error()), - } - }; - ($next:expr, $pat:pat => $save:expr) => { - match $next { - Some(Ok($pat)) => $save, - None => return Err(Error::UnexpectedEof), - _ => return Err(event_mismatch_error()), - } - }; -} - -macro_rules! try_next { - ($next:expr) => { - match $next { - Some(Ok(v)) => v, - Some(Err(_)) => return Err(event_mismatch_error()), - None => return Err(Error::UnexpectedEof), - } - }; -} - -fn event_mismatch_error() -> Error { - Error::InvalidData -} - -impl de::Error for Error { - fn custom(msg: T) -> Self { - Error::Serde(msg.to_string()) - } -} - -pub struct Deserializer -where - I: IntoIterator>, -{ - events: Peekable<::IntoIter>, -} - -impl Deserializer -where - I: IntoIterator>, -{ - pub fn new(iter: I) -> Deserializer { - Deserializer { - events: iter.into_iter().peekable(), - } - } -} - -impl<'de, 'a, I> de::Deserializer<'de> for &'a mut Deserializer -where - I: IntoIterator>, -{ - type Error = Error; - - fn deserialize_any(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - match try_next!(self.events.next()) { - PlistEvent::StartArray(len) => { - let len = u64_option_to_usize(len)?; - let ret = visitor.visit_seq(MapAndSeqAccess::new(self, false, len))?; - expect!(self.events.next(), PlistEvent::EndArray); - Ok(ret) - } - PlistEvent::EndArray => Err(event_mismatch_error()), - - PlistEvent::StartDictionary(len) => { - let len = u64_option_to_usize(len)?; - let ret = visitor.visit_map(MapAndSeqAccess::new(self, false, len))?; - expect!(self.events.next(), PlistEvent::EndDictionary); - Ok(ret) - } - PlistEvent::EndDictionary => Err(event_mismatch_error()), - - 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), - } - } - - 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(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - expect!(self.events.next(), PlistEvent::StringValue(_)); - visitor.visit_unit() - } - - fn deserialize_option(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - expect!(self.events.next(), PlistEvent::StartDictionary(_)); - - let ret = match try_next!(self.events.next()) { - PlistEvent::StringValue(ref s) if &s[..] == "None" => { - expect!(self.events.next(), PlistEvent::StringValue(_)); - visitor.visit_none::()? - } - PlistEvent::StringValue(ref s) if &s[..] == "Some" => visitor.visit_some(&mut *self)?, - _ => return Err(event_mismatch_error()), - }; - - expect!(self.events.next(), PlistEvent::EndDictionary); - - Ok(ret) - } - - fn deserialize_newtype_struct( - self, - _name: &'static str, - visitor: V, - ) -> Result - where - V: de::Visitor<'de>, - { - visitor.visit_newtype_struct(self) - } - - fn deserialize_struct( - self, - _name: &'static str, - _fields: &'static [&'static str], - visitor: V, - ) -> Result - 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( - self, - _enum: &'static str, - _variants: &'static [&'static str], - visitor: V, - ) -> Result - where - V: de::Visitor<'de>, - { - expect!(self.events.next(), PlistEvent::StartDictionary(_)); - let ret = visitor.visit_enum(&mut *self)?; - expect!(self.events.next(), PlistEvent::EndDictionary); - Ok(ret) - } -} - -impl<'de, 'a, I> de::EnumAccess<'de> for &'a mut Deserializer -where - I: IntoIterator>, -{ - type Error = Error; - type Variant = Self; - - fn variant_seed(self, seed: V) -> Result<(V::Value, Self), Self::Error> - where - V: de::DeserializeSeed<'de>, - { - Ok((seed.deserialize(&mut *self)?, self)) - } -} - -impl<'de, 'a, I> de::VariantAccess<'de> for &'a mut Deserializer -where - I: IntoIterator>, -{ - type Error = Error; - - fn unit_variant(self) -> Result<(), Self::Error> { - <() as de::Deserialize>::deserialize(self) - } - - fn newtype_variant_seed(self, seed: T) -> Result - where - T: de::DeserializeSeed<'de>, - { - seed.deserialize(self) - } - - fn tuple_variant(self, len: usize, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - ::deserialize_tuple(self, len, visitor) - } - - fn struct_variant( - self, - fields: &'static [&'static str], - visitor: V, - ) -> Result - where - V: de::Visitor<'de>, - { - let name = ""; - ::deserialize_struct(self, name, fields, visitor) - } -} - -pub struct StructValueDeserializer<'a, I: 'a> -where - I: IntoIterator>, -{ - de: &'a mut Deserializer, -} - -impl<'de, 'a, I> de::Deserializer<'de> for StructValueDeserializer<'a, I> -where - I: IntoIterator>, -{ - type Error = Error; - - fn deserialize_any(self, visitor: V) -> Result - 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(self, visitor: V) -> Result - where - V: de::Visitor<'de>, - { - self.de.deserialize_unit(visitor) - } - - fn deserialize_option(self, visitor: V) -> Result - 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( - self, - name: &'static str, - visitor: V, - ) -> Result - where - V: de::Visitor<'de>, - { - self.de.deserialize_newtype_struct(name, visitor) - } - - fn deserialize_struct( - self, - name: &'static str, - fields: &'static [&'static str], - visitor: V, - ) -> Result - where - V: de::Visitor<'de>, - { - self.de.deserialize_struct(name, fields, visitor) - } - - fn deserialize_enum( - self, - enum_: &'static str, - variants: &'static [&'static str], - visitor: V, - ) -> Result - where - V: de::Visitor<'de>, - { - self.de.deserialize_enum(enum_, variants, visitor) - } -} - -struct MapAndSeqAccess<'a, I> -where - I: 'a + IntoIterator>, -{ - de: &'a mut Deserializer, - is_struct: bool, - remaining: Option, -} - -impl<'a, I> MapAndSeqAccess<'a, I> -where - I: 'a + IntoIterator>, -{ - fn new( - de: &'a mut Deserializer, - is_struct: bool, - len: Option, - ) -> MapAndSeqAccess<'a, I> { - MapAndSeqAccess { - de: de, - is_struct: is_struct, - remaining: len, - } - } -} - -impl<'de, 'a, I> de::SeqAccess<'de> for MapAndSeqAccess<'a, I> -where - I: 'a + IntoIterator>, -{ - type Error = Error; - - fn next_element_seed(&mut self, seed: T) -> Result, Self::Error> - where - T: de::DeserializeSeed<'de>, - { - 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 { - self.remaining - } -} - -impl<'de, 'a, I> de::MapAccess<'de> for MapAndSeqAccess<'a, I> -where - I: 'a + IntoIterator>, -{ - type Error = Error; - - fn next_key_seed(&mut self, seed: K) -> Result, Self::Error> - where - K: de::DeserializeSeed<'de>, - { - 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(&mut self, seed: V) -> Result - where - V: de::DeserializeSeed<'de>, - { - if self.is_struct { - seed.deserialize(StructValueDeserializer { de: &mut *self.de }) - } else { - seed.deserialize(&mut *self.de) - } - } - - fn size_hint(&self) -> Option { - self.remaining - } -} diff --git a/src/serde/mod.rs b/src/serde/mod.rs deleted file mode 100644 index 2b2411c..0000000 --- a/src/serde/mod.rs +++ /dev/null @@ -1,25 +0,0 @@ -mod de; -mod ser; - -pub use self::de::Deserializer; -pub use self::ser::Serializer; - -use serde_base::de::{Deserialize, DeserializeOwned}; -use serde_base::ser::Serialize; -use std::io::{Read, Seek, Write}; - -use EventReader; -use Result; -use xml; - -pub fn deserialize(reader: R) -> Result { - let reader = EventReader::new(reader); - let mut de = Deserializer::new(reader); - Deserialize::deserialize(&mut de) -} - -pub fn serialize_to_xml(writer: W, value: &T) -> Result<()> { - let writer = xml::EventWriter::new(writer); - let mut ser = Serializer::new(writer); - value.serialize(&mut ser) -} diff --git a/src/serde/ser.rs b/src/serde/ser.rs deleted file mode 100644 index f9cb5b3..0000000 --- a/src/serde/ser.rs +++ /dev/null @@ -1,704 +0,0 @@ -use serde_base::ser; -use std::fmt::Display; - -use date::serde_impls::DATE_NEWTYPE_STRUCT_NAME; -use {Date, Error, EventWriter, PlistEvent}; - -impl ser::Error for Error { - fn custom(msg: T) -> Self { - Error::Serde(msg.to_string()) - } -} - -pub struct Serializer { - writer: W, -} - -impl Serializer { - pub fn new(writer: W) -> Serializer { - Serializer { writer: writer } - } - - fn emit(&mut self, event: PlistEvent) -> Result<(), Error> { - self.writer.write(&event)?; - Ok(()) - } - - pub fn into_inner(self) -> W { - self.writer - } - - // Emit {key: value} - fn single_key_dict(&mut self, key: String) -> Result<(), Error> { - self.emit(PlistEvent::StartDictionary(Some(1)))?; - self.emit(PlistEvent::StringValue(key))?; - Ok(()) - } - - fn single_key_dict_end(&mut self) -> Result<(), Error> { - self.emit(PlistEvent::EndDictionary)?; - Ok(()) - } -} - -impl<'a, W: EventWriter> ser::Serializer for &'a mut Serializer { - type Ok = (); - type Error = Error; - - type SerializeSeq = Compound<'a, W>; - type SerializeTuple = Compound<'a, W>; - type SerializeTupleStruct = Compound<'a, W>; - type SerializeTupleVariant = Compound<'a, W>; - type SerializeMap = Compound<'a, W>; - type SerializeStruct = Compound<'a, W>; - type SerializeStructVariant = Compound<'a, W>; - - fn serialize_bool(self, v: bool) -> Result<(), Self::Error> { - self.emit(PlistEvent::BooleanValue(v)) - } - - fn serialize_i8(self, v: i8) -> Result<(), Self::Error> { - self.serialize_i64(v as i64) - } - - fn serialize_i16(self, v: i16) -> Result<(), Self::Error> { - self.serialize_i64(v as i64) - } - - fn serialize_i32(self, v: i32) -> Result<(), Self::Error> { - self.serialize_i64(v as i64) - } - - fn serialize_i64(self, v: i64) -> Result<(), Self::Error> { - self.emit(PlistEvent::IntegerValue(v)) - } - - fn serialize_u8(self, v: u8) -> Result<(), Self::Error> { - self.serialize_u64(v as u64) - } - - fn serialize_u16(self, v: u16) -> Result<(), Self::Error> { - self.serialize_u64(v as u64) - } - - fn serialize_u32(self, v: u32) -> Result<(), Self::Error> { - self.serialize_u64(v as u64) - } - - fn serialize_u64(self, v: u64) -> Result<(), Self::Error> { - self.emit(PlistEvent::IntegerValue(v as i64)) - } - - fn serialize_f32(self, v: f32) -> Result<(), Self::Error> { - self.serialize_f64(v as f64) - } - - fn serialize_f64(self, v: f64) -> Result<(), Self::Error> { - self.emit(PlistEvent::RealValue(v)) - } - - fn serialize_char(self, v: char) -> Result<(), Self::Error> { - self.emit(PlistEvent::StringValue(v.to_string())) - } - - fn serialize_str(self, v: &str) -> Result<(), Self::Error> { - self.emit(PlistEvent::StringValue(v.to_owned())) - } - - fn serialize_bytes(self, v: &[u8]) -> Result<(), Self::Error> { - self.emit(PlistEvent::DataValue(v.to_owned())) - } - - fn serialize_none(self) -> Result<(), Self::Error> { - self.single_key_dict("None".to_owned())?; - self.serialize_unit()?; - self.single_key_dict_end() - } - - fn serialize_some(self, value: &T) -> Result<(), Self::Error> { - self.single_key_dict("Some".to_owned())?; - value.serialize(&mut *self)?; - self.single_key_dict_end() - } - - fn serialize_unit(self) -> Result<(), Self::Error> { - // Emit empty string - self.emit(PlistEvent::StringValue(String::new())) - } - - fn serialize_unit_struct(self, _name: &'static str) -> Result<(), Self::Error> { - self.serialize_unit() - } - - fn serialize_unit_variant( - self, - _name: &'static str, - _variant_index: u32, - variant: &'static str, - ) -> Result<(), Self::Error> { - self.single_key_dict(variant.to_owned())?; - self.serialize_unit()?; - self.single_key_dict_end()?; - Ok(()) - } - - fn serialize_newtype_struct( - self, - name: &'static str, - value: &T, - ) -> Result<(), Self::Error> { - if name == DATE_NEWTYPE_STRUCT_NAME { - value.serialize(DateSerializer { ser: &mut *self }) - } else { - value.serialize(self) - } - } - - fn serialize_newtype_variant( - self, - _name: &'static str, - _variant_index: u32, - variant: &'static str, - value: &T, - ) -> Result<(), Self::Error> { - self.single_key_dict(variant.to_owned())?; - value.serialize(&mut *self)?; - self.single_key_dict_end() - } - - fn serialize_seq(self, len: Option) -> Result { - let len = len.map(|len| len as u64); - self.emit(PlistEvent::StartArray(len))?; - Ok(Compound { ser: self }) - } - - fn serialize_tuple(self, len: usize) -> Result { - self.serialize_seq(Some(len)) - } - - fn serialize_tuple_struct( - self, - _name: &'static str, - len: usize, - ) -> Result { - self.serialize_tuple(len) - } - - fn serialize_tuple_variant( - self, - _name: &'static str, - _variant_index: u32, - variant: &'static str, - len: usize, - ) -> Result { - self.single_key_dict(variant.to_owned())?; - self.serialize_tuple(len) - } - - fn serialize_map(self, len: Option) -> Result { - let len = len.map(|len| len as u64); - self.emit(PlistEvent::StartDictionary(len))?; - Ok(Compound { ser: self }) - } - - fn serialize_struct( - self, - _name: &'static str, - _len: usize, - ) -> Result { - // The number of struct fields is not known as fields with None values are ignored. - self.serialize_map(None) - } - - fn serialize_struct_variant( - self, - name: &'static str, - _variant_index: u32, - variant: &'static str, - len: usize, - ) -> Result { - self.single_key_dict(variant.to_owned())?; - self.serialize_struct(name, len) - } -} - -struct StructFieldSerializer<'a, W: 'a + EventWriter> { - ser: &'a mut Serializer, - field_name: &'static str, -} - -impl<'a, W: EventWriter> StructFieldSerializer<'a, W> { - fn use_ser(self) -> Result<&'a mut Serializer, Error> { - // We are going to serialize something so write the struct field name. - self.ser - .emit(PlistEvent::StringValue(self.field_name.to_owned()))?; - Ok(self.ser) - } -} - -impl<'a, W: EventWriter> ser::Serializer for StructFieldSerializer<'a, W> { - type Ok = (); - type Error = Error; - - type SerializeSeq = Compound<'a, W>; - type SerializeTuple = Compound<'a, W>; - type SerializeTupleStruct = Compound<'a, W>; - type SerializeTupleVariant = Compound<'a, W>; - type SerializeMap = Compound<'a, W>; - type SerializeStruct = Compound<'a, W>; - type SerializeStructVariant = Compound<'a, W>; - - fn serialize_bool(self, v: bool) -> Result<(), Self::Error> { - self.use_ser()?.serialize_bool(v) - } - - fn serialize_i8(self, v: i8) -> Result<(), Self::Error> { - self.use_ser()?.serialize_i8(v) - } - - fn serialize_i16(self, v: i16) -> Result<(), Self::Error> { - self.use_ser()?.serialize_i16(v) - } - - fn serialize_i32(self, v: i32) -> Result<(), Self::Error> { - self.use_ser()?.serialize_i32(v) - } - - fn serialize_i64(self, v: i64) -> Result<(), Self::Error> { - self.use_ser()?.serialize_i64(v) - } - - fn serialize_u8(self, v: u8) -> Result<(), Self::Error> { - self.use_ser()?.serialize_u8(v) - } - - fn serialize_u16(self, v: u16) -> Result<(), Self::Error> { - self.use_ser()?.serialize_u16(v) - } - - fn serialize_u32(self, v: u32) -> Result<(), Self::Error> { - self.use_ser()?.serialize_u32(v) - } - - fn serialize_u64(self, v: u64) -> Result<(), Self::Error> { - self.use_ser()?.serialize_u64(v) - } - - fn serialize_f32(self, v: f32) -> Result<(), Self::Error> { - self.use_ser()?.serialize_f32(v) - } - - fn serialize_f64(self, v: f64) -> Result<(), Self::Error> { - self.use_ser()?.serialize_f64(v) - } - - fn serialize_char(self, v: char) -> Result<(), Self::Error> { - self.use_ser()?.serialize_char(v) - } - - fn serialize_str(self, v: &str) -> Result<(), Self::Error> { - self.use_ser()?.serialize_str(v) - } - - fn serialize_bytes(self, v: &[u8]) -> Result<(), Self::Error> { - self.use_ser()?.serialize_bytes(v) - } - - fn serialize_none(self) -> Result<(), Self::Error> { - // Don't write a dict for None if the Option is in a struct. - Ok(()) - } - - fn serialize_some(self, value: &T) -> Result<(), Self::Error> { - let ser = self.use_ser()?; - value.serialize(ser) - } - - fn serialize_unit(self) -> Result<(), Self::Error> { - self.use_ser()?.serialize_unit() - } - - fn serialize_unit_struct(self, name: &'static str) -> Result<(), Self::Error> { - self.use_ser()?.serialize_unit_struct(name) - } - - fn serialize_unit_variant( - self, - name: &'static str, - variant_index: u32, - variant: &'static str, - ) -> Result<(), Self::Error> { - self.use_ser()? - .serialize_unit_variant(name, variant_index, variant) - } - - fn serialize_newtype_struct( - self, - name: &'static str, - value: &T, - ) -> Result<(), Self::Error> { - self.use_ser()?.serialize_newtype_struct(name, value) - } - - fn serialize_newtype_variant( - self, - name: &'static str, - variant_index: u32, - variant: &'static str, - value: &T, - ) -> Result<(), Self::Error> { - self.use_ser()? - .serialize_newtype_variant(name, variant_index, variant, value) - } - - fn serialize_seq(self, len: Option) -> Result { - self.use_ser()?.serialize_seq(len) - } - - fn serialize_tuple(self, len: usize) -> Result { - self.use_ser()?.serialize_tuple(len) - } - - fn serialize_tuple_struct( - self, - name: &'static str, - len: usize, - ) -> Result { - self.use_ser()?.serialize_tuple_struct(name, len) - } - - fn serialize_tuple_variant( - self, - name: &'static str, - variant_index: u32, - variant: &'static str, - len: usize, - ) -> Result { - self.use_ser()? - .serialize_tuple_variant(name, variant_index, variant, len) - } - - fn serialize_map(self, len: Option) -> Result { - self.use_ser()?.serialize_map(len) - } - - fn serialize_struct( - self, - name: &'static str, - len: usize, - ) -> Result { - self.use_ser()?.serialize_struct(name, len) - } - - fn serialize_struct_variant( - self, - name: &'static str, - variant_index: u32, - variant: &'static str, - len: usize, - ) -> Result { - self.use_ser()? - .serialize_struct_variant(name, variant_index, variant, len) - } -} - -struct DateSerializer<'a, W: 'a + EventWriter> { - ser: &'a mut Serializer, -} - -impl<'a, W: EventWriter> DateSerializer<'a, W> { - fn expecting_date_error(&self) -> Error { - ser::Error::custom("plist date string expected") - } -} - -impl<'a, W: EventWriter> ser::Serializer for DateSerializer<'a, W> { - type Ok = (); - type Error = Error; - - type SerializeSeq = ser::Impossible<(), Error>; - type SerializeTuple = ser::Impossible<(), Error>; - type SerializeTupleStruct = ser::Impossible<(), Error>; - type SerializeTupleVariant = ser::Impossible<(), Error>; - type SerializeMap = ser::Impossible<(), Error>; - type SerializeStruct = ser::Impossible<(), Error>; - type SerializeStructVariant = ser::Impossible<(), Error>; - - fn serialize_bool(self, _: bool) -> Result<(), Self::Error> { - Err(self.expecting_date_error()) - } - - fn serialize_i8(self, _: i8) -> Result<(), Self::Error> { - Err(self.expecting_date_error()) - } - - fn serialize_i16(self, _: i16) -> Result<(), Self::Error> { - Err(self.expecting_date_error()) - } - - fn serialize_i32(self, _: i32) -> Result<(), Self::Error> { - Err(self.expecting_date_error()) - } - - fn serialize_i64(self, _: i64) -> Result<(), Self::Error> { - Err(self.expecting_date_error()) - } - - fn serialize_u8(self, _: u8) -> Result<(), Self::Error> { - Err(self.expecting_date_error()) - } - - fn serialize_u16(self, _: u16) -> Result<(), Self::Error> { - Err(self.expecting_date_error()) - } - - fn serialize_u32(self, _: u32) -> Result<(), Self::Error> { - Err(self.expecting_date_error()) - } - - fn serialize_u64(self, _: u64) -> Result<(), Self::Error> { - Err(self.expecting_date_error()) - } - - fn serialize_f32(self, _: f32) -> Result<(), Self::Error> { - Err(self.expecting_date_error()) - } - - fn serialize_f64(self, _: f64) -> Result<(), Self::Error> { - Err(self.expecting_date_error()) - } - - fn serialize_char(self, _: char) -> Result<(), Self::Error> { - Err(self.expecting_date_error()) - } - - fn serialize_str(self, v: &str) -> Result<(), Self::Error> { - let date = Date::from_rfc3339(v).map_err(|_| self.expecting_date_error())?; - self.ser.emit(PlistEvent::DateValue(date)) - } - - fn serialize_bytes(self, _: &[u8]) -> Result<(), Self::Error> { - Err(self.expecting_date_error()) - } - - fn serialize_none(self) -> Result<(), Self::Error> { - Err(self.expecting_date_error()) - } - - fn serialize_some(self, _: &T) -> Result<(), Self::Error> { - Err(self.expecting_date_error()) - } - - fn serialize_unit(self) -> Result<(), Self::Error> { - Err(self.expecting_date_error()) - } - - fn serialize_unit_struct(self, _: &'static str) -> Result<(), Self::Error> { - Err(self.expecting_date_error()) - } - - fn serialize_unit_variant( - self, - _: &'static str, - _: u32, - _: &'static str, - ) -> Result<(), Self::Error> { - Err(self.expecting_date_error()) - } - - fn serialize_newtype_struct( - self, - _: &'static str, - _: &T, - ) -> Result<(), Self::Error> { - Err(self.expecting_date_error()) - } - - fn serialize_newtype_variant( - self, - _: &'static str, - _: u32, - _: &'static str, - _: &T, - ) -> Result<(), Self::Error> { - Err(self.expecting_date_error()) - } - - fn serialize_seq(self, _: Option) -> Result { - Err(self.expecting_date_error()) - } - - fn serialize_tuple(self, _: usize) -> Result { - Err(self.expecting_date_error()) - } - - fn serialize_tuple_struct( - self, - _: &'static str, - _: usize, - ) -> Result { - Err(self.expecting_date_error()) - } - - fn serialize_tuple_variant( - self, - _: &'static str, - _: u32, - _: &'static str, - _: usize, - ) -> Result { - Err(self.expecting_date_error()) - } - - fn serialize_map(self, _: Option) -> Result { - Err(self.expecting_date_error()) - } - - fn serialize_struct( - self, - _: &'static str, - _: usize, - ) -> Result { - Err(self.expecting_date_error()) - } - - fn serialize_struct_variant( - self, - _: &'static str, - _: u32, - _: &'static str, - _: usize, - ) -> Result { - Err(self.expecting_date_error()) - } -} - -#[doc(hidden)] -pub struct Compound<'a, W: 'a + EventWriter> { - ser: &'a mut Serializer, -} - -impl<'a, W: EventWriter> ser::SerializeSeq for Compound<'a, W> { - type Ok = (); - type Error = Error; - - fn serialize_element( - &mut self, - value: &T, - ) -> Result<(), Self::Error> { - value.serialize(&mut *self.ser) - } - - fn end(self) -> Result { - self.ser.emit(PlistEvent::EndArray) - } -} - -impl<'a, W: EventWriter> ser::SerializeTuple for Compound<'a, W> { - type Ok = (); - type Error = Error; - - fn serialize_element( - &mut self, - value: &T, - ) -> Result<(), Self::Error> { - ::serialize_element(self, value) - } - - fn end(self) -> Result { - ::end(self) - } -} - -impl<'a, W: EventWriter> ser::SerializeTupleStruct for Compound<'a, W> { - type Ok = (); - type Error = Error; - - fn serialize_field( - &mut self, - value: &T, - ) -> Result<(), Self::Error> { - ::serialize_element(self, value) - } - - fn end(self) -> Result { - ::end(self) - } -} - -impl<'a, W: EventWriter> ser::SerializeTupleVariant for Compound<'a, W> { - type Ok = (); - type Error = Error; - - fn serialize_field( - &mut self, - value: &T, - ) -> Result<(), Self::Error> { - ::serialize_element(self, value) - } - - fn end(self) -> Result { - self.ser.emit(PlistEvent::EndArray)?; - self.ser.single_key_dict_end() - } -} - -impl<'a, W: EventWriter> ser::SerializeMap for Compound<'a, W> { - type Ok = (); - type Error = Error; - - fn serialize_key(&mut self, key: &T) -> Result<(), Self::Error> { - key.serialize(&mut *self.ser) - } - - fn serialize_value( - &mut self, - value: &T, - ) -> Result<(), Self::Error> { - value.serialize(&mut *self.ser) - } - - fn end(self) -> Result { - self.ser.emit(PlistEvent::EndDictionary) - } -} - -impl<'a, W: EventWriter> ser::SerializeStruct for Compound<'a, W> { - type Ok = (); - type Error = Error; - - fn serialize_field( - &mut self, - key: &'static str, - value: &T, - ) -> Result<(), Self::Error> { - // We don't want to serialize None if the Option is a struct field as this is how null - // fields are represented in plists. - value.serialize(StructFieldSerializer { - field_name: key, - ser: &mut *self.ser, - }) - } - - fn end(self) -> Result { - ::end(self) - } -} - -impl<'a, W: EventWriter> ser::SerializeStructVariant for Compound<'a, W> { - type Ok = (); - type Error = Error; - - fn serialize_field( - &mut self, - key: &'static str, - value: &T, - ) -> Result<(), Self::Error> { - ::serialize_field(self, key, value) - } - - fn end(self) -> Result { - self.ser.emit(PlistEvent::EndDictionary)?; - self.ser.single_key_dict_end() - } -} diff --git a/src/value.rs b/src/value.rs new file mode 100644 index 0000000..d04ad86 --- /dev/null +++ b/src/value.rs @@ -0,0 +1,377 @@ +use std::collections::BTreeMap; +use std::io::{Read, Seek}; + +use events::{Event, Reader}; +use {builder, Date, Result}; + +#[derive(Clone, Debug, PartialEq)] +pub enum Value { + Array(Vec), + Dictionary(BTreeMap), + Boolean(bool), + Data(Vec), + Date(Date), + Real(f64), + Integer(i64), + String(String), +} + +impl Value { + pub fn read(reader: R) -> Result { + let reader = Reader::new(reader); + Value::from_events(reader) + } + + pub fn from_events(events: T) -> Result + where + T: IntoIterator>, + { + let iter = events.into_iter(); + let builder = builder::Builder::new(iter); + builder.build() + } + + pub fn into_events(self) -> Vec { + let mut events = Vec::new(); + self.into_events_inner(&mut events); + events + } + + fn into_events_inner(self, events: &mut Vec) { + match self { + Value::Array(array) => { + events.push(Event::StartArray(Some(array.len() as u64))); + for value in array { + value.into_events_inner(events); + } + events.push(Event::EndArray); + } + Value::Dictionary(dict) => { + events.push(Event::StartDictionary(Some(dict.len() as u64))); + for (key, value) in dict { + events.push(Event::StringValue(key)); + value.into_events_inner(events); + } + events.push(Event::EndDictionary); + } + Value::Boolean(value) => events.push(Event::BooleanValue(value)), + Value::Data(value) => events.push(Event::DataValue(value)), + Value::Date(value) => events.push(Event::DateValue(value)), + Value::Real(value) => events.push(Event::RealValue(value)), + Value::Integer(value) => events.push(Event::IntegerValue(value)), + Value::String(value) => events.push(Event::StringValue(value)), + } + } + + /// If the `Value` is an Array, returns the associated Vec. + /// Returns None otherwise. + pub fn as_array(&self) -> Option<&Vec> { + match *self { + Value::Array(ref array) => Some(array), + _ => None, + } + } + + /// If the `Value` is an Array, returns the associated mutable Vec. + /// Returns None otherwise. + pub fn as_array_mut(&mut self) -> Option<&mut Vec> { + match *self { + Value::Array(ref mut array) => Some(array), + _ => None, + } + } + + /// If the `Value` is a Dictionary, returns the associated BTreeMap. + /// Returns None otherwise. + pub fn as_dictionary(&self) -> Option<&BTreeMap> { + match *self { + Value::Dictionary(ref map) => Some(map), + _ => None, + } + } + + /// If the `Value` is a Dictionary, returns the associated mutable BTreeMap. + /// Returns None otherwise. + pub fn as_dictionary_mut(&mut self) -> Option<&mut BTreeMap> { + match *self { + Value::Dictionary(ref mut map) => Some(map), + _ => None, + } + } + + /// If the `Value` is a Boolean, returns the associated bool. + /// Returns None otherwise. + pub fn as_boolean(&self) -> Option { + match *self { + Value::Boolean(v) => Some(v), + _ => None, + } + } + + /// If the `Value` is a Data, returns the underlying Vec. + /// Returns None otherwise. + /// + /// This method consumes the `Value`. If this is not desired, please use + /// `as_data` method. + pub fn into_data(self) -> Option> { + match self { + Value::Data(data) => Some(data), + _ => None, + } + } + + /// If the `Value` is a Data, returns the associated Vec. + /// Returns None otherwise. + pub fn as_data(&self) -> Option<&[u8]> { + match *self { + Value::Data(ref data) => Some(data), + _ => None, + } + } + + /// If the `Value` is a Date, returns the associated DateTime. + /// Returns None otherwise. + pub fn as_date(&self) -> Option<&Date> { + match *self { + Value::Date(ref date) => Some(date), + _ => None, + } + } + + /// If the `Value` is a Real, returns the associated f64. + /// Returns None otherwise. + pub fn as_real(&self) -> Option { + match *self { + Value::Real(v) => Some(v), + _ => None, + } + } + + /// If the `Value` is an Integer, returns the associated i64. + /// Returns None otherwise. + pub fn as_integer(&self) -> Option { + match *self { + Value::Integer(v) => Some(v), + _ => None, + } + } + + /// If the `Value` is a String, returns the underlying String. + /// Returns None otherwise. + /// + /// This method consumes the `Value`. If this is not desired, please use + /// `as_string` method. + pub fn into_string(self) -> Option { + match self { + Value::String(v) => Some(v), + _ => None, + } + } + + /// If the `Value` is a String, returns the associated str. + /// Returns None otherwise. + pub fn as_string(&self) -> Option<&str> { + match *self { + Value::String(ref v) => Some(v), + _ => None, + } + } +} + +impl From> for Value { + fn from(from: Vec) -> Value { + Value::Array(from) + } +} + +impl From> for Value { + fn from(from: BTreeMap) -> Value { + Value::Dictionary(from) + } +} + +impl From for Value { + fn from(from: bool) -> Value { + Value::Boolean(from) + } +} + +impl<'a> From<&'a bool> for Value { + fn from(from: &'a bool) -> Value { + Value::Boolean(*from) + } +} + +impl From for Value { + fn from(from: Date) -> Value { + Value::Date(from) + } +} + +impl<'a> From<&'a Date> for Value { + fn from(from: &'a Date) -> Value { + Value::Date(from.clone()) + } +} + +impl From for Value { + fn from(from: f64) -> Value { + Value::Real(from) + } +} + +impl From for Value { + fn from(from: f32) -> Value { + Value::Real(from as f64) + } +} + +impl From for Value { + fn from(from: i64) -> Value { + Value::Integer(from) + } +} + +impl From for Value { + fn from(from: i32) -> Value { + Value::Integer(from as i64) + } +} + +impl From for Value { + fn from(from: i16) -> Value { + Value::Integer(from as i64) + } +} + +impl From for Value { + fn from(from: i8) -> Value { + Value::Integer(from as i64) + } +} + +impl From for Value { + fn from(from: u32) -> Value { + Value::Integer(from as i64) + } +} + +impl From for Value { + fn from(from: u16) -> Value { + Value::Integer(from as i64) + } +} + +impl From for Value { + fn from(from: u8) -> Value { + Value::Integer(from as i64) + } +} + +impl<'a> From<&'a f64> for Value { + fn from(from: &'a f64) -> Value { + Value::Real(*from) + } +} + +impl<'a> From<&'a f32> for Value { + fn from(from: &'a f32) -> Value { + Value::Real(*from as f64) + } +} + +impl<'a> From<&'a i64> for Value { + fn from(from: &'a i64) -> Value { + Value::Integer(*from) + } +} + +impl<'a> From<&'a i32> for Value { + fn from(from: &'a i32) -> Value { + Value::Integer(*from as i64) + } +} + +impl<'a> From<&'a i16> for Value { + fn from(from: &'a i16) -> Value { + Value::Integer(*from as i64) + } +} + +impl<'a> From<&'a i8> for Value { + fn from(from: &'a i8) -> Value { + Value::Integer(*from as i64) + } +} + +impl<'a> From<&'a u32> for Value { + fn from(from: &'a u32) -> Value { + Value::Integer(*from as i64) + } +} + +impl<'a> From<&'a u16> for Value { + fn from(from: &'a u16) -> Value { + Value::Integer(*from as i64) + } +} + +impl<'a> From<&'a u8> for Value { + fn from(from: &'a u8) -> Value { + Value::Integer(*from as i64) + } +} + +impl From for Value { + fn from(from: String) -> Value { + Value::String(from) + } +} + +impl<'a> From<&'a str> for Value { + fn from(from: &'a str) -> Value { + Value::String(from.into()) + } +} + +#[cfg(test)] +mod tests { + use std::collections::BTreeMap; + use std::time::SystemTime; + + use {Date, Value}; + + #[test] + fn test_plist_access() { + let vec = vec![Value::Real(0.0)]; + let mut array = Value::Array(vec.clone()); + assert_eq!(array.as_array(), Some(&vec.clone())); + assert_eq!(array.as_array_mut(), Some(&mut vec.clone())); + + let mut map = BTreeMap::new(); + map.insert("key1".to_owned(), Value::String("value1".to_owned())); + let mut dict = Value::Dictionary(map.clone()); + assert_eq!(dict.as_dictionary(), Some(&map.clone())); + assert_eq!(dict.as_dictionary_mut(), Some(&mut map.clone())); + + assert_eq!(Value::Boolean(true).as_boolean(), Some(true)); + + let slice: &[u8] = &[1, 2, 3]; + assert_eq!(Value::Data(slice.to_vec()).as_data(), Some(slice)); + assert_eq!( + Value::Data(slice.to_vec()).into_data(), + Some(slice.to_vec()) + ); + + let date: Date = SystemTime::now().into(); + assert_eq!(Value::Date(date.clone()).as_date(), Some(&date)); + + assert_eq!(Value::Real(0.0).as_real(), Some(0.0)); + assert_eq!(Value::Integer(1).as_integer(), Some(1)); + assert_eq!(Value::String("2".to_owned()).as_string(), Some("2")); + assert_eq!( + Value::String("t".to_owned()).into_string(), + Some("t".to_owned()) + ); + } +} diff --git a/src/xml/mod.rs b/src/xml/mod.rs deleted file mode 100644 index 0400e13..0000000 --- a/src/xml/mod.rs +++ /dev/null @@ -1,5 +0,0 @@ -mod reader; -mod writer; - -pub use self::reader::EventReader; -pub use self::writer::EventWriter; diff --git a/src/xml/reader.rs b/src/xml/reader.rs deleted file mode 100644 index 6642d59..0000000 --- a/src/xml/reader.rs +++ /dev/null @@ -1,199 +0,0 @@ -use base64; -use std::io::Read; -use std::str::FromStr; -use xml_rs::reader::{EventReader as XmlEventReader, ParserConfig, XmlEvent}; - -use {Date, Error, PlistEvent, Result}; - -pub struct EventReader { - xml_reader: XmlEventReader, - queued_event: Option, - element_stack: Vec, - finished: bool, -} - -impl EventReader { - pub fn new(reader: R) -> EventReader { - let config = ParserConfig::new() - .trim_whitespace(false) - .whitespace_to_characters(true) - .cdata_to_characters(true) - .ignore_comments(true) - .coalesce_characters(true); - - EventReader { - xml_reader: XmlEventReader::new_with_config(reader, config), - queued_event: None, - element_stack: Vec::new(), - finished: false, - } - } - - fn read_content(&mut self, f: F) -> Result - where - F: FnOnce(String) -> Result, - { - match self.xml_reader.next() { - Ok(XmlEvent::Characters(s)) => f(s), - Ok(event @ XmlEvent::EndElement { .. }) => { - self.queued_event = Some(event); - f("".to_owned()) - } - _ => Err(Error::InvalidData), - } - } - - fn next_event(&mut self) -> ::std::result::Result { - if let Some(event) = self.queued_event.take() { - Ok(event) - } else { - self.xml_reader.next().map_err(|_| ()) - } - } - - fn read_next(&mut self) -> Option> { - loop { - match self.next_event() { - Ok(XmlEvent::StartElement { name, .. }) => { - // Add the current element to the element stack - self.element_stack.push(name.local_name.clone()); - - match &name.local_name[..] { - "plist" => (), - "array" => return Some(Ok(PlistEvent::StartArray(None))), - "dict" => return Some(Ok(PlistEvent::StartDictionary(None))), - "key" => return Some(self.read_content(|s| Ok(PlistEvent::StringValue(s)))), - "true" => return Some(Ok(PlistEvent::BooleanValue(true))), - "false" => return Some(Ok(PlistEvent::BooleanValue(false))), - "data" => { - return Some(self.read_content(|s| { - let data = base64::decode_config(&s, base64::MIME) - .map_err(|_| Error::InvalidData)?; - Ok(PlistEvent::DataValue(data)) - })) - } - "date" => { - return Some(self.read_content(|s| { - Ok(PlistEvent::DateValue(Date::from_rfc3339(&s)?)) - })) - } - "integer" => { - return Some(self.read_content(|s| match FromStr::from_str(&s) { - Ok(i) => Ok(PlistEvent::IntegerValue(i)), - Err(_) => Err(Error::InvalidData), - })) - } - "real" => { - return Some(self.read_content(|s| match FromStr::from_str(&s) { - Ok(f) => Ok(PlistEvent::RealValue(f)), - Err(_) => Err(Error::InvalidData), - })) - } - "string" => { - return Some(self.read_content(|s| Ok(PlistEvent::StringValue(s)))) - } - _ => return Some(Err(Error::InvalidData)), - } - } - Ok(XmlEvent::EndElement { name, .. }) => { - // Check the corrent element is being closed - match self.element_stack.pop() { - Some(ref open_name) if &name.local_name == open_name => (), - Some(ref _open_name) => return Some(Err(Error::InvalidData)), - None => return Some(Err(Error::InvalidData)), - } - - match &name.local_name[..] { - "array" => return Some(Ok(PlistEvent::EndArray)), - "dict" => return Some(Ok(PlistEvent::EndDictionary)), - "plist" => (), - _ => (), - } - } - Ok(XmlEvent::EndDocument) => { - if self.element_stack.is_empty() { - return None; - } else { - return Some(Err(Error::UnexpectedEof)); - } - } - Err(_) => return Some(Err(Error::InvalidData)), - _ => (), - } - } - } -} - -impl Iterator for EventReader { - type Item = Result; - - fn next(&mut self) -> Option> { - if self.finished { - None - } else { - match self.read_next() { - Some(Ok(event)) => Some(Ok(event)), - Some(Err(err)) => { - self.finished = true; - Some(Err(err)) - } - None => { - self.finished = true; - None - } - } - } - } -} - -#[cfg(test)] -mod tests { - use humantime::parse_rfc3339_weak; - use std::fs::File; - use std::path::Path; - - use super::*; - use PlistEvent; - - #[test] - fn streaming_parser() { - use PlistEvent::*; - - let reader = File::open(&Path::new("./tests/data/xml.plist")).unwrap(); - let streaming_parser = EventReader::new(reader); - let events: Vec = streaming_parser.map(|e| e.unwrap()).collect(); - - let comparison = &[ - StartDictionary(None), - StringValue("Author".to_owned()), - StringValue("William Shakespeare".to_owned()), - StringValue("Lines".to_owned()), - StartArray(None), - StringValue("It is a tale told by an idiot,".to_owned()), - StringValue("Full of sound and fury, signifying nothing.".to_owned()), - EndArray, - StringValue("Death".to_owned()), - IntegerValue(1564), - StringValue("Height".to_owned()), - RealValue(1.60), - StringValue("Data".to_owned()), - DataValue(vec![0, 0, 0, 190, 0, 0, 0, 3, 0, 0, 0, 30, 0, 0, 0]), - StringValue("Birthdate".to_owned()), - DateValue(parse_rfc3339_weak("1981-05-16 11:32:06").unwrap().into()), - StringValue("Blank".to_owned()), - StringValue("".to_owned()), - EndDictionary, - ]; - - assert_eq!(events, comparison); - } - - #[test] - fn bad_data() { - let reader = File::open(&Path::new("./tests/data/xml_error.plist")).unwrap(); - let streaming_parser = EventReader::new(reader); - let events: Vec<_> = streaming_parser.collect(); - - assert!(events.last().unwrap().is_err()); - } -} diff --git a/src/xml/writer.rs b/src/xml/writer.rs deleted file mode 100644 index e002e55..0000000 --- a/src/xml/writer.rs +++ /dev/null @@ -1,259 +0,0 @@ -use base64; -use std::borrow::Cow; -use std::io::Write; -use xml_rs::name::Name; -use xml_rs::namespace::Namespace; -use xml_rs::writer::events::XmlEvent as WriteXmlEvent; -use xml_rs::writer::{EmitterConfig, Error as XmlWriterError, EventWriter as XmlEventWriter}; - -use {Error, EventWriter as PlistEventWriter, PlistEvent, Result}; - -impl From for Error { - fn from(err: XmlWriterError) -> Error { - match err { - XmlWriterError::Io(err) => Error::Io(err), - _ => Error::InvalidData, - } - } -} - -enum Element { - Dictionary(DictionaryState), - Array, - Root, -} - -enum DictionaryState { - ExpectKey, - ExpectValue, -} - -pub struct EventWriter { - xml_writer: XmlEventWriter, - stack: Vec, - // Not very nice - empty_namespace: Namespace, -} - -impl EventWriter { - pub fn new(writer: W) -> EventWriter { - let config = EmitterConfig::new() - .line_separator("\n") - .indent_string("\t") - .perform_indent(true) - .write_document_declaration(false) - .normalize_empty_elements(true) - .cdata_to_characters(true) - .keep_element_names_stack(false) - .autopad_comments(true); - - EventWriter { - xml_writer: XmlEventWriter::new_with_config(writer, config), - stack: Vec::new(), - empty_namespace: Namespace::empty(), - } - } - - fn write_element_and_value(&mut self, name: &str, value: &str) -> Result<()> { - self.start_element(name)?; - self.write_value(value)?; - self.end_element(name)?; - Ok(()) - } - - fn start_element(&mut self, name: &str) -> Result<()> { - self.xml_writer.write(WriteXmlEvent::StartElement { - name: Name::local(name), - attributes: Cow::Borrowed(&[]), - namespace: Cow::Borrowed(&self.empty_namespace), - })?; - Ok(()) - } - - fn end_element(&mut self, name: &str) -> Result<()> { - self.xml_writer.write(WriteXmlEvent::EndElement { - name: Some(Name::local(name)), - })?; - Ok(()) - } - - fn write_value(&mut self, value: &str) -> Result<()> { - self.xml_writer.write(WriteXmlEvent::Characters(value))?; - Ok(()) - } - - fn maybe_end_plist(&mut self) -> Result<()> { - // If there are no more open tags then write the element - if self.stack.len() == 1 { - // We didn't tell the xml_writer about the tag so we'll skip telling it - // about the tag as well. - self.xml_writer.inner_mut().write(b"\n")?; - if let Some(Element::Root) = self.stack.pop() { - } else { - return Err(Error::InvalidData); - } - } - Ok(()) - } - - pub fn write(&mut self, event: &PlistEvent) -> Result<()> { - ::write(self, event) - } -} - -impl PlistEventWriter for EventWriter { - fn write(&mut self, event: &PlistEvent) -> Result<()> { - match self.stack.pop() { - Some(Element::Dictionary(DictionaryState::ExpectKey)) => { - match *event { - PlistEvent::StringValue(ref value) => { - self.write_element_and_value("key", &*value)?; - self.stack - .push(Element::Dictionary(DictionaryState::ExpectValue)); - } - PlistEvent::EndDictionary => { - self.end_element("dict")?; - // We might be closing the last tag here as well - self.maybe_end_plist()?; - } - _ => return Err(Error::InvalidData), - }; - return Ok(()); - } - Some(Element::Dictionary(DictionaryState::ExpectValue)) => self.stack - .push(Element::Dictionary(DictionaryState::ExpectKey)), - Some(other) => self.stack.push(other), - None => { - // Write prologue - let prologue = r#" - - -"#; - self.xml_writer.inner_mut().write(prologue.as_bytes())?; - - self.stack.push(Element::Root); - } - } - - match *event { - PlistEvent::StartArray(_) => { - self.start_element("array")?; - self.stack.push(Element::Array); - } - PlistEvent::EndArray => { - self.end_element("array")?; - if let Some(Element::Array) = self.stack.pop() { - } else { - return Err(Error::InvalidData); - } - } - - PlistEvent::StartDictionary(_) => { - self.start_element("dict")?; - self.stack - .push(Element::Dictionary(DictionaryState::ExpectKey)); - } - PlistEvent::EndDictionary => return Err(Error::InvalidData), - - PlistEvent::BooleanValue(true) => { - self.start_element("true")?; - self.end_element("true")?; - } - PlistEvent::BooleanValue(false) => { - self.start_element("false")?; - self.end_element("false")?; - } - PlistEvent::DataValue(ref value) => { - let base64_data = base64::encode_config(&value, base64::MIME); - self.write_element_and_value("data", &base64_data)?; - } - PlistEvent::DateValue(ref value) => { - self.write_element_and_value("date", &value.to_rfc3339())? - } - PlistEvent::IntegerValue(ref value) => { - self.write_element_and_value("integer", &value.to_string())? - } - PlistEvent::RealValue(ref value) => { - self.write_element_and_value("real", &value.to_string())? - } - PlistEvent::StringValue(ref value) => self.write_element_and_value("string", &*value)?, - }; - - self.maybe_end_plist()?; - - Ok(()) - } -} - -#[cfg(test)] -mod tests { - use humantime::parse_rfc3339_weak; - use std::io::Cursor; - - use super::*; - - #[test] - fn streaming_parser() { - use PlistEvent::*; - - let plist = &[ - StartDictionary(None), - StringValue("Author".to_owned()), - StringValue("William Shakespeare".to_owned()), - StringValue("Lines".to_owned()), - StartArray(None), - StringValue("It is a tale told by an idiot,".to_owned()), - StringValue("Full of sound and fury, signifying nothing.".to_owned()), - EndArray, - StringValue("Death".to_owned()), - IntegerValue(1564), - StringValue("Height".to_owned()), - RealValue(1.60), - StringValue("Data".to_owned()), - DataValue(vec![0, 0, 0, 190, 0, 0, 0, 3, 0, 0, 0, 30, 0, 0, 0]), - StringValue("Birthdate".to_owned()), - DateValue(parse_rfc3339_weak("1981-05-16 11:32:06").unwrap().into()), - StringValue("Comment".to_owned()), - StringValue("2 < 3".to_owned()), // make sure characters are escaped - EndDictionary, - ]; - - let mut cursor = Cursor::new(Vec::new()); - - { - let mut plist_w = EventWriter::new(&mut cursor); - - for item in plist { - plist_w.write(item).unwrap(); - } - } - - let comparison = " - - - -\tAuthor -\tWilliam Shakespeare -\tLines -\t -\t\tIt is a tale told by an idiot, -\t\tFull of sound and fury, signifying nothing. -\t -\tDeath -\t1564 -\tHeight -\t1.6 -\tData -\tAAAAvgAAAAMAAAAeAAAA -\tBirthdate -\t1981-05-16T11:32:06Z -\tComment -\t2 < 3 - -"; - - let s = String::from_utf8(cursor.into_inner()).unwrap(); - - assert_eq!(s, comparison); - } -} diff --git a/tests/fuzzer.rs b/tests/fuzzer.rs index 539c689..160bc53 100644 --- a/tests/fuzzer.rs +++ b/tests/fuzzer.rs @@ -1,6 +1,6 @@ extern crate plist; -use plist::{Error, Plist}; +use plist::{Error, Value}; use std::io::Cursor; #[test] @@ -59,9 +59,9 @@ fn issue_22_binary_with_byte_ref_size() { test_fuzzer_data_ok(data); } -fn test_fuzzer_data(data: &[u8]) -> Result { +fn test_fuzzer_data(data: &[u8]) -> Result { let cursor = Cursor::new(data); - Plist::read(cursor) + Value::read(cursor) } fn test_fuzzer_data_ok(data: &[u8]) { diff --git a/tests/serde_tests/mod.rs b/tests/serde_tests/mod.rs index d908f08..881dc7b 100644 --- a/tests/serde_tests/mod.rs +++ b/tests/serde_tests/mod.rs @@ -1,13 +1,14 @@ -use plist::PlistEvent::*; -use plist::serde::{Deserializer, Serializer}; -use plist::{Date, Error, EventWriter, PlistEvent}; +use plist::events::Event; +use plist::events::Event::*; +use plist::events::Writer; +use plist::{Date, Deserializer, Error, Serializer}; use serde::de::DeserializeOwned; use serde::ser::Serialize; use std::fmt::Debug; use std::time::SystemTime; struct VecWriter { - events: Vec, + events: Vec, } impl VecWriter { @@ -15,13 +16,13 @@ impl VecWriter { VecWriter { events: Vec::new() } } - pub fn into_inner(self) -> Vec { + pub fn into_inner(self) -> Vec { self.events } } -impl EventWriter for VecWriter { - fn write(&mut self, event: &PlistEvent) -> Result<(), Error> { +impl Writer for VecWriter { + fn write(&mut self, event: &Event) -> Result<(), Error> { self.events.push(event.clone()); Ok(()) } @@ -31,12 +32,12 @@ fn new_serializer() -> Serializer { Serializer::new(VecWriter::new()) } -fn new_deserializer(events: Vec) -> Deserializer>> { +fn new_deserializer(events: Vec) -> Deserializer>> { let result_events = events.into_iter().map(Ok).collect(); Deserializer::new(result_events) } -fn assert_roundtrip(obj: T, comparison: Option<&[PlistEvent]>) +fn assert_roundtrip(obj: T, comparison: Option<&[Event]>) where T: Debug + DeserializeOwned + PartialEq + Serialize, { @@ -98,13 +99,11 @@ fn cow() { #[test] fn dog() { let dog = Animal::Dog(DogOuter { - inner: vec![ - DogInner { - a: (), - b: 12, - c: vec!["a".to_string(), "b".to_string()], - }, - ], + inner: vec![DogInner { + a: (), + b: 12, + c: vec!["a".to_string(), "b".to_string()], + }], }); let comparison = &[ -- cgit v1.2.3