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