From eef9d906b38def0091faa2dc955a4c0970fe251d Mon Sep 17 00:00:00 2001 From: Edward Barnard Date: Tue, 22 Dec 2015 12:58:19 +0000 Subject: Rustfmt --- src/binary/mod.rs | 2 +- src/binary/reader.rs | 600 ++++++++++++++++++++++++++------------------------- 2 files changed, 306 insertions(+), 296 deletions(-) (limited to 'src/binary') diff --git a/src/binary/mod.rs b/src/binary/mod.rs index 460dbd8..7c9ae75 100644 --- a/src/binary/mod.rs +++ b/src/binary/mod.rs @@ -1,3 +1,3 @@ mod reader; -pub use self::reader::EventReader; \ No newline at end of file +pub use self::reader::EventReader; diff --git a/src/binary/reader.rs b/src/binary/reader.rs index 11c20cc..eec7554 100644 --- a/src/binary/reader.rs +++ b/src/binary/reader.rs @@ -7,320 +7,330 @@ use std::string::FromUtf16Error; use {ReadError, ReadResult, PlistEvent}; impl From for ReadError { - fn from(err: ByteorderError) -> ReadError { - match err { - ByteorderError::UnexpectedEOF => ReadError::UnexpectedEof, - ByteorderError::Io(err) => ReadError::Io(err) - } - } + fn from(err: ByteorderError) -> ReadError { + match err { + ByteorderError::UnexpectedEOF => ReadError::UnexpectedEof, + ByteorderError::Io(err) => ReadError::Io(err), + } + } } impl From for ReadError { - fn from(_: FromUtf16Error) -> ReadError { - ReadError::InvalidData - } + fn from(_: FromUtf16Error) -> ReadError { + ReadError::InvalidData + } } struct StackItem { - object_refs: Vec, - ty: StackType + object_refs: Vec, + ty: StackType, } enum StackType { - Array, - Dict, - Root + Array, + Dict, + Root, } /// https://opensource.apple.com/source/CF/CF-550/CFBinaryPList.c /// https://hg.python.org/cpython/file/3.4/Lib/plistlib.py pub struct EventReader { - stack: Vec, - object_offsets: Vec, - reader: R, - ref_size: u8, - finished: bool + stack: Vec, + object_offsets: Vec, + reader: R, + ref_size: u8, + finished: bool, } -impl EventReader { - pub fn new(reader: R) -> EventReader { - EventReader { - stack: Vec::new(), - object_offsets: Vec::new(), - reader: reader, - ref_size: 0, - finished: false - } - } - - fn read_trailer(&mut self) -> ReadResult<()> { - try!(self.reader.seek(SeekFrom::Start(0))); - let mut magic = [0; 8]; - try!(self.reader.read(&mut magic)); - assert_eq!(&magic, b"bplist00"); - - - // Trailer starts with 6 bytes of padding - try!(self.reader.seek(SeekFrom::End(-32 + 6))); - let offset_size = try!(self.reader.read_u8()); - self.ref_size = try!(self.reader.read_u8()); - let num_objects = try!(self.reader.read_u64::()); - let top_object = try!(self.reader.read_u64::()); - let offset_table_offset = try!(self.reader.read_u64::()); - - // Read offset table - try!(self.reader.seek(SeekFrom::Start(offset_table_offset))); - self.object_offsets = try!(self.read_ints(num_objects, offset_size)); - - // Seek to top object - self.stack.push(StackItem { - object_refs: vec![top_object], - ty: StackType::Root - }); - - Ok(()) - } - - fn read_ints(&mut self, len: u64, size: u8) -> ReadResult> { - let mut ints = Vec::with_capacity(len as usize); - // TODO: Is the match hoisted out of the loop? - for _ in 0..len { - match size { - 1 => ints.push(try!(self.reader.read_u8()) as u64), - 2 => ints.push(try!(self.reader.read_u16::()) as u64), - 4 => ints.push(try!(self.reader.read_u32::()) as u64), - 8 => ints.push(try!(self.reader.read_u64::()) as u64), - _ => return Err(ReadError::InvalidData) - } - } - Ok(ints) - } - - fn read_refs(&mut self, len: u64) -> ReadResult> { - let ref_size = self.ref_size; - self.read_ints(len, ref_size) - } - - fn read_object_len(&mut self, len: u8) -> ReadResult { - if (len & 0xf) == 0xf { - let len_power_of_two = try!(self.reader.read_u8()) & 0x3; - Ok(match len_power_of_two { - 0 => try!(self.reader.read_u8()) as u64, - 1 => try!(self.reader.read_u16::()) as u64, - 2 => try!(self.reader.read_u32::()) as u64, - 3 => try!(self.reader.read_u64::()), - _ => return Err(ReadError::InvalidData) - }) - } else { - Ok(len as u64) - } - } - - fn read_data(&mut self, len: u64) -> ReadResult> { - let mut data = vec![0; len as usize]; - let mut total_read = 0usize; - - while (total_read as u64) < len { - let read = try!(self.reader.read(&mut data[total_read..])); - if read == 0 { - return Err(ReadError::UnexpectedEof); - } - total_read += read; - } - - Ok(data) - } - - fn seek_to_object(&mut self, object_ref: u64) -> ReadResult { - let offset = *&self.object_offsets[object_ref as usize]; - let pos = try!(self.reader.seek(SeekFrom::Start(offset))); - Ok(pos) - } - - fn read_next(&mut self) -> ReadResult> { - if self.ref_size == 0 { - // Initialise here rather than in new - try!(self.read_trailer()); - return Ok(Some(PlistEvent::StartPlist)) - } - - let object_ref = match self.stack.last_mut() { - Some(stack_item) => stack_item.object_refs.pop(), - // Reached the end of the plist - None => return Ok(None) - }; - - match object_ref { - Some(object_ref) => { - try!(self.seek_to_object(object_ref)); - }, - None => { - // We're at the end of an array or dict. Pop the top stack item and return - let item = self.stack.pop().unwrap(); - match item.ty { - StackType::Array => return Ok(Some(PlistEvent::EndArray)), - StackType::Dict => return Ok(Some(PlistEvent::EndDictionary)), - StackType::Root => return Ok(Some(PlistEvent::EndPlist)) - } - } - } - - let token = try!(self.reader.read_u8()); - let ty = (token & 0xf0) >> 4; - let size = token & 0x0f; - - let result = match (ty, size) { - (0x0, 0x00) => return Err(ReadError::UnsupportedType), // null - (0x0, 0x08) => Some(PlistEvent::BooleanValue(false)), - (0x0, 0x09) => Some(PlistEvent::BooleanValue(true)), - (0x0, 0x0f) => return Err(ReadError::UnsupportedType), // fill - (0x1, 0) => Some(PlistEvent::IntegerValue(try!(self.reader.read_u8()) as i64)), - (0x1, 1) => Some(PlistEvent::IntegerValue(try!(self.reader.read_u16::()) as i64)), - (0x1, 2) => Some(PlistEvent::IntegerValue(try!(self.reader.read_u32::()) as i64)), - (0x1, 3) => Some(PlistEvent::IntegerValue(try!(self.reader.read_i64::()))), - (0x1, 4) => return Err(ReadError::UnsupportedType), // 128 bit int - (0x1, _) => return Err(ReadError::UnsupportedType), // variable length int - (0x2, 2) => Some(PlistEvent::RealValue(try!(self.reader.read_f32::()) as f64)), - (0x2, 3) => Some(PlistEvent::RealValue(try!(self.reader.read_f64::()))), - (0x2, _) => return Err(ReadError::UnsupportedType), // odd length float - (0x3, 3) => { // Date - // Seconds since 1/1/2001 00:00:00 - let timestamp = try!(self.reader.read_f64::()); - - let secs = timestamp.floor(); - let subsecs = timestamp - secs; - - let int_secs = (secs as i64) + (31 * 365 + 8) * 86400; - let int_nanos = (subsecs * 1_000_000_000f64) as u32; - - Some(PlistEvent::DateValue(UTC.timestamp(int_secs, int_nanos))) - } - (0x4, n) => { // Data - let len = try!(self.read_object_len(n)); - Some(PlistEvent::DataValue(try!(self.read_data(len)))) - }, - (0x5, n) => { // ASCII string - let len = try!(self.read_object_len(n)); - let raw = try!(self.read_data(len)); - let string = String::from_utf8(raw).unwrap(); - Some(PlistEvent::StringValue(string)) - }, - (0x6, n) => { // UTF-16 string - let len = try!(self.read_object_len(n)); - let raw = try!(self.read_data(len)); - let mut cursor = Cursor::new(raw); - - let mut raw_utf16 = Vec::with_capacity(len as usize / 2); - while cursor.position() < len { - raw_utf16.push(try!(cursor.read_u16::())) - } - - let string = try!(String::from_utf16(&raw_utf16)); - Some(PlistEvent::StringValue(string)) - }, - (0xa, n) => { // Array - let len = try!(self.read_object_len(n)); - let mut object_refs = try!(self.read_refs(len)); - // Reverse so we can pop off the end of the stack in order - object_refs.reverse(); - - self.stack.push(StackItem { - ty: StackType::Array, - object_refs: object_refs - }); - - Some(PlistEvent::StartArray(Some(len))) - }, - (0xd, n) => { // Dict - let len = try!(self.read_object_len(n)); - let key_refs = try!(self.read_refs(len)); - let value_refs = try!(self.read_refs(len)); - - let len = len as usize; - - let mut object_refs = Vec::with_capacity(len * 2); - - for i in 1..len+1 { - // Reverse so we can pop off the end of the stack in order - object_refs.push(value_refs[len - i]); - object_refs.push(key_refs[len - i]); - } - - self.stack.push(StackItem { - ty: StackType::Dict, - object_refs: object_refs - }); - - Some(PlistEvent::StartDictionary(Some(len as u64))) - }, - (_, _) => return Err(ReadError::InvalidData) - }; - - Ok(result) - } +impl EventReader { + pub fn new(reader: R) -> EventReader { + EventReader { + stack: Vec::new(), + object_offsets: Vec::new(), + reader: reader, + ref_size: 0, + finished: false, + } + } + + fn read_trailer(&mut self) -> ReadResult<()> { + try!(self.reader.seek(SeekFrom::Start(0))); + let mut magic = [0; 8]; + try!(self.reader.read(&mut magic)); + assert_eq!(&magic, b"bplist00"); + + + // Trailer starts with 6 bytes of padding + try!(self.reader.seek(SeekFrom::End(-32 + 6))); + let offset_size = try!(self.reader.read_u8()); + self.ref_size = try!(self.reader.read_u8()); + let num_objects = try!(self.reader.read_u64::()); + let top_object = try!(self.reader.read_u64::()); + let offset_table_offset = try!(self.reader.read_u64::()); + + // Read offset table + try!(self.reader.seek(SeekFrom::Start(offset_table_offset))); + self.object_offsets = try!(self.read_ints(num_objects, offset_size)); + + // Seek to top object + self.stack.push(StackItem { + object_refs: vec![top_object], + ty: StackType::Root, + }); + + Ok(()) + } + + fn read_ints(&mut self, len: u64, size: u8) -> ReadResult> { + let mut ints = Vec::with_capacity(len as usize); + // TODO: Is the match hoisted out of the loop? + for _ in 0..len { + match size { + 1 => ints.push(try!(self.reader.read_u8()) as u64), + 2 => ints.push(try!(self.reader.read_u16::()) as u64), + 4 => ints.push(try!(self.reader.read_u32::()) as u64), + 8 => ints.push(try!(self.reader.read_u64::()) as u64), + _ => return Err(ReadError::InvalidData), + } + } + Ok(ints) + } + + fn read_refs(&mut self, len: u64) -> ReadResult> { + let ref_size = self.ref_size; + self.read_ints(len, ref_size) + } + + fn read_object_len(&mut self, len: u8) -> ReadResult { + if (len & 0xf) == 0xf { + let len_power_of_two = try!(self.reader.read_u8()) & 0x3; + Ok(match len_power_of_two { + 0 => try!(self.reader.read_u8()) as u64, + 1 => try!(self.reader.read_u16::()) as u64, + 2 => try!(self.reader.read_u32::()) as u64, + 3 => try!(self.reader.read_u64::()), + _ => return Err(ReadError::InvalidData), + }) + } else { + Ok(len as u64) + } + } + + fn read_data(&mut self, len: u64) -> ReadResult> { + let mut data = vec![0; len as usize]; + let mut total_read = 0usize; + + while (total_read as u64) < len { + let read = try!(self.reader.read(&mut data[total_read..])); + if read == 0 { + return Err(ReadError::UnexpectedEof); + } + total_read += read; + } + + Ok(data) + } + + fn seek_to_object(&mut self, object_ref: u64) -> ReadResult { + let offset = *&self.object_offsets[object_ref as usize]; + let pos = try!(self.reader.seek(SeekFrom::Start(offset))); + Ok(pos) + } + + fn read_next(&mut self) -> ReadResult> { + if self.ref_size == 0 { + // Initialise here rather than in new + try!(self.read_trailer()); + return Ok(Some(PlistEvent::StartPlist)); + } + + let object_ref = match self.stack.last_mut() { + Some(stack_item) => stack_item.object_refs.pop(), + // Reached the end of the plist + None => return Ok(None), + }; + + match object_ref { + Some(object_ref) => { + try!(self.seek_to_object(object_ref)); + } + None => { + // We're at the end of an array or dict. Pop the top stack item and return + let item = self.stack.pop().unwrap(); + match item.ty { + StackType::Array => return Ok(Some(PlistEvent::EndArray)), + StackType::Dict => return Ok(Some(PlistEvent::EndDictionary)), + StackType::Root => return Ok(Some(PlistEvent::EndPlist)), + } + } + } + + let token = try!(self.reader.read_u8()); + let ty = (token & 0xf0) >> 4; + let size = token & 0x0f; + + let result = match (ty, size) { + (0x0, 0x00) => return Err(ReadError::UnsupportedType), // null + (0x0, 0x08) => Some(PlistEvent::BooleanValue(false)), + (0x0, 0x09) => Some(PlistEvent::BooleanValue(true)), + (0x0, 0x0f) => return Err(ReadError::UnsupportedType), // fill + (0x1, 0) => Some(PlistEvent::IntegerValue(try!(self.reader.read_u8()) as i64)), + (0x1, 1) => { + Some(PlistEvent::IntegerValue(try!(self.reader.read_u16::()) as i64)) + } + (0x1, 2) => { + Some(PlistEvent::IntegerValue(try!(self.reader.read_u32::()) as i64)) + } + (0x1, 3) => Some(PlistEvent::IntegerValue(try!(self.reader.read_i64::()))), + (0x1, 4) => return Err(ReadError::UnsupportedType), // 128 bit int + (0x1, _) => return Err(ReadError::UnsupportedType), // variable length int + (0x2, 2) => { + Some(PlistEvent::RealValue(try!(self.reader.read_f32::()) as f64)) + } + (0x2, 3) => Some(PlistEvent::RealValue(try!(self.reader.read_f64::()))), + (0x2, _) => return Err(ReadError::UnsupportedType), // odd length float + (0x3, 3) => { + // Date + // Seconds since 1/1/2001 00:00:00 + let timestamp = try!(self.reader.read_f64::()); + + let secs = timestamp.floor(); + let subsecs = timestamp - secs; + + let int_secs = (secs as i64) + (31 * 365 + 8) * 86400; + let int_nanos = (subsecs * 1_000_000_000f64) as u32; + + Some(PlistEvent::DateValue(UTC.timestamp(int_secs, int_nanos))) + } + (0x4, n) => { + // Data + let len = try!(self.read_object_len(n)); + Some(PlistEvent::DataValue(try!(self.read_data(len)))) + } + (0x5, n) => { + // ASCII string + let len = try!(self.read_object_len(n)); + let raw = try!(self.read_data(len)); + let string = String::from_utf8(raw).unwrap(); + Some(PlistEvent::StringValue(string)) + } + (0x6, n) => { + // UTF-16 string + let len = try!(self.read_object_len(n)); + let raw = try!(self.read_data(len)); + let mut cursor = Cursor::new(raw); + + let mut raw_utf16 = Vec::with_capacity(len as usize / 2); + while cursor.position() < len { + raw_utf16.push(try!(cursor.read_u16::())) + } + + let string = try!(String::from_utf16(&raw_utf16)); + Some(PlistEvent::StringValue(string)) + } + (0xa, n) => { + // Array + let len = try!(self.read_object_len(n)); + let mut object_refs = try!(self.read_refs(len)); + // Reverse so we can pop off the end of the stack in order + object_refs.reverse(); + + self.stack.push(StackItem { + ty: StackType::Array, + object_refs: object_refs, + }); + + Some(PlistEvent::StartArray(Some(len))) + } + (0xd, n) => { + // Dict + let len = try!(self.read_object_len(n)); + let key_refs = try!(self.read_refs(len)); + let value_refs = try!(self.read_refs(len)); + + let len = len as usize; + + let mut object_refs = Vec::with_capacity(len * 2); + + for i in 1..len + 1 { + // Reverse so we can pop off the end of the stack in order + object_refs.push(value_refs[len - i]); + object_refs.push(key_refs[len - i]); + } + + self.stack.push(StackItem { + ty: StackType::Dict, + object_refs: object_refs, + }); + + Some(PlistEvent::StartDictionary(Some(len as u64))) + } + (_, _) => return Err(ReadError::InvalidData), + }; + + Ok(result) + } } -impl Iterator for EventReader { - type Item = ReadResult; - - fn next(&mut self) -> Option> { - if self.finished { - None - } else { - match self.read_next() { - Ok(Some(event)) => Some(Ok(event)), - Err(err) => { - self.finished = true; - Some(Err(err)) - }, - Ok(None) => { - self.finished = true; - None - } - } - } - } +impl Iterator for EventReader { + type Item = ReadResult; + + fn next(&mut self) -> Option> { + if self.finished { + None + } else { + match self.read_next() { + Ok(Some(event)) => Some(Ok(event)), + Err(err) => { + self.finished = true; + Some(Err(err)) + } + Ok(None) => { + self.finished = true; + None + } + } + } + } } #[cfg(test)] mod tests { - use chrono::{TimeZone, UTC}; - use std::fs::File; - use std::path::Path; - - use super::*; - use PlistEvent; - - #[test] - fn streaming_parser() { - use PlistEvent::*; - - let reader = File::open(&Path::new("./tests/data/binary.plist")).unwrap(); - let streaming_parser = EventReader::new(reader); - let events: Vec = streaming_parser.map(|e| e.unwrap()).collect(); - - let comparison = &[ - StartPlist, - StartDictionary(Some(6)), - StringValue("Lines".to_owned()), - StartArray(Some(2)), - StringValue("It is a tale told by an idiot,".to_owned()), - StringValue("Full of sound and fury, signifying nothing.".to_owned()), - EndArray, - StringValue("Death".to_owned()), - IntegerValue(1564), - StringValue("Height".to_owned()), - RealValue(1.60), - StringValue("Birthdate".to_owned()), - DateValue(UTC.ymd(1981, 05, 16).and_hms(11, 32, 06)), - StringValue("Author".to_owned()), - StringValue("William Shakespeare".to_owned()), - StringValue("Data".to_owned()), - DataValue(vec![0, 0, 0, 190, 0, 0, 0, 3, 0, 0, 0, 30, 0, 0, 0]), - EndDictionary, - EndPlist - ]; - - assert_eq!(events, comparison); - } -} \ No newline at end of file + use chrono::{TimeZone, UTC}; + use std::fs::File; + use std::path::Path; + + use super::*; + use PlistEvent; + + #[test] + fn streaming_parser() { + use PlistEvent::*; + + let reader = File::open(&Path::new("./tests/data/binary.plist")).unwrap(); + let streaming_parser = EventReader::new(reader); + let events: Vec = streaming_parser.map(|e| e.unwrap()).collect(); + + let comparison = &[StartPlist, + StartDictionary(Some(6)), + StringValue("Lines".to_owned()), + StartArray(Some(2)), + StringValue("It is a tale told by an idiot,".to_owned()), + StringValue("Full of sound and fury, signifying nothing.".to_owned()), + EndArray, + StringValue("Death".to_owned()), + IntegerValue(1564), + StringValue("Height".to_owned()), + RealValue(1.60), + StringValue("Birthdate".to_owned()), + DateValue(UTC.ymd(1981, 05, 16).and_hms(11, 32, 06)), + StringValue("Author".to_owned()), + StringValue("William Shakespeare".to_owned()), + StringValue("Data".to_owned()), + DataValue(vec![0, 0, 0, 190, 0, 0, 0, 3, 0, 0, 0, 30, 0, 0, 0]), + EndDictionary, + EndPlist]; + + assert_eq!(events, comparison); + } +} -- cgit v1.2.3