summaryrefslogtreecommitdiffstats
path: root/third_party/rust/plist/src/de.rs
diff options
context:
space:
mode:
Diffstat (limited to 'third_party/rust/plist/src/de.rs')
-rw-r--r--third_party/rust/plist/src/de.rs427
1 files changed, 427 insertions, 0 deletions
diff --git a/third_party/rust/plist/src/de.rs b/third_party/rust/plist/src/de.rs
new file mode 100644
index 0000000000..12bdb06fa3
--- /dev/null
+++ b/third_party/rust/plist/src/de.rs
@@ -0,0 +1,427 @@
+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<T: Display>(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<I>
+where
+ I: IntoIterator<Item = Result<OwnedEvent, Error>>,
+{
+ events: Peekable<<I as IntoIterator>::IntoIter>,
+ option_mode: OptionMode,
+ in_plist_value: bool,
+}
+
+impl<I> Deserializer<I>
+where
+ I: IntoIterator<Item = Result<OwnedEvent, Error>>,
+{
+ pub fn new(iter: I) -> Deserializer<I> {
+ Deserializer {
+ events: iter.into_iter().peekable(),
+ option_mode: OptionMode::Root,
+ in_plist_value: false,
+ }
+ }
+
+ fn with_option_mode<T, F: FnOnce(&mut Deserializer<I>) -> Result<T, Error>>(
+ &mut self,
+ option_mode: OptionMode,
+ f: F,
+ ) -> Result<T, Error> {
+ 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<T, F: FnOnce(&mut Deserializer<I>) -> Result<T, Error>>(
+ &mut self,
+ f: F,
+ ) -> Result<T, Error> {
+ 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<I>
+where
+ I: IntoIterator<Item = Result<OwnedEvent, Error>>,
+{
+ type Error = Error;
+
+ fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
+ 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<V>(self, visitor: V) -> Result<V::Value, Error>
+ where
+ V: de::Visitor<'de>,
+ {
+ expect!(self.events.next(), EventKind::String);
+ visitor.visit_unit()
+ }
+
+ fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error>
+ where
+ V: de::Visitor<'de>,
+ {
+ match self.option_mode {
+ OptionMode::Root => {
+ if self.events.peek().is_none() {
+ visitor.visit_none::<Error>()
+ } 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::<Error>()?
+ }
+ 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<V>(
+ self,
+ name: &'static str,
+ visitor: V,
+ ) -> Result<V::Value, Error>
+ 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<V>(
+ self,
+ _name: &'static str,
+ _fields: &'static [&'static str],
+ visitor: V,
+ ) -> Result<V::Value, Error>
+ 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<V>(
+ self,
+ name: &'static str,
+ variants: &'static [&'static str],
+ visitor: V,
+ ) -> Result<V::Value, Error>
+ 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<I>
+where
+ I: IntoIterator<Item = Result<OwnedEvent, Error>>,
+{
+ type Error = Error;
+ type Variant = Self;
+
+ fn variant_seed<V>(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<I>
+where
+ I: IntoIterator<Item = Result<OwnedEvent, Error>>,
+{
+ type Error = Error;
+
+ fn unit_variant(self) -> Result<(), Error> {
+ <() as de::Deserialize>::deserialize(self)
+ }
+
+ fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, Error>
+ where
+ T: de::DeserializeSeed<'de>,
+ {
+ seed.deserialize(self)
+ }
+
+ fn tuple_variant<V>(self, len: usize, visitor: V) -> Result<V::Value, Error>
+ where
+ V: de::Visitor<'de>,
+ {
+ de::Deserializer::deserialize_tuple(self, len, visitor)
+ }
+
+ fn struct_variant<V>(
+ self,
+ fields: &'static [&'static str],
+ visitor: V,
+ ) -> Result<V::Value, Error>
+ where
+ V: de::Visitor<'de>,
+ {
+ let name = "";
+ de::Deserializer::deserialize_struct(self, name, fields, visitor)
+ }
+}
+
+struct MapAndSeqAccess<'a, I>
+where
+ I: 'a + IntoIterator<Item = Result<OwnedEvent, Error>>,
+{
+ de: &'a mut Deserializer<I>,
+ is_struct: bool,
+ remaining: Option<usize>,
+}
+
+impl<'a, I> MapAndSeqAccess<'a, I>
+where
+ I: 'a + IntoIterator<Item = Result<OwnedEvent, Error>>,
+{
+ fn new(
+ de: &'a mut Deserializer<I>,
+ is_struct: bool,
+ len: Option<usize>,
+ ) -> MapAndSeqAccess<'a, I> {
+ MapAndSeqAccess {
+ de,
+ is_struct,
+ remaining: len,
+ }
+ }
+}
+
+impl<'de, 'a, I> de::SeqAccess<'de> for MapAndSeqAccess<'a, I>
+where
+ I: 'a + IntoIterator<Item = Result<OwnedEvent, Error>>,
+{
+ type Error = Error;
+
+ fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, 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<usize> {
+ self.remaining
+ }
+}
+
+impl<'de, 'a, I> de::MapAccess<'de> for MapAndSeqAccess<'a, I>
+where
+ I: 'a + IntoIterator<Item = Result<OwnedEvent, Error>>,
+{
+ type Error = Error;
+
+ fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, 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<V>(&mut self, seed: V) -> Result<V::Value, Error>
+ 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<usize> {
+ self.remaining
+ }
+}
+
+/// Deserializes an instance of type `T` from a byte slice.
+pub fn from_bytes<T: de::DeserializeOwned>(bytes: &[u8]) -> Result<T, Error> {
+ 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<P: AsRef<Path>, T: de::DeserializeOwned>(path: P) -> Result<T, Error> {
+ 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<R: Read + Seek, T: de::DeserializeOwned>(reader: R) -> Result<T, Error> {
+ 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<R: Read, T: de::DeserializeOwned>(reader: R) -> Result<T, Error> {
+ let reader = stream::XmlReader::new(reader);
+ let mut de = Deserializer::new(reader);
+ de::Deserialize::deserialize(&mut de)
+}