1 //! An abstraction of a plist file as a stream of events. Used to support multiple encodings.
2 
3 mod binary_reader;
4 pub use self::binary_reader::BinaryReader;
5 
6 mod binary_writer;
7 pub use self::binary_writer::BinaryWriter;
8 
9 mod xml_reader;
10 pub use self::xml_reader::XmlReader;
11 
12 mod xml_writer;
13 pub use self::xml_writer::XmlWriter;
14 
15 use std::{
16     borrow::Cow,
17     io::{self, Read, Seek, SeekFrom},
18     vec,
19 };
20 
21 use crate::{
22     dictionary,
23     error::{Error, ErrorKind},
24     Date, Integer, Uid, Value,
25 };
26 
27 /// An encoding of a plist as a flat structure.
28 ///
29 /// Output by the event readers.
30 ///
31 /// Dictionary keys and values are represented as pairs of values e.g.:
32 ///
33 /// ```ignore rust
34 /// StartDictionary
35 /// String("Height") // Key
36 /// Real(181.2)      // Value
37 /// String("Age")    // Key
38 /// Integer(28)      // Value
39 /// EndDictionary
40 /// ```
41 ///
42 /// ## Lifetimes
43 ///
44 /// This type has a lifetime parameter; during serialization, data is borrowed
45 /// from a [`Value`], and the lifetime of the event is the lifetime of the
46 /// [`Value`] being serialized.
47 ///
48 /// During deserialization, data is always copied anyway, and this lifetime
49 /// is always `'static`.
50 #[derive(Clone, Debug, PartialEq)]
51 #[non_exhaustive]
52 pub enum Event<'a> {
53     // While the length of an array or dict cannot be feasably greater than max(usize) this better
54     // conveys the concept of an effectively unbounded event stream.
55     StartArray(Option<u64>),
56     StartDictionary(Option<u64>),
57     EndCollection,
58 
59     Boolean(bool),
60     Data(Cow<'a, [u8]>),
61     Date(Date),
62     Integer(Integer),
63     Real(f64),
64     String(Cow<'a, str>),
65     Uid(Uid),
66 }
67 
68 /// An owned [`Event`].
69 ///
70 /// During deserialization, events are always owned; this type alias helps
71 /// keep that code a bit clearer.
72 pub type OwnedEvent = Event<'static>;
73 
74 /// An `Event` stream returned by `Value::into_events`.
75 pub struct Events<'a> {
76     stack: Vec<StackItem<'a>>,
77 }
78 
79 enum StackItem<'a> {
80     Root(&'a Value),
81     Array(std::slice::Iter<'a, Value>),
82     Dict(dictionary::Iter<'a>),
83     DictValue(&'a Value),
84 }
85 
86 /// Options for customizing serialization of XML plists.
87 #[derive(Clone, Debug)]
88 pub struct XmlWriteOptions {
89     indent_str: Cow<'static, str>,
90 }
91 
92 impl XmlWriteOptions {
93     /// Specify the sequence of characters used for indentation.
94     ///
95     /// This may be either an `&'static str` or an owned `String`.
96     ///
97     /// The default is `\t`.
indent_string(mut self, indent_str: impl Into<Cow<'static, str>>) -> Self98     pub fn indent_string(mut self, indent_str: impl Into<Cow<'static, str>>) -> Self {
99         self.indent_str = indent_str.into();
100         self
101     }
102 }
103 
104 impl Default for XmlWriteOptions {
default() -> Self105     fn default() -> Self {
106         XmlWriteOptions {
107             indent_str: Cow::Borrowed("\t"),
108         }
109     }
110 }
111 
112 impl<'a> Events<'a> {
new(value: &'a Value) -> Events<'a>113     pub(crate) fn new(value: &'a Value) -> Events<'a> {
114         Events {
115             stack: vec![StackItem::Root(value)],
116         }
117     }
118 }
119 
120 impl<'a> Iterator for Events<'a> {
121     type Item = Event<'a>;
122 
next(&mut self) -> Option<Event<'a>>123     fn next(&mut self) -> Option<Event<'a>> {
124         fn handle_value<'c, 'b: 'c>(
125             value: &'b Value,
126             stack: &'c mut Vec<StackItem<'b>>,
127         ) -> Event<'b> {
128             match value {
129                 Value::Array(array) => {
130                     let len = array.len();
131                     let iter = array.iter();
132                     stack.push(StackItem::Array(iter));
133                     Event::StartArray(Some(len as u64))
134                 }
135                 Value::Dictionary(dict) => {
136                     let len = dict.len();
137                     let iter = dict.into_iter();
138                     stack.push(StackItem::Dict(iter));
139                     Event::StartDictionary(Some(len as u64))
140                 }
141                 Value::Boolean(value) => Event::Boolean(*value),
142                 Value::Data(value) => Event::Data(Cow::Borrowed(&value)),
143                 Value::Date(value) => Event::Date(*value),
144                 Value::Real(value) => Event::Real(*value),
145                 Value::Integer(value) => Event::Integer(*value),
146                 Value::String(value) => Event::String(Cow::Borrowed(value.as_str())),
147                 Value::Uid(value) => Event::Uid(*value),
148             }
149         }
150 
151         Some(match self.stack.pop()? {
152             StackItem::Root(value) => handle_value(value, &mut self.stack),
153             StackItem::Array(mut array) => {
154                 if let Some(value) = array.next() {
155                     // There might still be more items in the array so return it to the stack.
156                     self.stack.push(StackItem::Array(array));
157                     handle_value(value, &mut self.stack)
158                 } else {
159                     Event::EndCollection
160                 }
161             }
162             StackItem::Dict(mut dict) => {
163                 if let Some((key, value)) = dict.next() {
164                     // There might still be more items in the dictionary so return it to the stack.
165                     self.stack.push(StackItem::Dict(dict));
166                     // The next event to be returned must be the dictionary value.
167                     self.stack.push(StackItem::DictValue(value));
168                     // Return the key event now.
169                     Event::String(Cow::Borrowed(key))
170                 } else {
171                     Event::EndCollection
172                 }
173             }
174             StackItem::DictValue(value) => handle_value(value, &mut self.stack),
175         })
176     }
177 }
178 
179 pub struct Reader<R: Read + Seek>(ReaderInner<R>);
180 
181 enum ReaderInner<R: Read + Seek> {
182     Uninitialized(Option<R>),
183     Xml(XmlReader<R>),
184     Binary(BinaryReader<R>),
185 }
186 
187 impl<R: Read + Seek> Reader<R> {
new(reader: R) -> Reader<R>188     pub fn new(reader: R) -> Reader<R> {
189         Reader(ReaderInner::Uninitialized(Some(reader)))
190     }
191 
is_binary(reader: &mut R) -> Result<bool, Error>192     fn is_binary(reader: &mut R) -> Result<bool, Error> {
193         fn from_io_offset_0(err: io::Error) -> Error {
194             ErrorKind::Io(err).with_byte_offset(0)
195         }
196 
197         reader.seek(SeekFrom::Start(0)).map_err(from_io_offset_0)?;
198         let mut magic = [0; 8];
199         reader.read_exact(&mut magic).map_err(from_io_offset_0)?;
200         reader.seek(SeekFrom::Start(0)).map_err(from_io_offset_0)?;
201 
202         Ok(&magic == b"bplist00")
203     }
204 }
205 
206 impl<R: Read + Seek> Iterator for Reader<R> {
207     type Item = Result<OwnedEvent, Error>;
208 
next(&mut self) -> Option<Result<OwnedEvent, Error>>209     fn next(&mut self) -> Option<Result<OwnedEvent, Error>> {
210         let mut reader = match self.0 {
211             ReaderInner::Xml(ref mut parser) => return parser.next(),
212             ReaderInner::Binary(ref mut parser) => return parser.next(),
213             ReaderInner::Uninitialized(ref mut reader) => reader.take().unwrap(),
214         };
215 
216         match Reader::is_binary(&mut reader) {
217             Ok(true) => self.0 = ReaderInner::Binary(BinaryReader::new(reader)),
218             Ok(false) => self.0 = ReaderInner::Xml(XmlReader::new(reader)),
219             Err(err) => {
220                 self.0 = ReaderInner::Uninitialized(Some(reader));
221                 return Some(Err(err));
222             }
223         }
224 
225         self.next()
226     }
227 }
228 
229 /// Supports writing event streams in different plist encodings.
230 pub trait Writer: private::Sealed {
write(&mut self, event: &Event) -> Result<(), Error>231     fn write(&mut self, event: &Event) -> Result<(), Error> {
232         match event {
233             Event::StartArray(len) => self.write_start_array(*len),
234             Event::StartDictionary(len) => self.write_start_dictionary(*len),
235             Event::EndCollection => self.write_end_collection(),
236             Event::Boolean(value) => self.write_boolean(*value),
237             Event::Data(value) => self.write_data(value),
238             Event::Date(value) => self.write_date(*value),
239             Event::Integer(value) => self.write_integer(*value),
240             Event::Real(value) => self.write_real(*value),
241             Event::String(value) => self.write_string(value),
242             Event::Uid(value) => self.write_uid(*value),
243         }
244     }
245 
write_start_array(&mut self, len: Option<u64>) -> Result<(), Error>246     fn write_start_array(&mut self, len: Option<u64>) -> Result<(), Error>;
write_start_dictionary(&mut self, len: Option<u64>) -> Result<(), Error>247     fn write_start_dictionary(&mut self, len: Option<u64>) -> Result<(), Error>;
write_end_collection(&mut self) -> Result<(), Error>248     fn write_end_collection(&mut self) -> Result<(), Error>;
249 
write_boolean(&mut self, value: bool) -> Result<(), Error>250     fn write_boolean(&mut self, value: bool) -> Result<(), Error>;
write_data(&mut self, value: &[u8]) -> Result<(), Error>251     fn write_data(&mut self, value: &[u8]) -> Result<(), Error>;
write_date(&mut self, value: Date) -> Result<(), Error>252     fn write_date(&mut self, value: Date) -> Result<(), Error>;
write_integer(&mut self, value: Integer) -> Result<(), Error>253     fn write_integer(&mut self, value: Integer) -> Result<(), Error>;
write_real(&mut self, value: f64) -> Result<(), Error>254     fn write_real(&mut self, value: f64) -> Result<(), Error>;
write_string(&mut self, value: &str) -> Result<(), Error>255     fn write_string(&mut self, value: &str) -> Result<(), Error>;
write_uid(&mut self, value: Uid) -> Result<(), Error>256     fn write_uid(&mut self, value: Uid) -> Result<(), Error>;
257 }
258 
259 pub(crate) mod private {
260     use std::io::Write;
261 
262     pub trait Sealed {}
263 
264     impl<W: Write> Sealed for super::BinaryWriter<W> {}
265     impl<W: Write> Sealed for super::XmlWriter<W> {}
266 }
267