fn allocate_vec<T>(&self, len: u64, size: usize) -> Result<Vec<T>, Error> { // Check we are not reading past the start of the plist trailer let inner = |len: u64, size: usize| { let byte_len = len.checked_mul(size as u64)?; let end_offset = self.reader.pos.checked_add(byte_len)?; if end_offset <= self.trailer_start_offset {
Some(())
} else {
None
}
};
inner(len, size).ok_or_else(|| self.with_pos(ErrorKind::ObjectOffsetTooLarge))?;
/// Reads a list of `len` big-endian integers of `size` bytes from the reader. fn read_ints(&mutself, len: u64, size: u8) -> Result<Vec<u64>, Error> { letmut ints = self.allocate_vec(len, size as usize)?; for _ in0..len { match size { 1 => ints.push(self.read_u8()?.into()), 2 => ints.push(self.read_be_u16()?.into()), 4 => ints.push(self.read_be_u32()?.into()), 8 => ints.push(self.read_be_u64()?),
_ => unreachable!("size is either self.ref_size or offset_size both of which are already validated")
}
}
Ok(ints)
}
/// Reads a list of `len` offsets into the object table from the reader. fn read_refs(&mutself, len: u64) -> Result<Vec<u64>, Error> { let ref_size = self.ref_size; self.read_ints(len, ref_size)
}
/// Reads a compressed value length from the reader. `len` must contain the low 4 bits of the /// object token. fn read_object_len(&mutself, len: u8) -> Result<u64, Error> { if (len & 0x0f) == 0x0f { let len_power_of_two = self.read_u8()? & 0x03;
Ok(match len_power_of_two { 0 => self.read_u8()?.into(), 1 => self.read_be_u16()?.into(), 2 => self.read_be_u32()?.into(), 3 => self.read_be_u64()?,
_ => return Err(self.with_pos(ErrorKind::InvalidObjectLength)),
})
} else {
Ok(len.into())
}
}
/// Reads `len` bytes from the reader. fn read_data(&mutself, len: u64) -> Result<Vec<u8>, Error> { letmut data = self.allocate_vec(len, size_of::<u8>())?;
data.resize(len as usize, 0); self.reader.read_all(&mut data)?;
Ok(data)
}
fn read_next(&mutself) -> Result<Option<OwnedEvent>, Error> { let object_ref = ifself.ref_size == 0 { // Initialise here rather than in new self.read_trailer()?; self.root_object
} else { let maybe_object_ref = iflet Some(stack_item) = self.stack.last_mut() {
stack_item.child_object_refs.pop()
} else { // Finished reading the plist return Ok(None);
};
iflet Some(object_ref) = maybe_object_ref {
object_ref
} else { // We're at the end of an array or dict. Pop the top stack item and return. let stack_item = self.pop_stack_item(); match stack_item.ty {
StackType::Array | StackType::Dict => return Ok(Some(Event::EndCollection)),
}
}
};
self.seek_to_object(object_ref)?;
let token = self.read_u8()?; let ty = (token & 0xf0) >> 4; let size = token & 0x0f;
let result = match (ty, size) {
(0x0, 0x00) => return Err(self.with_pos(ErrorKind::NullObjectUnimplemented)),
(0x0, 0x08) => Some(Event::Boolean(false)),
(0x0, 0x09) => Some(Event::Boolean(true)),
(0x0, 0x0f) => return Err(self.with_pos(ErrorKind::FillObjectUnimplemented)),
(0x1, 0) => Some(Event::Integer(self.read_u8()?.into())),
(0x1, 1) => Some(Event::Integer(self.read_be_u16()?.into())),
(0x1, 2) => Some(Event::Integer(self.read_be_u32()?.into())),
(0x1, 3) => Some(Event::Integer(self.read_be_i64()?.into())),
(0x1, 4) => { let value = self.read_be_i128()?; if value < 0 || value > u64::max_value().into() { return Err(self.with_pos(ErrorKind::IntegerOutOfRange));
}
Some(Event::Integer((value as u64).into()))
}
(0x1, _) => return Err(self.with_pos(ErrorKind::UnknownObjectType(token))), // variable length int
(0x2, 2) => Some(Event::Real(f32::from_bits(self.read_be_u32()?).into())),
(0x2, 3) => Some(Event::Real(f64::from_bits(self.read_be_u64()?))),
(0x2, _) => return Err(self.with_pos(ErrorKind::UnknownObjectType(token))), // odd length float
(0x3, 3) => { // Date. Seconds since 1/1/2001 00:00:00. let secs = f64::from_bits(self.read_be_u64()?); let date = Date::from_seconds_since_plist_epoch(secs)
.map_err(|InfiniteOrNanDate| self.with_pos(ErrorKind::InfiniteOrNanDate))?;
Some(Event::Date(date))
}
(0x4, n) => { // Data let len = self.read_object_len(n)?;
Some(Event::Data(self.read_data(len)?.into()))
}
(0x5, n) => { // ASCII string let len = self.read_object_len(n)?; let raw = self.read_data(len)?; let string = String::from_utf8(raw)
.map_err(|_| self.with_pos(ErrorKind::InvalidUtf8String))?;
Some(Event::String(string.into()))
}
(0x6, n) => { // UTF-16 string let len_utf16_codepoints = self.read_object_len(n)?; letmut raw_utf16 = self.allocate_vec(len_utf16_codepoints, size_of::<u16>())?;
for _ in0..len_utf16_codepoints {
raw_utf16.push(self.read_be_u16()?);
}
let string = String::from_utf16(&raw_utf16)
.map_err(|_| self.with_pos(ErrorKind::InvalidUtf16String))?;
Some(Event::String(string.into()))
}
(0x8, n) if n < 8 => { // Uid letmut buf = [0; 8]; // `len_bytes` is at most 8. let len_bytes = n as usize + 1; // Values are stored in big-endian so we must put the least significant bytes at // the end of the buffer. self.reader.read_all(&mut buf[8 - len_bytes..])?; let value = u64::from_be_bytes(buf);
Some(Event::Uid(Uid::new(value)))
}
(0xa, n) => { // Array let len = self.read_object_len(n)?; letmut child_object_refs = self.read_refs(len)?; // Reverse so we can pop off the end of the stack in order
child_object_refs.reverse();
Some(Event::StartArray(Some(len)))
}
(0xd, n) => { // Dict let len = self.read_object_len(n)?; let key_refs = self.read_refs(len)?; let value_refs = self.read_refs(len)?;
let keys_and_values_len = len
.checked_mul(2)
.ok_or_else(|| self.with_pos(ErrorKind::ObjectTooLarge))?; letmut child_object_refs = self.allocate_vec(keys_and_values_len, self.ref_size as usize)?; let len = key_refs.len(); for i in1..=len { // Reverse so we can pop off the end of the stack in order
child_object_refs.push(value_refs[len - i]);
child_object_refs.push(key_refs[len - i]);
}
let reader = File::open(&Path::new("./tests/data/binary.plist")).unwrap(); let streaming_parser = BinaryReader::new(reader); let events: Vec<Event> = streaming_parser.map(|e| e.unwrap()).collect();
let comparison = &[
StartDictionary(Some(13)),
String("Author".into()),
String("William Shakespeare".into()),
String("Birthdate".into()),
Date(super::Date::from_rfc3339("1981-05-16T11:32:06Z").unwrap()),
String("EmptyArray".into()),
StartArray(Some(0)),
EndCollection,
String("IsNotFalse".into()),
Boolean(false),
String("SmallestNumber".into()),
Integer((-9223372036854775808i64).into()),
String("EmptyDictionary".into()),
StartDictionary(Some(0)),
EndCollection,
String("Height".into()),
Real(1.6),
String("Lines".into()),
StartArray(Some(2)),
String("It is a tale told by an idiot,".into()),
String("Full of sound and fury, signifying nothing.".into()),
EndCollection,
String("Death".into()),
Integer(1564.into()),
String("Blank".into()),
String("".into()),
String("BiggestNumber".into()),
Integer(18446744073709551615u64.into()),
String("IsTrue".into()),
Boolean(true),
String("Data".into()),
Data(vec![0, 0, 0, 190, 0, 0, 0, 3, 0, 0, 0, 30, 0, 0, 0].into()),
EndCollection,
];
assert_eq!(events, &comparison[..]);
}
#[test] fn utf16_plist() { let reader = File::open(&Path::new("./tests/data/utf16_bplist.plist")).unwrap(); let streaming_parser = BinaryReader::new(reader); letmut events: Vec<Event> = streaming_parser.map(|e| e.unwrap()).collect();
assert_eq!(events[2], Event::String("\u{2605} or better".into()));
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.