aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEdward Barnard2017-01-07 13:57:37 +0000
committerEdward Barnard2017-02-02 20:29:57 +0000
commit910c3eed3dc7895086a98bf7f5d373e22388a272 (patch)
treef13113d119e618fa37feaaf25998b0ebd29556d7
parente0c687aa4dfa8a27982037efdf8692b39b7b9c97 (diff)
downloadrust-plist-910c3eed3dc7895086a98bf7f5d373e22388a272.tar.bz2
Improve binary plist datetime decoding.
-rw-r--r--src/binary/reader.rs26
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