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