use serde::de::{ self, value::{MapAccessDeserializer, MapDeserializer}, IntoDeserializer, }; use std::{ array::IntoIter, fmt::Display, fs::File, io::{BufReader, Cursor, Read, Seek}, iter::Peekable, mem, path::Path, }; use crate::{ date::serde_impls::DATE_NEWTYPE_STRUCT_NAME, error::{self, Error, ErrorKind, EventKind}, stream::{self, Event, OwnedEvent}, u64_to_usize, uid::serde_impls::UID_NEWTYPE_STRUCT_NAME, value::serde_impls::VALUE_NEWTYPE_STRUCT_NAME, }; macro_rules! expect { ($next:expr, $kind:expr) => { match $next { Some(Ok(ref event)) if EventKind::of_event(event) != $kind => { return Err(error::unexpected_event_type($kind, event))?; } Some(Ok(event)) => event, Some(Err(err)) => return Err(err), None => return Err(ErrorKind::UnexpectedEndOfEventStream.without_position()), } }; } macro_rules! try_next { ($next:expr) => { match $next { Some(Ok(event)) => event, Some(Err(err)) => return Err(err)?, None => return Err(ErrorKind::UnexpectedEndOfEventStream.without_position())?, } }; } #[doc(hidden)] impl de::Error for Error { fn custom(msg: T) -> Self { ErrorKind::Serde(msg.to_string()).without_position() } } enum OptionMode { Root, StructField, Explicit, } /// A structure that deserializes plist event streams into Rust values. pub struct Deserializer where I: IntoIterator>, { events: Peekable<::IntoIter>, option_mode: OptionMode, in_plist_value: bool, } impl Deserializer where I: IntoIterator>, { pub fn new(iter: I) -> Deserializer { Deserializer { events: iter.into_iter().peekable(), option_mode: OptionMode::Root, in_plist_value: false, } } fn with_option_mode) -> Result>( &mut self, option_mode: OptionMode, f: F, ) -> Result { let prev_option_mode = mem::replace(&mut self.option_mode, option_mode); let ret = f(&mut *self); self.option_mode = prev_option_mode; ret } fn enter_plist_value) -> Result>( &mut self, f: F, ) -> Result { let prev = mem::replace(&mut self.in_plist_value, true); let ret = f(&mut *self); self.in_plist_value = prev; ret } } 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 = len.and_then(u64_to_usize); let ret = visitor.visit_seq(MapAndSeqAccess::new(self, false, len))?; expect!(self.events.next(), EventKind::EndCollection); Ok(ret) } Event::StartDictionary(len) => { let len = len.and_then(u64_to_usize); let ret = visitor.visit_map(MapAndSeqAccess::new(self, false, len))?; expect!(self.events.next(), EventKind::EndCollection); Ok(ret) } event @ Event::EndCollection => Err(error::unexpected_event_type( EventKind::ValueOrStartCollection, &event, )), Event::Boolean(v) => visitor.visit_bool(v), Event::Data(v) => visitor.visit_byte_buf(v.into_owned()), Event::Date(v) if self.in_plist_value => { visitor.visit_enum(MapAccessDeserializer::new(MapDeserializer::new( IntoIter::new([(DATE_NEWTYPE_STRUCT_NAME, v.to_rfc3339())]), ))) } Event::Date(v) => visitor.visit_string(v.to_rfc3339()), Event::Integer(v) => { if let Some(v) = v.as_unsigned() { visitor.visit_u64(v) } else if let Some(v) = v.as_signed() { visitor.visit_i64(v) } else { unreachable!() } } Event::Real(v) => visitor.visit_f64(v), Event::String(v) => visitor.visit_string(v.into_owned()), Event::Uid(v) if self.in_plist_value => visitor.visit_enum(MapAccessDeserializer::new( MapDeserializer::new(IntoIter::new([(UID_NEWTYPE_STRUCT_NAME, v.get())])), )), Event::Uid(v) => visitor.visit_u64(v.get()), } } 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(), EventKind::String); visitor.visit_unit() } fn deserialize_option(self, visitor: V) -> Result where V: de::Visitor<'de>, { match self.option_mode { OptionMode::Root => { if self.events.peek().is_none() { visitor.visit_none::() } else { self.with_option_mode(OptionMode::Explicit, |this| visitor.visit_some(this)) } } OptionMode::StructField => { // None struct values are ignored so if we're here the value must be Some. self.with_option_mode(OptionMode::Explicit, |this| Ok(visitor.visit_some(this)?)) } OptionMode::Explicit => { expect!(self.events.next(), EventKind::StartDictionary); let ret = match try_next!(self.events.next()) { Event::String(ref s) if &s[..] == "None" => { expect!(self.events.next(), EventKind::String); visitor.visit_none::()? } Event::String(ref s) if &s[..] == "Some" => visitor.visit_some(&mut *self)?, event => return Err(error::unexpected_event_type(EventKind::String, &event))?, }; expect!(self.events.next(), EventKind::EndCollection); Ok(ret) } } } fn deserialize_newtype_struct( self, name: &'static str, visitor: V, ) -> Result where V: de::Visitor<'de>, { if name == VALUE_NEWTYPE_STRUCT_NAME { self.enter_plist_value(|this| visitor.visit_newtype_struct(this)) } else { 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(), EventKind::StartDictionary); let ret = visitor.visit_map(MapAndSeqAccess::new(self, true, None))?; expect!(self.events.next(), EventKind::EndCollection); Ok(ret) } fn deserialize_enum( self, name: &'static str, variants: &'static [&'static str], visitor: V, ) -> Result where V: de::Visitor<'de>, { // `plist` since v1.1 serialises unit enum variants as plain strings. if let Some(Ok(Event::String(s))) = self.events.peek() { return s .as_ref() .into_deserializer() .deserialize_enum(name, variants, visitor); } expect!(self.events.next(), EventKind::StartDictionary); let ret = visitor.visit_enum(&mut *self)?; expect!(self.events.next(), EventKind::EndCollection); 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), 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<(), 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>, { de::Deserializer::deserialize_tuple(self, len, visitor) } fn struct_variant( self, fields: &'static [&'static str], visitor: V, ) -> Result where V: de::Visitor<'de>, { let name = ""; de::Deserializer::deserialize_struct(self, name, fields, 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, 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, Error> where T: de::DeserializeSeed<'de>, { if let Some(&Ok(Event::EndCollection)) = self.de.events.peek() { return Ok(None); } self.remaining = self.remaining.map(|r| r.saturating_sub(1)); self.de .with_option_mode(OptionMode::Explicit, |this| seed.deserialize(this)) .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, Error> where K: de::DeserializeSeed<'de>, { if let Some(&Ok(Event::EndCollection)) = self.de.events.peek() { return Ok(None); } self.remaining = self.remaining.map(|r| r.saturating_sub(1)); self.de .with_option_mode(OptionMode::Explicit, |this| seed.deserialize(this)) .map(Some) } fn next_value_seed(&mut self, seed: V) -> Result where V: de::DeserializeSeed<'de>, { let option_mode = if self.is_struct { OptionMode::StructField } else { OptionMode::Explicit }; self.de .with_option_mode(option_mode, |this| Ok(seed.deserialize(this)?)) } fn size_hint(&self) -> Option { self.remaining } } /// Deserializes an instance of type `T` from a byte slice. pub fn from_bytes(bytes: &[u8]) -> Result { let cursor = Cursor::new(bytes); from_reader(cursor) } /// Deserializes an instance of type `T` from a plist file of any encoding. pub fn from_file, T: de::DeserializeOwned>(path: P) -> Result { let file = File::open(path).map_err(error::from_io_without_position)?; from_reader(BufReader::new(file)) } /// Deserializes an instance of type `T` from a seekable byte stream containing a plist of any encoding. pub fn from_reader(reader: R) -> Result { let reader = stream::Reader::new(reader); let mut de = Deserializer::new(reader); de::Deserialize::deserialize(&mut de) } /// Deserializes an instance of type `T` from a byte stream containing an XML encoded plist. pub fn from_reader_xml(reader: R) -> Result { let reader = stream::XmlReader::new(reader); let mut de = Deserializer::new(reader); de::Deserialize::deserialize(&mut de) }