diff options
| author | Edward Barnard | 2018-05-17 20:30:41 +0100 | 
|---|---|---|
| committer | Edward Barnard | 2018-05-17 20:50:21 +0100 | 
| commit | 2af279c344a6a917ce4102fec82e6cba8cf8b37c (patch) | |
| tree | a2d3746d4981e8e22e30b91fd3b4d1821444777a | |
| parent | d8a4f4ef2a0e80f1dc6237678410807cce83cce0 (diff) | |
| download | rust-plist-2af279c344a6a917ce4102fec82e6cba8cf8b37c.tar.bz2 | |
Reorganise crate.
| -rw-r--r-- | src/binary/mod.rs | 3 | ||||
| -rw-r--r-- | src/builder.rs | 62 | ||||
| -rw-r--r-- | src/date.rs | 4 | ||||
| -rw-r--r-- | src/de.rs (renamed from src/serde/de.rs) | 86 | ||||
| -rw-r--r-- | src/events/binary_reader.rs (renamed from src/binary/reader.rs) | 73 | ||||
| -rw-r--r-- | src/events/mod.rs | 95 | ||||
| -rw-r--r-- | src/events/xml_reader.rs (renamed from src/xml/reader.rs) | 72 | ||||
| -rw-r--r-- | src/events/xml_writer.rs (renamed from src/xml/writer.rs) | 66 | ||||
| -rw-r--r-- | src/lib.rs | 111 | ||||
| -rw-r--r-- | src/plist.rs | 376 | ||||
| -rw-r--r-- | src/ser.rs (renamed from src/serde/ser.rs) | 86 | ||||
| -rw-r--r-- | src/serde/mod.rs | 25 | ||||
| -rw-r--r-- | src/value.rs | 377 | ||||
| -rw-r--r-- | src/xml/mod.rs | 5 | ||||
| -rw-r--r-- | tests/fuzzer.rs | 6 | ||||
| -rw-r--r-- | tests/serde_tests/mod.rs | 31 | 
16 files changed, 737 insertions, 741 deletions
| 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/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<T> {      stream: T, -    token: Option<PlistEvent>, +    token: Option<Event>,  } -impl<T: Iterator<Item = Result<PlistEvent>>> Builder<T> { +impl<T: Iterator<Item = Result<Event>>> Builder<T> {      pub fn new(stream: T) -> Builder<T> {          Builder {              stream: stream, @@ -15,7 +16,7 @@ impl<T: Iterator<Item = Result<PlistEvent>>> Builder<T> {          }      } -    pub fn build(mut self) -> Result<Plist> { +    pub fn build(mut self) -> Result<Value> {          self.bump()?;          let plist = self.build_value()?; @@ -37,27 +38,27 @@ impl<T: Iterator<Item = Result<PlistEvent>>> Builder<T> {          Ok(())      } -    fn build_value(&mut self) -> Result<Plist> { +    fn build_value(&mut self) -> Result<Value> {          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<u64>) -> Result<Vec<Plist>> { +    fn build_array(&mut self, len: Option<u64>) -> Result<Vec<Value>> {          let len = u64_option_to_usize(len)?;          let mut values = match len {              Some(len) => Vec::with_capacity(len), @@ -66,7 +67,7 @@ impl<T: Iterator<Item = Result<PlistEvent>>> Builder<T> {          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<T: Iterator<Item = Result<PlistEvent>>> Builder<T> {          }      } -    fn build_dict(&mut self, _len: Option<u64>) -> Result<BTreeMap<String, Plist>> { +    fn build_dict(&mut self, _len: Option<u64>) -> Result<BTreeMap<String, Value>> {          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<SystemTime> 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/serde/de.rs b/src/de.rs index 58e0973..148b7b7 100644 --- a/src/serde/de.rs +++ b/src/de.rs @@ -1,8 +1,10 @@ -use serde_base::de; +use serde::de;  use std::fmt::Display; +use std::io::{Read, Seek};  use std::iter::Peekable; -use {Error, PlistEvent, u64_option_to_usize}; +use events::{self, Event}; +use {u64_option_to_usize, Error};  macro_rules! expect {      ($next:expr, $pat:pat) => { @@ -43,14 +45,14 @@ impl de::Error for Error {  pub struct Deserializer<I>  where -    I: IntoIterator<Item = Result<PlistEvent, Error>>, +    I: IntoIterator<Item = Result<Event, Error>>,  {      events: Peekable<<I as IntoIterator>::IntoIter>,  }  impl<I> Deserializer<I>  where -    I: IntoIterator<Item = Result<PlistEvent, Error>>, +    I: IntoIterator<Item = Result<Event, Error>>,  {      pub fn new(iter: I) -> Deserializer<I> {          Deserializer { @@ -61,7 +63,7 @@ where  impl<'de, 'a, I> de::Deserializer<'de> for &'a mut Deserializer<I>  where -    I: IntoIterator<Item = Result<PlistEvent, Error>>, +    I: IntoIterator<Item = Result<Event, Error>>,  {      type Error = Error; @@ -70,29 +72,29 @@ where          V: de::Visitor<'de>,      {          match try_next!(self.events.next()) { -            PlistEvent::StartArray(len) => { +            Event::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); +                expect!(self.events.next(), Event::EndArray);                  Ok(ret)              } -            PlistEvent::EndArray => Err(event_mismatch_error()), +            Event::EndArray => Err(event_mismatch_error()), -            PlistEvent::StartDictionary(len) => { +            Event::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); +                expect!(self.events.next(), Event::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), +            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),          }      } @@ -106,7 +108,7 @@ where      where          V: de::Visitor<'de>,      { -        expect!(self.events.next(), PlistEvent::StringValue(_)); +        expect!(self.events.next(), Event::StringValue(_));          visitor.visit_unit()      } @@ -114,18 +116,18 @@ where      where          V: de::Visitor<'de>,      { -        expect!(self.events.next(), PlistEvent::StartDictionary(_)); +        expect!(self.events.next(), Event::StartDictionary(_));          let ret = match try_next!(self.events.next()) { -            PlistEvent::StringValue(ref s) if &s[..] == "None" => { -                expect!(self.events.next(), PlistEvent::StringValue(_)); +            Event::StringValue(ref s) if &s[..] == "None" => { +                expect!(self.events.next(), Event::StringValue(_));                  visitor.visit_none::<Self::Error>()?              } -            PlistEvent::StringValue(ref s) if &s[..] == "Some" => visitor.visit_some(&mut *self)?, +            Event::StringValue(ref s) if &s[..] == "Some" => visitor.visit_some(&mut *self)?,              _ => return Err(event_mismatch_error()),          }; -        expect!(self.events.next(), PlistEvent::EndDictionary); +        expect!(self.events.next(), Event::EndDictionary);          Ok(ret)      } @@ -150,9 +152,9 @@ where      where          V: de::Visitor<'de>,      { -        expect!(self.events.next(), PlistEvent::StartDictionary(_)); +        expect!(self.events.next(), Event::StartDictionary(_));          let ret = visitor.visit_map(MapAndSeqAccess::new(self, true, None))?; -        expect!(self.events.next(), PlistEvent::EndDictionary); +        expect!(self.events.next(), Event::EndDictionary);          Ok(ret)      } @@ -165,16 +167,16 @@ where      where          V: de::Visitor<'de>,      { -        expect!(self.events.next(), PlistEvent::StartDictionary(_)); +        expect!(self.events.next(), Event::StartDictionary(_));          let ret = visitor.visit_enum(&mut *self)?; -        expect!(self.events.next(), PlistEvent::EndDictionary); +        expect!(self.events.next(), Event::EndDictionary);          Ok(ret)      }  }  impl<'de, 'a, I> de::EnumAccess<'de> for &'a mut Deserializer<I>  where -    I: IntoIterator<Item = Result<PlistEvent, Error>>, +    I: IntoIterator<Item = Result<Event, Error>>,  {      type Error = Error;      type Variant = Self; @@ -189,7 +191,7 @@ where  impl<'de, 'a, I> de::VariantAccess<'de> for &'a mut Deserializer<I>  where -    I: IntoIterator<Item = Result<PlistEvent, Error>>, +    I: IntoIterator<Item = Result<Event, Error>>,  {      type Error = Error; @@ -226,14 +228,14 @@ where  pub struct StructValueDeserializer<'a, I: 'a>  where -    I: IntoIterator<Item = Result<PlistEvent, Error>>, +    I: IntoIterator<Item = Result<Event, Error>>,  {      de: &'a mut Deserializer<I>,  }  impl<'de, 'a, I> de::Deserializer<'de> for StructValueDeserializer<'a, I>  where -    I: IntoIterator<Item = Result<PlistEvent, Error>>, +    I: IntoIterator<Item = Result<Event, Error>>,  {      type Error = Error; @@ -303,7 +305,7 @@ where  struct MapAndSeqAccess<'a, I>  where -    I: 'a + IntoIterator<Item = Result<PlistEvent, Error>>, +    I: 'a + IntoIterator<Item = Result<Event, Error>>,  {      de: &'a mut Deserializer<I>,      is_struct: bool, @@ -312,7 +314,7 @@ where  impl<'a, I> MapAndSeqAccess<'a, I>  where -    I: 'a + IntoIterator<Item = Result<PlistEvent, Error>>, +    I: 'a + IntoIterator<Item = Result<Event, Error>>,  {      fn new(          de: &'a mut Deserializer<I>, @@ -329,7 +331,7 @@ where  impl<'de, 'a, I> de::SeqAccess<'de> for MapAndSeqAccess<'a, I>  where -    I: 'a + IntoIterator<Item = Result<PlistEvent, Error>>, +    I: 'a + IntoIterator<Item = Result<Event, Error>>,  {      type Error = Error; @@ -337,7 +339,7 @@ where      where          T: de::DeserializeSeed<'de>,      { -        if let Some(&Ok(PlistEvent::EndArray)) = self.de.events.peek() { +        if let Some(&Ok(Event::EndArray)) = self.de.events.peek() {              return Ok(None);          } @@ -352,7 +354,7 @@ where  impl<'de, 'a, I> de::MapAccess<'de> for MapAndSeqAccess<'a, I>  where -    I: 'a + IntoIterator<Item = Result<PlistEvent, Error>>, +    I: 'a + IntoIterator<Item = Result<Event, Error>>,  {      type Error = Error; @@ -360,7 +362,7 @@ where      where          K: de::DeserializeSeed<'de>,      { -        if let Some(&Ok(PlistEvent::EndDictionary)) = self.de.events.peek() { +        if let Some(&Ok(Event::EndDictionary)) = self.de.events.peek() {              return Ok(None);          } @@ -383,3 +385,9 @@ where          self.remaining      }  } + +pub fn deserialize<R: Read + Seek, T: de::DeserializeOwned>(reader: R) -> Result<T, Error> { +    let reader = events::Reader::new(reader); +    let mut de = Deserializer::new(reader); +    de::Deserialize::deserialize(&mut de) +} diff --git a/src/binary/reader.rs b/src/events/binary_reader.rs index bee34f7..e077904 100644 --- a/src/binary/reader.rs +++ b/src/events/binary_reader.rs @@ -3,7 +3,8 @@ use std::io::{Read, Seek, SeekFrom};  use std::mem::size_of;  use std::string::{FromUtf16Error, FromUtf8Error}; -use {Date, Error, PlistEvent, Result, u64_to_usize}; +use events::Event; +use {u64_to_usize, Date, Error, Result};  impl From<FromUtf8Error> for Error {      fn from(_: FromUtf8Error) -> Error { @@ -30,7 +31,7 @@ enum StackType {  /// https://opensource.apple.com/source/CF/CF-550/CFBinaryPList.c  /// https://hg.python.org/cpython/file/3.4/Lib/plistlib.py -pub struct EventReader<R> { +pub struct BinaryReader<R> {      stack: Vec<StackItem>,      object_offsets: Vec<u64>,      reader: R, @@ -48,9 +49,9 @@ pub struct EventReader<R> {      current_objects: usize,  } -impl<R: Read + Seek> EventReader<R> { -    pub fn new(reader: R) -> EventReader<R> { -        EventReader { +impl<R: Read + Seek> BinaryReader<R> { +    pub fn new(reader: R) -> BinaryReader<R> { +        BinaryReader {              stack: Vec::new(),              object_offsets: Vec::new(),              reader: reader, @@ -165,13 +166,14 @@ impl<R: Read + Seek> EventReader<R> {      fn seek_to_object(&mut self, object_ref: u64) -> Result<u64> {          let object_ref = u64_to_usize(object_ref)?; -        let offset = *self.object_offsets +        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<Option<PlistEvent>> { +    fn read_next(&mut self) -> Result<Option<Event>> {          if self.ref_size == 0 {              // Initialise here rather than in new              self.read_trailer()?; @@ -195,8 +197,8 @@ impl<R: Read + Seek> EventReader<R> {                  // 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)), +                    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),                  } @@ -209,40 +211,40 @@ impl<R: Read + Seek> EventReader<R> {          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, 0x08) => Some(Event::BooleanValue(false)), +            (0x0, 0x09) => Some(Event::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::<BigEndian>()? as i64, +            (0x1, 0) => Some(Event::IntegerValue(self.reader.read_u8()? as i64)), +            (0x1, 1) => Some(Event::IntegerValue( +                self.reader.read_u16::<BigEndian>()? as i64              )), -            (0x1, 2) => Some(PlistEvent::IntegerValue( -                self.reader.read_u32::<BigEndian>()? as i64, +            (0x1, 2) => Some(Event::IntegerValue( +                self.reader.read_u32::<BigEndian>()? as i64              )), -            (0x1, 3) => Some(PlistEvent::IntegerValue(self.reader.read_i64::<BigEndian>()?)), +            (0x1, 3) => Some(Event::IntegerValue(self.reader.read_i64::<BigEndian>()?)),              (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::<BigEndian>()? as f64)), -            (0x2, 3) => Some(PlistEvent::RealValue(self.reader.read_f64::<BigEndian>()?)), +            (0x2, 2) => Some(Event::RealValue(self.reader.read_f32::<BigEndian>()? as f64)), +            (0x2, 3) => Some(Event::RealValue(self.reader.read_f64::<BigEndian>()?)),              (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::<BigEndian>()?; -                Some(PlistEvent::DateValue(Date::from_seconds_since_plist_epoch( +                Some(Event::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)?)) +                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(PlistEvent::StringValue(string)) +                Some(Event::StringValue(string))              }              (0x6, n) => {                  // UTF-16 string @@ -254,7 +256,7 @@ impl<R: Read + Seek> EventReader<R> {                  }                  let string = String::from_utf16(&raw_utf16)?; -                Some(PlistEvent::StringValue(string)) +                Some(Event::StringValue(string))              }              (0xa, n) => {                  // Array @@ -268,7 +270,7 @@ impl<R: Read + Seek> EventReader<R> {                      object_refs: object_refs,                  }); -                Some(PlistEvent::StartArray(Some(len))) +                Some(Event::StartArray(Some(len)))              }              (0xd, n) => {                  // Dict @@ -289,7 +291,7 @@ impl<R: Read + Seek> EventReader<R> {                      object_refs: object_refs,                  }); -                Some(PlistEvent::StartDictionary(Some(len as u64))) +                Some(Event::StartDictionary(Some(len as u64)))              }              (_, _) => return Err(Error::InvalidData),          }; @@ -303,10 +305,10 @@ impl<R: Read + Seek> EventReader<R> {      }  } -impl<R: Read + Seek> Iterator for EventReader<R> { -    type Item = Result<PlistEvent>; +impl<R: Read + Seek> Iterator for BinaryReader<R> { +    type Item = Result<Event>; -    fn next(&mut self) -> Option<Result<PlistEvent>> { +    fn next(&mut self) -> Option<Result<Event>> {          if self.finished {              None          } else { @@ -332,15 +334,14 @@ mod tests {      use std::path::Path;      use super::*; -    use PlistEvent; +    use events::Event; +    use events::Event::*;      #[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<PlistEvent> = streaming_parser.map(|e| e.unwrap()).collect(); +        let streaming_parser = BinaryReader::new(reader); +        let events: Vec<Event> = streaming_parser.map(|e| e.unwrap()).collect();          let comparison = &[              StartDictionary(Some(6)), @@ -367,11 +368,9 @@ mod tests {      #[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<PlistEvent> = streaming_parser.map(|e| e.unwrap()).collect(); +        let streaming_parser = BinaryReader::new(reader); +        let mut events: Vec<Event> = streaming_parser.map(|e| e.unwrap()).collect();          assert_eq!(events[2], StringValue("\u{2605} or better".to_owned())); 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<u64>), +    EndArray, + +    StartDictionary(Option<u64>), +    EndDictionary, + +    BooleanValue(bool), +    DataValue(Vec<u8>), +    DateValue(Date), +    IntegerValue(i64), +    RealValue(f64), +    StringValue(String), +} + +pub struct Reader<R: Read + Seek>(ReaderInner<R>); + +enum ReaderInner<R: Read + Seek> { +    Uninitialized(Option<R>), +    Xml(XmlReader<R>), +    Binary(BinaryReader<R>), +} + +impl<R: Read + Seek> Reader<R> { +    pub fn new(reader: R) -> Reader<R> { +        Reader(ReaderInner::Uninitialized(Some(reader))) +    } + +    fn is_binary(reader: &mut R) -> Result<bool> { +        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<R: Read + Seek> Iterator for Reader<R> { +    type Item = Result<Event>; + +    fn next(&mut self) -> Option<Result<Event>> { +        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/xml/reader.rs b/src/events/xml_reader.rs index 6642d59..46e0062 100644 --- a/src/xml/reader.rs +++ b/src/events/xml_reader.rs @@ -1,19 +1,20 @@  use base64;  use std::io::Read;  use std::str::FromStr; -use xml_rs::reader::{EventReader as XmlEventReader, ParserConfig, XmlEvent}; +use xml_rs::reader::{EventReader, ParserConfig, XmlEvent}; -use {Date, Error, PlistEvent, Result}; +use events::Event; +use {Date, Error, Result}; -pub struct EventReader<R: Read> { -    xml_reader: XmlEventReader<R>, +pub struct XmlReader<R: Read> { +    xml_reader: EventReader<R>,      queued_event: Option<XmlEvent>,      element_stack: Vec<String>,      finished: bool,  } -impl<R: Read> EventReader<R> { -    pub fn new(reader: R) -> EventReader<R> { +impl<R: Read> XmlReader<R> { +    pub fn new(reader: R) -> XmlReader<R> {          let config = ParserConfig::new()              .trim_whitespace(false)              .whitespace_to_characters(true) @@ -21,17 +22,17 @@ impl<R: Read> EventReader<R> {              .ignore_comments(true)              .coalesce_characters(true); -        EventReader { -            xml_reader: XmlEventReader::new_with_config(reader, config), +        XmlReader { +            xml_reader: EventReader::new_with_config(reader, config),              queued_event: None,              element_stack: Vec::new(),              finished: false,          }      } -    fn read_content<F>(&mut self, f: F) -> Result<PlistEvent> +    fn read_content<F>(&mut self, f: F) -> Result<Event>      where -        F: FnOnce(String) -> Result<PlistEvent>, +        F: FnOnce(String) -> Result<Event>,      {          match self.xml_reader.next() {              Ok(XmlEvent::Characters(s)) => f(s), @@ -51,7 +52,7 @@ impl<R: Read> EventReader<R> {          }      } -    fn read_next(&mut self) -> Option<Result<PlistEvent>> { +    fn read_next(&mut self) -> Option<Result<Event>> {          loop {              match self.next_event() {                  Ok(XmlEvent::StartElement { name, .. }) => { @@ -60,38 +61,38 @@ impl<R: Read> EventReader<R> {                      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))), +                        "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(PlistEvent::DataValue(data)) +                                Ok(Event::DataValue(data))                              }))                          }                          "date" => { -                            return Some(self.read_content(|s| { -                                Ok(PlistEvent::DateValue(Date::from_rfc3339(&s)?)) -                            })) +                            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(PlistEvent::IntegerValue(i)), +                                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(PlistEvent::RealValue(f)), +                                Ok(f) => Ok(Event::RealValue(f)),                                  Err(_) => Err(Error::InvalidData),                              }))                          } -                        "string" => { -                            return Some(self.read_content(|s| Ok(PlistEvent::StringValue(s)))) -                        } +                        "string" => return Some(self.read_content(|s| Ok(Event::StringValue(s)))),                          _ => return Some(Err(Error::InvalidData)),                      }                  } @@ -104,8 +105,8 @@ impl<R: Read> EventReader<R> {                      }                      match &name.local_name[..] { -                        "array" => return Some(Ok(PlistEvent::EndArray)), -                        "dict" => return Some(Ok(PlistEvent::EndDictionary)), +                        "array" => return Some(Ok(Event::EndArray)), +                        "dict" => return Some(Ok(Event::EndDictionary)),                          "plist" => (),                          _ => (),                      } @@ -124,10 +125,10 @@ impl<R: Read> EventReader<R> {      }  } -impl<R: Read> Iterator for EventReader<R> { -    type Item = Result<PlistEvent>; +impl<R: Read> Iterator for XmlReader<R> { +    type Item = Result<Event>; -    fn next(&mut self) -> Option<Result<PlistEvent>> { +    fn next(&mut self) -> Option<Result<Event>> {          if self.finished {              None          } else { @@ -153,15 +154,14 @@ mod tests {      use std::path::Path;      use super::*; -    use PlistEvent; +    use events::Event; +    use events::Event::*;      #[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<PlistEvent> = streaming_parser.map(|e| e.unwrap()).collect(); +        let streaming_parser = XmlReader::new(reader); +        let events: Vec<Event> = streaming_parser.map(|e| e.unwrap()).collect();          let comparison = &[              StartDictionary(None), @@ -191,7 +191,7 @@ mod tests {      #[test]      fn bad_data() {          let reader = File::open(&Path::new("./tests/data/xml_error.plist")).unwrap(); -        let streaming_parser = EventReader::new(reader); +        let streaming_parser = XmlReader::new(reader);          let events: Vec<_> = streaming_parser.collect();          assert!(events.last().unwrap().is_err()); diff --git a/src/xml/writer.rs b/src/events/xml_writer.rs index e002e55..f89ea81 100644 --- a/src/xml/writer.rs +++ b/src/events/xml_writer.rs @@ -3,10 +3,10 @@ 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 xml_rs::writer::{EmitterConfig, Error as XmlWriterError, EventWriter, XmlEvent}; -use {Error, EventWriter as PlistEventWriter, PlistEvent, Result}; +use events::{Event, Writer}; +use {Error, Result};  impl From<XmlWriterError> for Error {      fn from(err: XmlWriterError) -> Error { @@ -28,15 +28,15 @@ enum DictionaryState {      ExpectValue,  } -pub struct EventWriter<W: Write> { -    xml_writer: XmlEventWriter<W>, +pub struct XmlWriter<W: Write> { +    xml_writer: EventWriter<W>,      stack: Vec<Element>,      // Not very nice      empty_namespace: Namespace,  } -impl<W: Write> EventWriter<W> { -    pub fn new(writer: W) -> EventWriter<W> { +impl<W: Write> XmlWriter<W> { +    pub fn new(writer: W) -> XmlWriter<W> {          let config = EmitterConfig::new()              .line_separator("\n")              .indent_string("\t") @@ -47,8 +47,8 @@ impl<W: Write> EventWriter<W> {              .keep_element_names_stack(false)              .autopad_comments(true); -        EventWriter { -            xml_writer: XmlEventWriter::new_with_config(writer, config), +        XmlWriter { +            xml_writer: EventWriter::new_with_config(writer, config),              stack: Vec::new(),              empty_namespace: Namespace::empty(),          } @@ -62,7 +62,7 @@ impl<W: Write> EventWriter<W> {      }      fn start_element(&mut self, name: &str) -> Result<()> { -        self.xml_writer.write(WriteXmlEvent::StartElement { +        self.xml_writer.write(XmlEvent::StartElement {              name: Name::local(name),              attributes: Cow::Borrowed(&[]),              namespace: Cow::Borrowed(&self.empty_namespace), @@ -71,14 +71,14 @@ impl<W: Write> EventWriter<W> {      }      fn end_element(&mut self, name: &str) -> Result<()> { -        self.xml_writer.write(WriteXmlEvent::EndElement { +        self.xml_writer.write(XmlEvent::EndElement {              name: Some(Name::local(name)),          })?;          Ok(())      }      fn write_value(&mut self, value: &str) -> Result<()> { -        self.xml_writer.write(WriteXmlEvent::Characters(value))?; +        self.xml_writer.write(XmlEvent::Characters(value))?;          Ok(())      } @@ -96,22 +96,22 @@ impl<W: Write> EventWriter<W> {          Ok(())      } -    pub fn write(&mut self, event: &PlistEvent) -> Result<()> { -        <Self as PlistEventWriter>::write(self, event) +    pub fn write(&mut self, event: &Event) -> Result<()> { +        <Self as Writer>::write(self, event)      }  } -impl<W: Write> PlistEventWriter for EventWriter<W> { -    fn write(&mut self, event: &PlistEvent) -> Result<()> { +impl<W: Write> Writer for XmlWriter<W> { +    fn write(&mut self, event: &Event) -> Result<()> {          match self.stack.pop() {              Some(Element::Dictionary(DictionaryState::ExpectKey)) => {                  match *event { -                    PlistEvent::StringValue(ref value) => { +                    Event::StringValue(ref value) => {                          self.write_element_and_value("key", &*value)?;                          self.stack                              .push(Element::Dictionary(DictionaryState::ExpectValue));                      } -                    PlistEvent::EndDictionary => { +                    Event::EndDictionary => {                          self.end_element("dict")?;                          // We might be closing the last tag here as well                          self.maybe_end_plist()?; @@ -120,7 +120,8 @@ impl<W: Write> PlistEventWriter for EventWriter<W> {                  };                  return Ok(());              } -            Some(Element::Dictionary(DictionaryState::ExpectValue)) => self.stack +            Some(Element::Dictionary(DictionaryState::ExpectValue)) => self +                .stack                  .push(Element::Dictionary(DictionaryState::ExpectKey)),              Some(other) => self.stack.push(other),              None => { @@ -136,11 +137,11 @@ impl<W: Write> PlistEventWriter for EventWriter<W> {          }          match *event { -            PlistEvent::StartArray(_) => { +            Event::StartArray(_) => {                  self.start_element("array")?;                  self.stack.push(Element::Array);              } -            PlistEvent::EndArray => { +            Event::EndArray => {                  self.end_element("array")?;                  if let Some(Element::Array) = self.stack.pop() {                  } else { @@ -148,35 +149,35 @@ impl<W: Write> PlistEventWriter for EventWriter<W> {                  }              } -            PlistEvent::StartDictionary(_) => { +            Event::StartDictionary(_) => {                  self.start_element("dict")?;                  self.stack                      .push(Element::Dictionary(DictionaryState::ExpectKey));              } -            PlistEvent::EndDictionary => return Err(Error::InvalidData), +            Event::EndDictionary => return Err(Error::InvalidData), -            PlistEvent::BooleanValue(true) => { +            Event::BooleanValue(true) => {                  self.start_element("true")?;                  self.end_element("true")?;              } -            PlistEvent::BooleanValue(false) => { +            Event::BooleanValue(false) => {                  self.start_element("false")?;                  self.end_element("false")?;              } -            PlistEvent::DataValue(ref value) => { +            Event::DataValue(ref value) => {                  let base64_data = base64::encode_config(&value, base64::MIME);                  self.write_element_and_value("data", &base64_data)?;              } -            PlistEvent::DateValue(ref value) => { +            Event::DateValue(ref value) => {                  self.write_element_and_value("date", &value.to_rfc3339())?              } -            PlistEvent::IntegerValue(ref value) => { +            Event::IntegerValue(ref value) => {                  self.write_element_and_value("integer", &value.to_string())?              } -            PlistEvent::RealValue(ref value) => { +            Event::RealValue(ref value) => {                  self.write_element_and_value("real", &value.to_string())?              } -            PlistEvent::StringValue(ref value) => self.write_element_and_value("string", &*value)?, +            Event::StringValue(ref value) => self.write_element_and_value("string", &*value)?,          };          self.maybe_end_plist()?; @@ -191,11 +192,10 @@ mod tests {      use std::io::Cursor;      use super::*; +    use events::Event::*;      #[test]      fn streaming_parser() { -        use PlistEvent::*; -          let plist = &[              StartDictionary(None),              StringValue("Author".to_owned()), @@ -221,7 +221,7 @@ mod tests {          let mut cursor = Cursor::new(Vec::new());          { -            let mut plist_w = EventWriter::new(&mut cursor); +            let mut plist_w = XmlWriter::new(&mut cursor);              for item in plist {                  plist_w.write(item).unwrap(); @@ -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<u64>), -    EndArray, - -    StartDictionary(Option<u64>), -    EndDictionary, - -    BooleanValue(bool), -    DataValue(Vec<u8>), -    DateValue(Date), -    IntegerValue(i64), -    RealValue(f64), -    StringValue(String), -} +use std::io;  type Result<T> = ::std::result::Result<T, Error>; @@ -158,58 +131,6 @@ impl From<io::Error> for Error {      }  } -pub struct EventReader<R: Read + Seek>(EventReaderInner<R>); - -enum EventReaderInner<R: Read + Seek> { -    Uninitialized(Option<R>), -    Xml(xml::EventReader<R>), -    Binary(binary::EventReader<R>), -} - -impl<R: Read + Seek> EventReader<R> { -    pub fn new(reader: R) -> EventReader<R> { -        EventReader(EventReaderInner::Uninitialized(Some(reader))) -    } - -    fn is_binary(reader: &mut R) -> Result<bool> { -        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<R: Read + Seek> Iterator for EventReader<R> { -    type Item = Result<PlistEvent>; - -    fn next(&mut self) -> Option<Result<PlistEvent>> { -        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<usize> {      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<Plist>), -    Dictionary(BTreeMap<String, Plist>), -    Boolean(bool), -    Data(Vec<u8>), -    Date(Date), -    Real(f64), -    Integer(i64), -    String(String), -} - -impl Plist { -    pub fn read<R: Read + Seek>(reader: R) -> Result<Plist> { -        let reader = EventReader::new(reader); -        Plist::from_events(reader) -    } - -    pub fn from_events<T>(events: T) -> Result<Plist> -    where -        T: IntoIterator<Item = Result<PlistEvent>>, -    { -        let iter = events.into_iter(); -        let builder = builder::Builder::new(iter); -        builder.build() -    } - -    pub fn into_events(self) -> Vec<PlistEvent> { -        let mut events = Vec::new(); -        self.into_events_inner(&mut events); -        events -    } - -    fn into_events_inner(self, events: &mut Vec<PlistEvent>) { -        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<Plist>> { -        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<Plist>> { -        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<String, Plist>> { -        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<String, Plist>> { -        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<bool> { -        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<Vec<u8>> { -        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<f64> { -        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<i64> { -        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<String> { -        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<Vec<Plist>> for Plist { -    fn from(from: Vec<Plist>) -> Plist { -        Plist::Array(from) -    } -} - -impl From<BTreeMap<String, Plist>> for Plist { -    fn from(from: BTreeMap<String, Plist>) -> Plist { -        Plist::Dictionary(from) -    } -} - -impl From<bool> 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<Date> 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<f64> for Plist { -    fn from(from: f64) -> Plist { -        Plist::Real(from) -    } -} - -impl From<f32> for Plist { -    fn from(from: f32) -> Plist { -        Plist::Real(from as f64) -    } -} - -impl From<i64> for Plist { -    fn from(from: i64) -> Plist { -        Plist::Integer(from) -    } -} - -impl From<i32> for Plist { -    fn from(from: i32) -> Plist { -        Plist::Integer(from as i64) -    } -} - -impl From<i16> for Plist { -    fn from(from: i16) -> Plist { -        Plist::Integer(from as i64) -    } -} - -impl From<i8> for Plist { -    fn from(from: i8) -> Plist { -        Plist::Integer(from as i64) -    } -} - -impl From<u32> for Plist { -    fn from(from: u32) -> Plist { -        Plist::Integer(from as i64) -    } -} - -impl From<u16> for Plist { -    fn from(from: u16) -> Plist { -        Plist::Integer(from as i64) -    } -} - -impl From<u8> 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<String> 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/serde/ser.rs b/src/ser.rs index f9cb5b3..4a2a42b 100644 --- a/src/serde/ser.rs +++ b/src/ser.rs @@ -1,8 +1,10 @@ -use serde_base::ser; +use serde::ser;  use std::fmt::Display; +use std::io::Write;  use date::serde_impls::DATE_NEWTYPE_STRUCT_NAME; -use {Date, Error, EventWriter, PlistEvent}; +use events::{self, Event, Writer}; +use {Date, Error};  impl ser::Error for Error {      fn custom<T: Display>(msg: T) -> Self { @@ -10,16 +12,16 @@ impl ser::Error for Error {      }  } -pub struct Serializer<W: EventWriter> { +pub struct Serializer<W: Writer> {      writer: W,  } -impl<W: EventWriter> Serializer<W> { +impl<W: Writer> Serializer<W> {      pub fn new(writer: W) -> Serializer<W> {          Serializer { writer: writer }      } -    fn emit(&mut self, event: PlistEvent) -> Result<(), Error> { +    fn emit(&mut self, event: Event) -> Result<(), Error> {          self.writer.write(&event)?;          Ok(())      } @@ -30,18 +32,18 @@ impl<W: EventWriter> Serializer<W> {      // Emit {key: value}      fn single_key_dict(&mut self, key: String) -> Result<(), Error> { -        self.emit(PlistEvent::StartDictionary(Some(1)))?; -        self.emit(PlistEvent::StringValue(key))?; +        self.emit(Event::StartDictionary(Some(1)))?; +        self.emit(Event::StringValue(key))?;          Ok(())      }      fn single_key_dict_end(&mut self) -> Result<(), Error> { -        self.emit(PlistEvent::EndDictionary)?; +        self.emit(Event::EndDictionary)?;          Ok(())      }  } -impl<'a, W: EventWriter> ser::Serializer for &'a mut Serializer<W> { +impl<'a, W: Writer> ser::Serializer for &'a mut Serializer<W> {      type Ok = ();      type Error = Error; @@ -54,7 +56,7 @@ impl<'a, W: EventWriter> ser::Serializer for &'a mut Serializer<W> {      type SerializeStructVariant = Compound<'a, W>;      fn serialize_bool(self, v: bool) -> Result<(), Self::Error> { -        self.emit(PlistEvent::BooleanValue(v)) +        self.emit(Event::BooleanValue(v))      }      fn serialize_i8(self, v: i8) -> Result<(), Self::Error> { @@ -70,7 +72,7 @@ impl<'a, W: EventWriter> ser::Serializer for &'a mut Serializer<W> {      }      fn serialize_i64(self, v: i64) -> Result<(), Self::Error> { -        self.emit(PlistEvent::IntegerValue(v)) +        self.emit(Event::IntegerValue(v))      }      fn serialize_u8(self, v: u8) -> Result<(), Self::Error> { @@ -86,7 +88,7 @@ impl<'a, W: EventWriter> ser::Serializer for &'a mut Serializer<W> {      }      fn serialize_u64(self, v: u64) -> Result<(), Self::Error> { -        self.emit(PlistEvent::IntegerValue(v as i64)) +        self.emit(Event::IntegerValue(v as i64))      }      fn serialize_f32(self, v: f32) -> Result<(), Self::Error> { @@ -94,19 +96,19 @@ impl<'a, W: EventWriter> ser::Serializer for &'a mut Serializer<W> {      }      fn serialize_f64(self, v: f64) -> Result<(), Self::Error> { -        self.emit(PlistEvent::RealValue(v)) +        self.emit(Event::RealValue(v))      }      fn serialize_char(self, v: char) -> Result<(), Self::Error> { -        self.emit(PlistEvent::StringValue(v.to_string())) +        self.emit(Event::StringValue(v.to_string()))      }      fn serialize_str(self, v: &str) -> Result<(), Self::Error> { -        self.emit(PlistEvent::StringValue(v.to_owned())) +        self.emit(Event::StringValue(v.to_owned()))      }      fn serialize_bytes(self, v: &[u8]) -> Result<(), Self::Error> { -        self.emit(PlistEvent::DataValue(v.to_owned())) +        self.emit(Event::DataValue(v.to_owned()))      }      fn serialize_none(self) -> Result<(), Self::Error> { @@ -123,7 +125,7 @@ impl<'a, W: EventWriter> ser::Serializer for &'a mut Serializer<W> {      fn serialize_unit(self) -> Result<(), Self::Error> {          // Emit empty string -        self.emit(PlistEvent::StringValue(String::new())) +        self.emit(Event::StringValue(String::new()))      }      fn serialize_unit_struct(self, _name: &'static str) -> Result<(), Self::Error> { @@ -168,7 +170,7 @@ impl<'a, W: EventWriter> ser::Serializer for &'a mut Serializer<W> {      fn serialize_seq(self, len: Option<usize>) -> Result<Self::SerializeSeq, Self::Error> {          let len = len.map(|len| len as u64); -        self.emit(PlistEvent::StartArray(len))?; +        self.emit(Event::StartArray(len))?;          Ok(Compound { ser: self })      } @@ -197,7 +199,7 @@ impl<'a, W: EventWriter> ser::Serializer for &'a mut Serializer<W> {      fn serialize_map(self, len: Option<usize>) -> Result<Self::SerializeMap, Self::Error> {          let len = len.map(|len| len as u64); -        self.emit(PlistEvent::StartDictionary(len))?; +        self.emit(Event::StartDictionary(len))?;          Ok(Compound { ser: self })      } @@ -222,21 +224,21 @@ impl<'a, W: EventWriter> ser::Serializer for &'a mut Serializer<W> {      }  } -struct StructFieldSerializer<'a, W: 'a + EventWriter> { +struct StructFieldSerializer<'a, W: 'a + Writer> {      ser: &'a mut Serializer<W>,      field_name: &'static str,  } -impl<'a, W: EventWriter> StructFieldSerializer<'a, W> { +impl<'a, W: Writer> StructFieldSerializer<'a, W> {      fn use_ser(self) -> Result<&'a mut Serializer<W>, Error> {          // We are going to serialize something so write the struct field name.          self.ser -            .emit(PlistEvent::StringValue(self.field_name.to_owned()))?; +            .emit(Event::StringValue(self.field_name.to_owned()))?;          Ok(self.ser)      }  } -impl<'a, W: EventWriter> ser::Serializer for StructFieldSerializer<'a, W> { +impl<'a, W: Writer> ser::Serializer for StructFieldSerializer<'a, W> {      type Ok = ();      type Error = Error; @@ -402,17 +404,17 @@ impl<'a, W: EventWriter> ser::Serializer for StructFieldSerializer<'a, W> {      }  } -struct DateSerializer<'a, W: 'a + EventWriter> { +struct DateSerializer<'a, W: 'a + Writer> {      ser: &'a mut Serializer<W>,  } -impl<'a, W: EventWriter> DateSerializer<'a, W> { +impl<'a, W: Writer> 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> { +impl<'a, W: Writer> ser::Serializer for DateSerializer<'a, W> {      type Ok = ();      type Error = Error; @@ -474,7 +476,7 @@ impl<'a, W: EventWriter> ser::Serializer for DateSerializer<'a, W> {      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)) +        self.ser.emit(Event::DateValue(date))      }      fn serialize_bytes(self, _: &[u8]) -> Result<(), Self::Error> { @@ -574,11 +576,11 @@ impl<'a, W: EventWriter> ser::Serializer for DateSerializer<'a, W> {  }  #[doc(hidden)] -pub struct Compound<'a, W: 'a + EventWriter> { +pub struct Compound<'a, W: 'a + Writer> {      ser: &'a mut Serializer<W>,  } -impl<'a, W: EventWriter> ser::SerializeSeq for Compound<'a, W> { +impl<'a, W: Writer> ser::SerializeSeq for Compound<'a, W> {      type Ok = ();      type Error = Error; @@ -590,11 +592,11 @@ impl<'a, W: EventWriter> ser::SerializeSeq for Compound<'a, W> {      }      fn end(self) -> Result<Self::Ok, Self::Error> { -        self.ser.emit(PlistEvent::EndArray) +        self.ser.emit(Event::EndArray)      }  } -impl<'a, W: EventWriter> ser::SerializeTuple for Compound<'a, W> { +impl<'a, W: Writer> ser::SerializeTuple for Compound<'a, W> {      type Ok = ();      type Error = Error; @@ -610,7 +612,7 @@ impl<'a, W: EventWriter> ser::SerializeTuple for Compound<'a, W> {      }  } -impl<'a, W: EventWriter> ser::SerializeTupleStruct for Compound<'a, W> { +impl<'a, W: Writer> ser::SerializeTupleStruct for Compound<'a, W> {      type Ok = ();      type Error = Error; @@ -626,7 +628,7 @@ impl<'a, W: EventWriter> ser::SerializeTupleStruct for Compound<'a, W> {      }  } -impl<'a, W: EventWriter> ser::SerializeTupleVariant for Compound<'a, W> { +impl<'a, W: Writer> ser::SerializeTupleVariant for Compound<'a, W> {      type Ok = ();      type Error = Error; @@ -638,12 +640,12 @@ impl<'a, W: EventWriter> ser::SerializeTupleVariant for Compound<'a, W> {      }      fn end(self) -> Result<Self::Ok, Self::Error> { -        self.ser.emit(PlistEvent::EndArray)?; +        self.ser.emit(Event::EndArray)?;          self.ser.single_key_dict_end()      }  } -impl<'a, W: EventWriter> ser::SerializeMap for Compound<'a, W> { +impl<'a, W: Writer> ser::SerializeMap for Compound<'a, W> {      type Ok = ();      type Error = Error; @@ -659,11 +661,11 @@ impl<'a, W: EventWriter> ser::SerializeMap for Compound<'a, W> {      }      fn end(self) -> Result<Self::Ok, Self::Error> { -        self.ser.emit(PlistEvent::EndDictionary) +        self.ser.emit(Event::EndDictionary)      }  } -impl<'a, W: EventWriter> ser::SerializeStruct for Compound<'a, W> { +impl<'a, W: Writer> ser::SerializeStruct for Compound<'a, W> {      type Ok = ();      type Error = Error; @@ -685,7 +687,7 @@ impl<'a, W: EventWriter> ser::SerializeStruct for Compound<'a, W> {      }  } -impl<'a, W: EventWriter> ser::SerializeStructVariant for Compound<'a, W> { +impl<'a, W: Writer> ser::SerializeStructVariant for Compound<'a, W> {      type Ok = ();      type Error = Error; @@ -698,7 +700,13 @@ impl<'a, W: EventWriter> ser::SerializeStructVariant for Compound<'a, W> {      }      fn end(self) -> Result<Self::Ok, Self::Error> { -        self.ser.emit(PlistEvent::EndDictionary)?; +        self.ser.emit(Event::EndDictionary)?;          self.ser.single_key_dict_end()      }  } + +pub fn serialize_to_xml<W: Write, T: ser::Serialize>(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/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<R: Read + Seek, T: DeserializeOwned>(reader: R) -> Result<T> { -    let reader = EventReader::new(reader); -    let mut de = Deserializer::new(reader); -    Deserialize::deserialize(&mut de) -} - -pub fn serialize_to_xml<W: Write, T: Serialize>(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/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<Value>), +    Dictionary(BTreeMap<String, Value>), +    Boolean(bool), +    Data(Vec<u8>), +    Date(Date), +    Real(f64), +    Integer(i64), +    String(String), +} + +impl Value { +    pub fn read<R: Read + Seek>(reader: R) -> Result<Value> { +        let reader = Reader::new(reader); +        Value::from_events(reader) +    } + +    pub fn from_events<T>(events: T) -> Result<Value> +    where +        T: IntoIterator<Item = Result<Event>>, +    { +        let iter = events.into_iter(); +        let builder = builder::Builder::new(iter); +        builder.build() +    } + +    pub fn into_events(self) -> Vec<Event> { +        let mut events = Vec::new(); +        self.into_events_inner(&mut events); +        events +    } + +    fn into_events_inner(self, events: &mut Vec<Event>) { +        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<Value>> { +        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<Value>> { +        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<String, Value>> { +        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<String, Value>> { +        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<bool> { +        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<Vec<u8>> { +        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<f64> { +        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<i64> { +        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<String> { +        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<Vec<Value>> for Value { +    fn from(from: Vec<Value>) -> Value { +        Value::Array(from) +    } +} + +impl From<BTreeMap<String, Value>> for Value { +    fn from(from: BTreeMap<String, Value>) -> Value { +        Value::Dictionary(from) +    } +} + +impl From<bool> 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<Date> 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<f64> for Value { +    fn from(from: f64) -> Value { +        Value::Real(from) +    } +} + +impl From<f32> for Value { +    fn from(from: f32) -> Value { +        Value::Real(from as f64) +    } +} + +impl From<i64> for Value { +    fn from(from: i64) -> Value { +        Value::Integer(from) +    } +} + +impl From<i32> for Value { +    fn from(from: i32) -> Value { +        Value::Integer(from as i64) +    } +} + +impl From<i16> for Value { +    fn from(from: i16) -> Value { +        Value::Integer(from as i64) +    } +} + +impl From<i8> for Value { +    fn from(from: i8) -> Value { +        Value::Integer(from as i64) +    } +} + +impl From<u32> for Value { +    fn from(from: u32) -> Value { +        Value::Integer(from as i64) +    } +} + +impl From<u16> for Value { +    fn from(from: u16) -> Value { +        Value::Integer(from as i64) +    } +} + +impl From<u8> 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<String> 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/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<Plist, Error> { +fn test_fuzzer_data(data: &[u8]) -> Result<Value, Error> {      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<PlistEvent>, +    events: Vec<Event>,  }  impl VecWriter { @@ -15,13 +16,13 @@ impl VecWriter {          VecWriter { events: Vec::new() }      } -    pub fn into_inner(self) -> Vec<PlistEvent> { +    pub fn into_inner(self) -> Vec<Event> {          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<VecWriter> {      Serializer::new(VecWriter::new())  } -fn new_deserializer(events: Vec<PlistEvent>) -> Deserializer<Vec<Result<PlistEvent, Error>>> { +fn new_deserializer(events: Vec<Event>) -> Deserializer<Vec<Result<Event, Error>>> {      let result_events = events.into_iter().map(Ok).collect();      Deserializer::new(result_events)  } -fn assert_roundtrip<T>(obj: T, comparison: Option<&[PlistEvent]>) +fn assert_roundtrip<T>(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 = &[ | 
