diff options
| author | Edward Barnard | 2017-01-07 13:57:37 +0000 |
|---|---|---|
| committer | Edward Barnard | 2017-02-02 20:29:57 +0000 |
| commit | 910c3eed3dc7895086a98bf7f5d373e22388a272 (patch) | |
| tree | f13113d119e618fa37feaaf25998b0ebd29556d7 /src/binary | |
| parent | e0c687aa4dfa8a27982037efdf8692b39b7b9c97 (diff) | |
| download | rust-plist-910c3eed3dc7895086a98bf7f5d373e22388a272.tar.bz2 | |
Improve binary plist datetime decoding.
Diffstat (limited to 'src/binary')
| -rw-r--r-- | src/binary/reader.rs | 26 |
1 files changed, 18 insertions, 8 deletions
diff --git a/src/binary/reader.rs b/src/binary/reader.rs index 56bb587..c3c0be4 100644 --- a/src/binary/reader.rs +++ b/src/binary/reader.rs @@ -1,5 +1,5 @@ use byteorder::{BigEndian, ReadBytesExt}; -use chrono::{TimeZone, UTC}; +use chrono::{Duration, TimeZone, UTC}; use std::io::{Cursor, Read, Seek, SeekFrom}; use std::string::{FromUtf8Error, FromUtf16Error}; @@ -189,18 +189,28 @@ impl<R: Read + Seek> EventReader<R> { } (0x2, 3) => Some(PlistEvent::RealValue(try!(self.reader.read_f64::<BigEndian>()))), (0x2, _) => return Err(Error::InvalidData), // odd length float - (0x3, 3) => { + (0x3, 3) => {; // Date - // Seconds since 1/1/2001 00:00:00 + // Seconds since 1/1/2001 00:00:00. let timestamp = try!(self.reader.read_f64::<BigEndian>()); - let secs = timestamp.floor(); - let subsecs = timestamp - secs; + let millis = timestamp * 1_000.0; + // Chrono's Duration can only millisecond values between ::std::i64::MIN and + // ::std::i64::MAX. + if millis > ::std::i64::MAX as f64 || millis < ::std::i64::MIN as f64 { + return Err(Error::InvalidData); + } + + let whole_millis = millis.floor(); + let submilli_nanos = ((millis - whole_millis) * 1_000_000.0).floor(); + + let dur = Duration::milliseconds(whole_millis as i64); + let dur = dur + Duration::nanoseconds(submilli_nanos as i64); - let int_secs = (secs as i64) + (31 * 365 + 8) * 86400; - let int_nanos = (subsecs * 1_000_000_000f64) as u32; + let plist_epoch = UTC.ymd(2001, 1, 1).and_hms(0, 0, 0); + let date = try!(plist_epoch.checked_add(dur).ok_or(Error::InvalidData)); - Some(PlistEvent::DateValue(UTC.timestamp(int_secs, int_nanos))) + Some(PlistEvent::DateValue(date)) } (0x4, n) => { // Data |
