creator_plist/
value.rs

1use std::{
2    fs::File,
3    io::{BufReader, BufWriter, Read, Seek, Write},
4    path::Path,
5};
6
7use crate::{
8    error::{self, Error, ErrorKind, EventKind},
9    stream::{BinaryWriter, Event, IntoEvents, Reader, Writer, XmlReader, XmlWriter},
10    u64_to_usize, Date, Dictionary, Integer, Uid,
11};
12
13/// Represents any plist value.
14#[derive(Clone, Debug, PartialEq)]
15pub enum Value {
16    Array(Vec<Value>),
17    Dictionary(Dictionary),
18    Boolean(bool),
19    Data(Vec<u8>),
20    Date(Date),
21    Real(f64),
22    Integer(Integer),
23    String(String),
24    Uid(Uid),
25    #[doc(hidden)]
26    __Nonexhaustive,
27}
28
29impl Value {
30    /// Reads a `Value` from a plist file of any encoding.
31    pub fn from_file<P: AsRef<Path>>(path: P) -> Result<Value, Error> {
32        let file = File::open(path).map_err(error::from_io_without_position)?;
33        Value::from_reader(BufReader::new(file))
34    }
35
36    /// Reads a `Value` from a seekable byte stream containing a plist of any encoding.
37    pub fn from_reader<R: Read + Seek>(reader: R) -> Result<Value, Error> {
38        let reader = Reader::new(reader);
39        Value::from_events(reader)
40    }
41
42    /// Reads a `Value` from a seekable byte stream containing an XML encoded plist.
43    pub fn from_reader_xml<R: Read>(reader: R) -> Result<Value, Error> {
44        let reader = XmlReader::new(reader);
45        Value::from_events(reader)
46    }
47
48    /// Serializes a `Value` to a file as a binary encoded plist.
49    pub fn to_file_binary<P: AsRef<Path>>(&self, path: P) -> Result<(), Error> {
50        let mut file = File::create(path).map_err(error::from_io_without_position)?;
51        self.to_writer_binary(BufWriter::new(&mut file))?;
52        file.sync_all().map_err(error::from_io_without_position)?;
53        Ok(())
54    }
55
56    /// Serializes a `Value` to a file as an XML encoded plist.
57    pub fn to_file_xml<P: AsRef<Path>>(&self, path: P) -> Result<(), Error> {
58        let mut file = File::create(path).map_err(error::from_io_without_position)?;
59        self.to_writer_xml(BufWriter::new(&mut file))?;
60        file.sync_all().map_err(error::from_io_without_position)?;
61        Ok(())
62    }
63
64    /// Serializes a `Value` to a byte stream as a binary encoded plist.
65    pub fn to_writer_binary<W: Write>(&self, writer: W) -> Result<(), Error> {
66        let mut writer = BinaryWriter::new(writer);
67        self.to_writer_inner(&mut writer)
68    }
69
70    /// Serializes a `Value` to a byte stream as an XML encoded plist.
71    pub fn to_writer_xml<W: Write>(&self, writer: W) -> Result<(), Error> {
72        let mut writer = XmlWriter::new(writer);
73        self.to_writer_inner(&mut writer)
74    }
75
76    fn to_writer_inner(&self, writer: &mut dyn Writer) -> Result<(), Error> {
77        let events = self.clone().into_events();
78        for event in events {
79            writer.write(&event)?;
80        }
81        Ok(())
82    }
83
84    /// Builds a single `Value` from an `Event` iterator.
85    /// On success any excess `Event`s will remain in the iterator.
86    #[cfg(feature = "enable_unstable_features_that_may_break_with_minor_version_bumps")]
87    pub fn from_events<T>(events: T) -> Result<Value, Error>
88    where
89        T: IntoIterator<Item = Result<Event, Error>>,
90    {
91        Builder::new(events.into_iter()).build()
92    }
93
94    /// Builds a single `Value` from an `Event` iterator.
95    /// On success any excess `Event`s will remain in the iterator.
96    #[cfg(not(feature = "enable_unstable_features_that_may_break_with_minor_version_bumps"))]
97    pub(crate) fn from_events<T>(events: T) -> Result<Value, Error>
98    where
99        T: IntoIterator<Item = Result<Event, Error>>,
100    {
101        Builder::new(events.into_iter()).build()
102    }
103
104    /// Converts a `Value` into an `Event` iterator.
105    #[cfg(feature = "enable_unstable_features_that_may_break_with_minor_version_bumps")]
106    pub fn into_events(self) -> IntoEvents {
107        IntoEvents::new(self)
108    }
109
110    /// Converts a `Value` into an `Event` iterator.
111    #[cfg(not(feature = "enable_unstable_features_that_may_break_with_minor_version_bumps"))]
112    pub(crate) fn into_events(self) -> IntoEvents {
113        IntoEvents::new(self)
114    }
115
116    /// If the `Value` is a Array, returns the underlying `Vec`.
117    ///
118    /// Returns `None` otherwise.
119    ///
120    /// This method consumes the `Value`. To get a reference instead, use
121    /// `as_array`.
122    pub fn into_array(self) -> Option<Vec<Value>> {
123        match self {
124            Value::Array(dict) => Some(dict),
125            _ => None,
126        }
127    }
128
129    /// If the `Value` is an Array, returns the associated `Vec`.
130    ///
131    /// Returns `None` otherwise.
132    pub fn as_array(&self) -> Option<&Vec<Value>> {
133        match *self {
134            Value::Array(ref array) => Some(array),
135            _ => None,
136        }
137    }
138
139    /// If the `Value` is an Array, returns the associated mutable `Vec`.
140    ///
141    /// Returns `None` otherwise.
142    pub fn as_array_mut(&mut self) -> Option<&mut Vec<Value>> {
143        match *self {
144            Value::Array(ref mut array) => Some(array),
145            _ => None,
146        }
147    }
148
149    /// If the `Value` is a Dictionary, returns the associated `BTreeMap`.
150    ///
151    /// Returns `None` otherwise.
152    ///
153    /// This method consumes the `Value`. To get a reference instead, use
154    /// `as_dictionary`.
155    pub fn into_dictionary(self) -> Option<Dictionary> {
156        match self {
157            Value::Dictionary(dict) => Some(dict),
158            _ => None,
159        }
160    }
161
162    /// If the `Value` is a Dictionary, returns the associated `BTreeMap`.
163    ///
164    /// Returns `None` otherwise.
165    pub fn as_dictionary(&self) -> Option<&Dictionary> {
166        match *self {
167            Value::Dictionary(ref dict) => Some(dict),
168            _ => None,
169        }
170    }
171
172    /// If the `Value` is a Dictionary, returns the associated mutable `BTreeMap`.
173    ///
174    /// Returns `None` otherwise.
175    pub fn as_dictionary_mut(&mut self) -> Option<&mut Dictionary> {
176        match *self {
177            Value::Dictionary(ref mut dict) => Some(dict),
178            _ => None,
179        }
180    }
181
182    /// If the `Value` is a Boolean, returns the associated `bool`.
183    ///
184    /// Returns `None` otherwise.
185    pub fn as_boolean(&self) -> Option<bool> {
186        match *self {
187            Value::Boolean(v) => Some(v),
188            _ => None,
189        }
190    }
191
192    /// If the `Value` is a Data, returns the underlying `Vec`.
193    ///
194    /// Returns `None` otherwise.
195    ///
196    /// This method consumes the `Value`. If this is not desired, please use
197    /// `as_data` method.
198    pub fn into_data(self) -> Option<Vec<u8>> {
199        match self {
200            Value::Data(data) => Some(data),
201            _ => None,
202        }
203    }
204
205    /// If the `Value` is a Data, returns the associated `Vec`.
206    ///
207    /// Returns `None` otherwise.
208    pub fn as_data(&self) -> Option<&[u8]> {
209        match *self {
210            Value::Data(ref data) => Some(data),
211            _ => None,
212        }
213    }
214
215    /// If the `Value` is a Date, returns the associated `Date`.
216    ///
217    /// Returns `None` otherwise.
218    pub fn as_date(&self) -> Option<Date> {
219        match *self {
220            Value::Date(date) => Some(date),
221            _ => None,
222        }
223    }
224
225    /// If the `Value` is a Real, returns the associated `f64`.
226    ///
227    /// Returns `None` otherwise.
228    pub fn as_real(&self) -> Option<f64> {
229        match *self {
230            Value::Real(v) => Some(v),
231            _ => None,
232        }
233    }
234
235    /// If the `Value` is a signed Integer, returns the associated `i64`.
236    ///
237    /// Returns `None` otherwise.
238    pub fn as_signed_integer(&self) -> Option<i64> {
239        match *self {
240            Value::Integer(v) => v.as_signed(),
241            _ => None,
242        }
243    }
244
245    /// If the `Value` is an unsigned Integer, returns the associated `u64`.
246    ///
247    /// Returns `None` otherwise.
248    pub fn as_unsigned_integer(&self) -> Option<u64> {
249        match *self {
250            Value::Integer(v) => v.as_unsigned(),
251            _ => None,
252        }
253    }
254
255    /// If the `Value` is a String, returns the underlying `String`.
256    ///
257    /// Returns `None` otherwise.
258    ///
259    /// This method consumes the `Value`. If this is not desired, please use
260    /// `as_string` method.
261    pub fn into_string(self) -> Option<String> {
262        match self {
263            Value::String(v) => Some(v),
264            _ => None,
265        }
266    }
267
268    /// If the `Value` is a String, returns the associated `str`.
269    ///
270    /// Returns `None` otherwise.
271    pub fn as_string(&self) -> Option<&str> {
272        match *self {
273            Value::String(ref v) => Some(v),
274            _ => None,
275        }
276    }
277}
278
279impl From<Vec<Value>> for Value {
280    fn from(from: Vec<Value>) -> Value {
281        Value::Array(from)
282    }
283}
284
285impl From<Dictionary> for Value {
286    fn from(from: Dictionary) -> Value {
287        Value::Dictionary(from)
288    }
289}
290
291impl From<bool> for Value {
292    fn from(from: bool) -> Value {
293        Value::Boolean(from)
294    }
295}
296
297impl<'a> From<&'a bool> for Value {
298    fn from(from: &'a bool) -> Value {
299        Value::Boolean(*from)
300    }
301}
302
303impl From<Date> for Value {
304    fn from(from: Date) -> Value {
305        Value::Date(from)
306    }
307}
308
309impl<'a> From<&'a Date> for Value {
310    fn from(from: &'a Date) -> Value {
311        Value::Date(*from)
312    }
313}
314
315impl From<f64> for Value {
316    fn from(from: f64) -> Value {
317        Value::Real(from)
318    }
319}
320
321impl From<f32> for Value {
322    fn from(from: f32) -> Value {
323        Value::Real(from.into())
324    }
325}
326
327impl From<i64> for Value {
328    fn from(from: i64) -> Value {
329        Value::Integer(Integer::from(from))
330    }
331}
332
333impl From<i32> for Value {
334    fn from(from: i32) -> Value {
335        Value::Integer(Integer::from(from))
336    }
337}
338
339impl From<i16> for Value {
340    fn from(from: i16) -> Value {
341        Value::Integer(Integer::from(from))
342    }
343}
344
345impl From<i8> for Value {
346    fn from(from: i8) -> Value {
347        Value::Integer(Integer::from(from))
348    }
349}
350
351impl From<u64> for Value {
352    fn from(from: u64) -> Value {
353        Value::Integer(Integer::from(from))
354    }
355}
356
357impl From<u32> for Value {
358    fn from(from: u32) -> Value {
359        Value::Integer(Integer::from(from))
360    }
361}
362
363impl From<u16> for Value {
364    fn from(from: u16) -> Value {
365        Value::Integer(Integer::from(from))
366    }
367}
368
369impl From<u8> for Value {
370    fn from(from: u8) -> Value {
371        Value::Integer(Integer::from(from))
372    }
373}
374
375impl<'a> From<&'a f64> for Value {
376    fn from(from: &'a f64) -> Value {
377        Value::Real(*from)
378    }
379}
380
381impl<'a> From<&'a f32> for Value {
382    fn from(from: &'a f32) -> Value {
383        Value::Real((*from).into())
384    }
385}
386
387impl<'a> From<&'a i64> for Value {
388    fn from(from: &'a i64) -> Value {
389        Value::Integer(Integer::from(*from))
390    }
391}
392
393impl<'a> From<&'a i32> for Value {
394    fn from(from: &'a i32) -> Value {
395        Value::Integer(Integer::from(*from))
396    }
397}
398
399impl<'a> From<&'a i16> for Value {
400    fn from(from: &'a i16) -> Value {
401        Value::Integer(Integer::from(*from))
402    }
403}
404
405impl<'a> From<&'a i8> for Value {
406    fn from(from: &'a i8) -> Value {
407        Value::Integer(Integer::from(*from))
408    }
409}
410
411impl<'a> From<&'a u64> for Value {
412    fn from(from: &'a u64) -> Value {
413        Value::Integer(Integer::from(*from))
414    }
415}
416
417impl<'a> From<&'a u32> for Value {
418    fn from(from: &'a u32) -> Value {
419        Value::Integer(Integer::from(*from))
420    }
421}
422
423impl<'a> From<&'a u16> for Value {
424    fn from(from: &'a u16) -> Value {
425        Value::Integer((*from).into())
426    }
427}
428
429impl<'a> From<&'a u8> for Value {
430    fn from(from: &'a u8) -> Value {
431        Value::Integer((*from).into())
432    }
433}
434
435impl From<String> for Value {
436    fn from(from: String) -> Value {
437        Value::String(from)
438    }
439}
440
441impl<'a> From<&'a str> for Value {
442    fn from(from: &'a str) -> Value {
443        Value::String(from.into())
444    }
445}
446
447struct Builder<T> {
448    stream: T,
449    token: Option<Event>,
450}
451
452impl<T: Iterator<Item = Result<Event, Error>>> Builder<T> {
453    fn new(stream: T) -> Builder<T> {
454        Builder {
455            stream,
456            token: None,
457        }
458    }
459
460    fn build(mut self) -> Result<Value, Error> {
461        self.bump()?;
462        self.build_value()
463    }
464
465    fn bump(&mut self) -> Result<(), Error> {
466        self.token = match self.stream.next() {
467            Some(Ok(token)) => Some(token),
468            Some(Err(err)) => return Err(err),
469            None => None,
470        };
471        Ok(())
472    }
473
474    fn build_value(&mut self) -> Result<Value, Error> {
475        match self.token.take() {
476            Some(Event::StartArray(len)) => Ok(Value::Array(self.build_array(len)?)),
477            Some(Event::StartDictionary(len)) => Ok(Value::Dictionary(self.build_dict(len)?)),
478
479            Some(Event::Boolean(b)) => Ok(Value::Boolean(b)),
480            Some(Event::Data(d)) => Ok(Value::Data(d)),
481            Some(Event::Date(d)) => Ok(Value::Date(d)),
482            Some(Event::Integer(i)) => Ok(Value::Integer(i)),
483            Some(Event::Real(f)) => Ok(Value::Real(f)),
484            Some(Event::String(s)) => Ok(Value::String(s)),
485            Some(Event::Uid(u)) => Ok(Value::Uid(u)),
486
487            Some(event @ Event::EndCollection) => Err(error::unexpected_event_type(
488                EventKind::ValueOrStartCollection,
489                &event,
490            )),
491
492            Some(Event::__Nonexhaustive) => unreachable!(),
493
494            None => Err(ErrorKind::UnexpectedEndOfEventStream.without_position()),
495        }
496    }
497
498    fn build_array(&mut self, len: Option<u64>) -> Result<Vec<Value>, Error> {
499        let mut values = match len.and_then(u64_to_usize) {
500            Some(len) => Vec::with_capacity(len),
501            None => Vec::new(),
502        };
503
504        loop {
505            self.bump()?;
506            if let Some(Event::EndCollection) = self.token {
507                self.token.take();
508                return Ok(values);
509            }
510            values.push(self.build_value()?);
511        }
512    }
513
514    fn build_dict(&mut self, _len: Option<u64>) -> Result<Dictionary, Error> {
515        let mut dict = Dictionary::new();
516
517        loop {
518            self.bump()?;
519            match self.token.take() {
520                Some(Event::EndCollection) => return Ok(dict),
521                Some(Event::String(s)) => {
522                    self.bump()?;
523                    dict.insert(s, self.build_value()?);
524                }
525                Some(event) => {
526                    return Err(error::unexpected_event_type(
527                        EventKind::DictionaryKeyOrEndCollection,
528                        &event,
529                    ))
530                }
531                None => return Err(ErrorKind::UnexpectedEndOfEventStream.without_position()),
532            }
533        }
534    }
535}
536
537#[cfg(test)]
538mod tests {
539    use std::time::SystemTime;
540
541    use super::*;
542    use crate::{stream::Event::*, Date, Dictionary, Value};
543
544    #[test]
545    fn value_accessors() {
546        let vec = vec![Value::Real(0.0)];
547        let mut array = Value::Array(vec.clone());
548        assert_eq!(array.as_array(), Some(&vec.clone()));
549        assert_eq!(array.as_array_mut(), Some(&mut vec.clone()));
550
551        let mut map = Dictionary::new();
552        map.insert("key1".to_owned(), Value::String("value1".to_owned()));
553        let mut dict = Value::Dictionary(map.clone());
554        assert_eq!(dict.as_dictionary(), Some(&map.clone()));
555        assert_eq!(dict.as_dictionary_mut(), Some(&mut map.clone()));
556
557        assert_eq!(Value::Boolean(true).as_boolean(), Some(true));
558
559        let slice: &[u8] = &[1, 2, 3];
560        assert_eq!(Value::Data(slice.to_vec()).as_data(), Some(slice));
561        assert_eq!(
562            Value::Data(slice.to_vec()).into_data(),
563            Some(slice.to_vec())
564        );
565
566        let date: Date = SystemTime::now().into();
567        assert_eq!(Value::Date(date.clone()).as_date(), Some(date));
568
569        assert_eq!(Value::Real(0.0).as_real(), Some(0.0));
570        assert_eq!(Value::Integer(1.into()).as_signed_integer(), Some(1));
571        assert_eq!(Value::Integer(1.into()).as_unsigned_integer(), Some(1));
572        assert_eq!(Value::Integer((-1).into()).as_unsigned_integer(), None);
573        assert_eq!(
574            Value::Integer((i64::max_value() as u64 + 1).into()).as_signed_integer(),
575            None
576        );
577        assert_eq!(Value::String("2".to_owned()).as_string(), Some("2"));
578        assert_eq!(
579            Value::String("t".to_owned()).into_string(),
580            Some("t".to_owned())
581        );
582    }
583
584    #[test]
585    fn builder() {
586        // Input
587        let events = vec![
588            StartDictionary(None),
589            String("Author".to_owned()),
590            String("William Shakespeare".to_owned()),
591            String("Lines".to_owned()),
592            StartArray(None),
593            String("It is a tale told by an idiot,".to_owned()),
594            String("Full of sound and fury, signifying nothing.".to_owned()),
595            EndCollection,
596            String("Birthdate".to_owned()),
597            Integer(1564.into()),
598            String("Height".to_owned()),
599            Real(1.60),
600            EndCollection,
601        ];
602
603        let builder = Builder::new(events.into_iter().map(|e| Ok(e)));
604        let plist = builder.build();
605
606        // Expected output
607        let mut lines = Vec::new();
608        lines.push(Value::String("It is a tale told by an idiot,".to_owned()));
609        lines.push(Value::String(
610            "Full of sound and fury, signifying nothing.".to_owned(),
611        ));
612
613        let mut dict = Dictionary::new();
614        dict.insert(
615            "Author".to_owned(),
616            Value::String("William Shakespeare".to_owned()),
617        );
618        dict.insert("Lines".to_owned(), Value::Array(lines));
619        dict.insert("Birthdate".to_owned(), Value::Integer(1564.into()));
620        dict.insert("Height".to_owned(), Value::Real(1.60));
621
622        assert_eq!(plist.unwrap(), Value::Dictionary(dict));
623    }
624}