Skip to main content

plist/
de.rs

1use serde::de::{
2    self, IntoDeserializer,
3    value::{MapAccessDeserializer, MapDeserializer},
4};
5use std::{
6    borrow::Cow,
7    fmt::Display,
8    fs::File,
9    io::{BufReader, Cursor, Read, Seek},
10    iter::Peekable,
11    mem,
12    path::Path,
13};
14
15use crate::{
16    Value,
17    date::serde_impls::DATE_NEWTYPE_STRUCT_NAME,
18    error::{self, Error, ErrorKind, EventKind},
19    stream::{self, Event},
20    u64_to_usize,
21    uid::serde_impls::UID_NEWTYPE_STRUCT_NAME,
22    value::serde_impls::VALUE_NEWTYPE_STRUCT_NAME,
23};
24
25macro_rules! expect {
26    ($next:expr, $kind:expr) => {
27        match $next {
28            Some(Ok(ref event)) if EventKind::of_event(event) != $kind => {
29                return Err(error::unexpected_event_type($kind, event))?;
30            }
31            Some(Ok(event)) => event,
32            Some(Err(err)) => return Err(err),
33            None => return Err(ErrorKind::UnexpectedEndOfEventStream.without_position()),
34        }
35    };
36}
37
38macro_rules! try_next {
39    ($next:expr) => {
40        match $next {
41            Some(Ok(event)) => event,
42            Some(Err(err)) => return Err(err)?,
43            None => return Err(ErrorKind::UnexpectedEndOfEventStream.without_position())?,
44        }
45    };
46}
47
48#[doc(hidden)]
49impl de::Error for Error {
50    fn custom<T: Display>(msg: T) -> Self {
51        ErrorKind::Serde(msg.to_string()).without_position()
52    }
53}
54
55enum OptionMode {
56    Root,
57    StructField,
58    Explicit,
59}
60
61/// A structure that deserializes plist event streams into Rust values.
62pub struct Deserializer<'event, I>
63where
64    I: IntoIterator<Item = Result<Event<'event>, Error>>,
65{
66    events: Peekable<<I as IntoIterator>::IntoIter>,
67    option_mode: OptionMode,
68    in_plist_value: bool,
69}
70
71impl<'event, I> Deserializer<'event, I>
72where
73    I: IntoIterator<Item = Result<Event<'event>, Error>>,
74{
75    pub fn new(iter: I) -> Deserializer<'event, I> {
76        Deserializer {
77            events: iter.into_iter().peekable(),
78            option_mode: OptionMode::Root,
79            in_plist_value: false,
80        }
81    }
82
83    fn with_option_mode<T, F: FnOnce(&mut Deserializer<'event, I>) -> Result<T, Error>>(
84        &mut self,
85        option_mode: OptionMode,
86        f: F,
87    ) -> Result<T, Error> {
88        let prev_option_mode = mem::replace(&mut self.option_mode, option_mode);
89        let ret = f(&mut *self);
90        self.option_mode = prev_option_mode;
91        ret
92    }
93
94    fn enter_plist_value<T, F: FnOnce(&mut Deserializer<'event, I>) -> Result<T, Error>>(
95        &mut self,
96        f: F,
97    ) -> Result<T, Error> {
98        let prev = mem::replace(&mut self.in_plist_value, true);
99        let ret = f(&mut *self);
100        self.in_plist_value = prev;
101        ret
102    }
103}
104
105impl<'de, 'event, I> de::Deserializer<'de> for &mut Deserializer<'event, I>
106where
107    I: IntoIterator<Item = Result<Event<'event>, Error>>,
108{
109    type Error = Error;
110
111    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Error>
112    where
113        V: de::Visitor<'de>,
114    {
115        match try_next!(self.events.next()) {
116            Event::StartArray(len) => {
117                let len = len.and_then(u64_to_usize);
118                let ret = visitor.visit_seq(MapAndSeqAccess::new(self, false, len))?;
119                expect!(self.events.next(), EventKind::EndCollection);
120                Ok(ret)
121            }
122            Event::StartDictionary(len) => {
123                let len = len.and_then(u64_to_usize);
124                let ret = visitor.visit_map(MapAndSeqAccess::new(self, false, len))?;
125                expect!(self.events.next(), EventKind::EndCollection);
126                Ok(ret)
127            }
128            event @ Event::EndCollection => Err(error::unexpected_event_type(
129                EventKind::ValueOrStartCollection,
130                &event,
131            )),
132
133            Event::Boolean(v) => visitor.visit_bool(v),
134            Event::Data(Cow::Borrowed(v)) => visitor.visit_bytes(v),
135            Event::Data(Cow::Owned(v)) => visitor.visit_byte_buf(v),
136            Event::Date(v) if self.in_plist_value => {
137                visitor.visit_enum(MapAccessDeserializer::new(MapDeserializer::new(
138                    [(DATE_NEWTYPE_STRUCT_NAME, v.to_xml_format())].into_iter(),
139                )))
140            }
141            Event::Date(v) => visitor.visit_string(v.to_xml_format()),
142            Event::Integer(v) => {
143                if let Some(v) = v.as_unsigned() {
144                    visitor.visit_u64(v)
145                } else if let Some(v) = v.as_signed() {
146                    visitor.visit_i64(v)
147                } else {
148                    unreachable!()
149                }
150            }
151            Event::Real(v) => visitor.visit_f64(v),
152            Event::String(Cow::Borrowed(v)) => visitor.visit_str(v),
153            Event::String(Cow::Owned(v)) => visitor.visit_string(v),
154            Event::Uid(v) if self.in_plist_value => visitor.visit_enum(MapAccessDeserializer::new(
155                MapDeserializer::new([(UID_NEWTYPE_STRUCT_NAME, v.get())].into_iter()),
156            )),
157            Event::Uid(v) => visitor.visit_u64(v.get()),
158        }
159    }
160
161    forward_to_deserialize_any! {
162        bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string
163        seq bytes byte_buf map unit_struct
164        tuple_struct tuple ignored_any identifier
165    }
166
167    fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Error>
168    where
169        V: de::Visitor<'de>,
170    {
171        expect!(self.events.next(), EventKind::String);
172        visitor.visit_unit()
173    }
174
175    fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error>
176    where
177        V: de::Visitor<'de>,
178    {
179        match self.option_mode {
180            OptionMode::Root => {
181                if self.events.peek().is_none() {
182                    visitor.visit_none::<Error>()
183                } else {
184                    self.with_option_mode(OptionMode::Explicit, |this| visitor.visit_some(this))
185                }
186            }
187            OptionMode::StructField => {
188                // None struct values are ignored so if we're here the value must be Some.
189                self.with_option_mode(OptionMode::Explicit, |this| visitor.visit_some(this))
190            }
191            OptionMode::Explicit => {
192                expect!(self.events.next(), EventKind::StartDictionary);
193
194                let ret = match try_next!(self.events.next()) {
195                    Event::String(ref s) if &s[..] == "None" => {
196                        expect!(self.events.next(), EventKind::String);
197                        visitor.visit_none::<Error>()?
198                    }
199                    Event::String(ref s) if &s[..] == "Some" => visitor.visit_some(&mut *self)?,
200                    event => return Err(error::unexpected_event_type(EventKind::String, &event))?,
201                };
202
203                expect!(self.events.next(), EventKind::EndCollection);
204
205                Ok(ret)
206            }
207        }
208    }
209
210    fn deserialize_newtype_struct<V>(
211        self,
212        name: &'static str,
213        visitor: V,
214    ) -> Result<V::Value, Error>
215    where
216        V: de::Visitor<'de>,
217    {
218        if name == VALUE_NEWTYPE_STRUCT_NAME {
219            self.enter_plist_value(|this| visitor.visit_newtype_struct(this))
220        } else {
221            visitor.visit_newtype_struct(self)
222        }
223    }
224
225    fn deserialize_struct<V>(
226        self,
227        _name: &'static str,
228        _fields: &'static [&'static str],
229        visitor: V,
230    ) -> Result<V::Value, Error>
231    where
232        V: de::Visitor<'de>,
233    {
234        expect!(self.events.next(), EventKind::StartDictionary);
235        let ret = visitor.visit_map(MapAndSeqAccess::new(self, true, None))?;
236        expect!(self.events.next(), EventKind::EndCollection);
237        Ok(ret)
238    }
239
240    fn deserialize_enum<V>(
241        self,
242        name: &'static str,
243        variants: &'static [&'static str],
244        visitor: V,
245    ) -> Result<V::Value, Error>
246    where
247        V: de::Visitor<'de>,
248    {
249        let event = self.events.next();
250
251        // `plist` since v1.1 serialises unit enum variants as plain strings.
252        if let Some(Ok(Event::String(s))) = event {
253            return match s {
254                Cow::Borrowed(s) => s
255                    .into_deserializer()
256                    .deserialize_enum(name, variants, visitor),
257                Cow::Owned(s) => s
258                    .into_deserializer()
259                    .deserialize_enum(name, variants, visitor),
260            };
261        }
262
263        expect!(event, EventKind::StartDictionary);
264        let ret = visitor.visit_enum(&mut *self)?;
265        expect!(self.events.next(), EventKind::EndCollection);
266        Ok(ret)
267    }
268}
269
270impl<'de, 'event, I> de::EnumAccess<'de> for &mut Deserializer<'event, I>
271where
272    I: IntoIterator<Item = Result<Event<'event>, Error>>,
273{
274    type Error = Error;
275    type Variant = Self;
276
277    fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self), Error>
278    where
279        V: de::DeserializeSeed<'de>,
280    {
281        Ok((seed.deserialize(&mut *self)?, self))
282    }
283}
284
285impl<'de, 'event, I> de::VariantAccess<'de> for &mut Deserializer<'event, I>
286where
287    I: IntoIterator<Item = Result<Event<'event>, Error>>,
288{
289    type Error = Error;
290
291    fn unit_variant(self) -> Result<(), Error> {
292        <() as de::Deserialize>::deserialize(self)
293    }
294
295    fn newtype_variant_seed<T>(self, seed: T) -> Result<T::Value, Error>
296    where
297        T: de::DeserializeSeed<'de>,
298    {
299        seed.deserialize(self)
300    }
301
302    fn tuple_variant<V>(self, len: usize, visitor: V) -> Result<V::Value, Error>
303    where
304        V: de::Visitor<'de>,
305    {
306        de::Deserializer::deserialize_tuple(self, len, visitor)
307    }
308
309    fn struct_variant<V>(
310        self,
311        fields: &'static [&'static str],
312        visitor: V,
313    ) -> Result<V::Value, Error>
314    where
315        V: de::Visitor<'de>,
316    {
317        let name = "";
318        de::Deserializer::deserialize_struct(self, name, fields, visitor)
319    }
320}
321
322struct MapAndSeqAccess<'a, 'event, I>
323where
324    I: 'a + IntoIterator<Item = Result<Event<'event>, Error>>,
325{
326    de: &'a mut Deserializer<'event, I>,
327    is_struct: bool,
328    remaining: Option<usize>,
329}
330
331impl<'a, 'event, I> MapAndSeqAccess<'a, 'event, I>
332where
333    I: 'a + IntoIterator<Item = Result<Event<'event>, Error>>,
334{
335    fn new(
336        de: &'a mut Deserializer<'event, I>,
337        is_struct: bool,
338        len: Option<usize>,
339    ) -> MapAndSeqAccess<'a, 'event, I> {
340        MapAndSeqAccess {
341            de,
342            is_struct,
343            remaining: len,
344        }
345    }
346}
347
348impl<'de, 'a, 'event, I> de::SeqAccess<'de> for MapAndSeqAccess<'a, 'event, I>
349where
350    I: 'a + IntoIterator<Item = Result<Event<'event>, Error>>,
351{
352    type Error = Error;
353
354    fn next_element_seed<T>(&mut self, seed: T) -> Result<Option<T::Value>, Error>
355    where
356        T: de::DeserializeSeed<'de>,
357    {
358        if let Some(&Ok(Event::EndCollection)) = self.de.events.peek() {
359            return Ok(None);
360        }
361
362        self.remaining = self.remaining.map(|r| r.saturating_sub(1));
363        self.de
364            .with_option_mode(OptionMode::Explicit, |this| seed.deserialize(this))
365            .map(Some)
366    }
367
368    fn size_hint(&self) -> Option<usize> {
369        self.remaining
370    }
371}
372
373impl<'de, 'a, 'event, I> de::MapAccess<'de> for MapAndSeqAccess<'a, 'event, I>
374where
375    I: 'a + IntoIterator<Item = Result<Event<'event>, Error>>,
376{
377    type Error = Error;
378
379    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>, Error>
380    where
381        K: de::DeserializeSeed<'de>,
382    {
383        if let Some(&Ok(Event::EndCollection)) = self.de.events.peek() {
384            return Ok(None);
385        }
386
387        self.remaining = self.remaining.map(|r| r.saturating_sub(1));
388        self.de
389            .with_option_mode(OptionMode::Explicit, |this| seed.deserialize(this))
390            .map(Some)
391    }
392
393    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Error>
394    where
395        V: de::DeserializeSeed<'de>,
396    {
397        let option_mode = if self.is_struct {
398            OptionMode::StructField
399        } else {
400            OptionMode::Explicit
401        };
402        self.de
403            .with_option_mode(option_mode, |this| seed.deserialize(this))
404    }
405
406    fn size_hint(&self) -> Option<usize> {
407        self.remaining
408    }
409}
410
411/// Deserializes an instance of type `T` from a byte slice.
412pub fn from_bytes<T: de::DeserializeOwned>(bytes: &[u8]) -> Result<T, Error> {
413    let cursor = Cursor::new(bytes);
414    from_reader(cursor)
415}
416
417/// Deserializes an instance of type `T` from a plist file of any encoding.
418pub fn from_file<P: AsRef<Path>, T: de::DeserializeOwned>(path: P) -> Result<T, Error> {
419    let file = File::open(path).map_err(error::from_io_without_position)?;
420    from_reader(BufReader::new(file))
421}
422
423/// Deserializes an instance of type `T` from a seekable byte stream containing a plist of any encoding.
424pub fn from_reader<R: Read + Seek, T: de::DeserializeOwned>(reader: R) -> Result<T, Error> {
425    let reader = stream::Reader::new(reader);
426    from_stream(reader)
427}
428
429/// Deserializes an instance of type `T` from a byte stream containing an ASCII encoded plist.
430pub fn from_reader_ascii<R: Read, T: de::DeserializeOwned>(reader: R) -> Result<T, Error> {
431    let reader = stream::AsciiReader::new(reader);
432    from_stream(reader)
433}
434
435/// Deserializes an instance of type `T` from a byte stream containing an XML encoded plist.
436pub fn from_reader_xml<R: Read, T: de::DeserializeOwned>(reader: R) -> Result<T, Error> {
437    let reader = stream::XmlReader::new(BufReader::new(reader));
438    from_stream(reader)
439}
440
441/// Interprets a [`Value`] as an instance of type `T`.
442pub fn from_value<T: de::DeserializeOwned>(value: &Value) -> Result<T, Error> {
443    let events = value.events().map(Ok);
444    from_stream(events)
445}
446
447pub(crate) fn from_stream<'event, T: de::DeserializeOwned>(
448    stream: impl IntoIterator<Item = Result<Event<'event>, Error>>,
449) -> Result<T, Error> {
450    let mut de = Deserializer::new(stream);
451    let value = de::Deserialize::deserialize(&mut de)?;
452
453    // TODO: Ideally this check would be inside the `Deserializer` implementation.
454    if let Some(event) = de.events.next().transpose()? {
455        return Err(ErrorKind::ExpectedEndOfEventStream {
456            found: EventKind::of_event(&event),
457        }
458        .without_position());
459    }
460
461    Ok(value)
462}