aboutsummaryrefslogtreecommitdiff
path: root/src/primitive
diff options
context:
space:
mode:
Diffstat (limited to 'src/primitive')
-rw-r--r--src/primitive/datetime.rs171
-rw-r--r--src/primitive/variant.rs13
2 files changed, 118 insertions, 66 deletions
diff --git a/src/primitive/datetime.rs b/src/primitive/datetime.rs
index e6946b9..cbcdd51 100644
--- a/src/primitive/datetime.rs
+++ b/src/primitive/datetime.rs
@@ -1,107 +1,160 @@
use crate::Deserialize;
use crate::Serialize;
-/// The DateTime struct represents a DateTime as received in IRC
-///
-/// DateTime is, like all other struct based types, serialized sequentially.
-#[derive(Clone, Debug, std::cmp::PartialEq)]
-pub struct DateTime {
- /// Day in Julian calendar, unknown if signed or unsigned
- julian_day: i32,
- /// Milliseconds since start of day
- millis_of_day: i32,
- /// Timezone of DateTime, 0x00 is local, 0x01 is UTC
- zone: u8,
+use time::{OffsetDateTime, PrimitiveDateTime, UtcOffset};
+
+// The DateTime struct represents a DateTime as received in IRC
+//
+// DateTime is, like all other struct based types, serialized sequentially.
+// #[derive(Clone, Debug, std::cmp::PartialEq)]
+// pub struct DateTime {
+// /// Day in Julian calendar, unknown if signed or unsigned
+// julian_day: i32,
+// /// Milliseconds since start of day
+// millis_of_day: i32,
+// /// Timezone of DateTime, 0x00 is local, 0x01 is UTC
+// zone: u8,
+// }
+
+pub type DateTime = OffsetDateTime;
+pub use time::{Date, Time};
+
+/// TimeSpec specifies whether the time is a local time, daylightsaving local time or a form of UTC Offset
+#[repr(i8)]
+#[derive(Copy, Clone, Debug, std::cmp::PartialEq)]
+pub enum TimeSpec {
+ LocalUnknown = -0x01,
+ LocalStandard = 0x00,
+ LocalDST = 0x01,
+ UTC = 0x02,
+ OffsetFromUTC = 0x03,
}
-impl Serialize for DateTime {
- fn serialize(&self) -> Result<Vec<std::primitive::u8>, failure::Error> {
+impl From<i8> for TimeSpec {
+ fn from(val: i8) -> Self {
+ match val {
+ -0x01 => TimeSpec::LocalUnknown,
+ 0x00 => TimeSpec::LocalStandard,
+ 0x01 => TimeSpec::LocalDST,
+ 0x02 => TimeSpec::UTC,
+ 0x03 => TimeSpec::OffsetFromUTC,
+ _ => unimplemented!(),
+ }
+ }
+}
+
+impl Serialize for OffsetDateTime {
+ fn serialize(&self) -> Result<Vec<u8>, failure::Error> {
let mut values: Vec<u8> = Vec::new();
- values.append(&mut i32::serialize(&self.julian_day)?);
- values.append(&mut i32::serialize(&self.millis_of_day)?);
- values.append(&mut u8::serialize(&(self.zone))?);
+ values.extend(i32::serialize(&(self.date().julian_day() as i32))?);
+
+ let time: i32 = {
+ let hour: i32 = self.time().hour() as i32;
+ let minute: i32 = self.time().minute() as i32;
+ let second: i32 = self.time().second() as i32;
+ let milli: i32 = self.time().millisecond() as i32;
+
+ milli + (second * 1000) + (minute * 60000) + (hour * 60 * 60000)
+ };
+
+ values.extend(i32::serialize(&time)?);
+ values.extend(u8::serialize(&(TimeSpec::OffsetFromUTC as u8))?);
+ values.extend(i32::serialize(&self.offset().as_seconds())?);
Ok(values)
}
}
-impl Deserialize for DateTime {
- fn parse(b: &[std::primitive::u8]) -> Result<(std::primitive::usize, Self), failure::Error>
- where
- Self: Sized,
- {
+impl Deserialize for OffsetDateTime {
+ fn parse(b: &[u8]) -> Result<(usize, Self), failure::Error> {
let (_, julian_day) = i32::parse(&b[0..4])?;
let (_, millis_of_day) = i32::parse(&b[4..8])?;
let (_, zone) = u8::parse(&b[8..9])?;
- return Ok((
- 9,
- DateTime {
- julian_day,
- millis_of_day,
- zone,
- },
- ));
- }
-}
+ let mut pos = 9;
+
+ let zone = TimeSpec::from(zone as i8);
+
+ let offset: UtcOffset;
+ match zone {
+ TimeSpec::LocalUnknown | TimeSpec::LocalStandard | TimeSpec::LocalDST => {
+ offset = UtcOffset::current_local_offset()
+ }
+ TimeSpec::UTC => offset = UtcOffset::UTC,
+ TimeSpec::OffsetFromUTC => {
+ let (_, tmp_offset) = i32::parse(&b[9..13])?;
+ pos += 4;
+ offset = UtcOffset::seconds(tmp_offset)
+ }
+ }
-/// The Date struct represents a Date as received in IRC
-///
-/// Date is, like all other struct based types, serialized sequentially.
-#[derive(Clone, Debug, std::cmp::PartialEq)]
-pub struct Date {
- /// Day in Julian calendar, unknown if signed or unsigned
- julian_day: i32,
+ let date = Date::from_julian_day(julian_day as i64);
+
+ let hour = millis_of_day / 60 / 60000;
+ let minute = (millis_of_day - (hour * 60 * 60000)) / 60000;
+ let seconds = (millis_of_day - (hour * 60 * 60000) - (minute * 60000)) / 1000;
+ let millis = millis_of_day - (hour * 60 * 60000) - (minute * 60000) - (seconds * 1000);
+
+ let time =
+ Time::try_from_hms_milli(hour as u8, minute as u8, seconds as u8, millis as u16)?;
+ let primitivedatetime = PrimitiveDateTime::new(date, time);
+ let datetime = primitivedatetime.assume_offset(offset);
+
+ Ok((pos, datetime))
+ }
}
impl Serialize for Date {
fn serialize(&self) -> Result<Vec<std::primitive::u8>, failure::Error> {
let mut values: Vec<u8> = Vec::new();
- values.append(&mut i32::serialize(&self.julian_day)?);
+ values.extend(i32::serialize(&(self.julian_day() as i32))?);
Ok(values)
}
}
impl Deserialize for Date {
- fn parse(b: &[std::primitive::u8]) -> Result<(std::primitive::usize, Self), failure::Error>
- where
- Self: Sized,
- {
+ fn parse(b: &[std::primitive::u8]) -> Result<(std::primitive::usize, Self), failure::Error> {
let (_, julian_day) = i32::parse(&b[0..4])?;
+ let date = Date::from_julian_day(julian_day as i64);
- return Ok((9, Date { julian_day }));
+ Ok((4, date))
}
}
-/// The Time struct represents a Time as received in IRC
-///
-/// Time is, like all other struct based types, serialized sequentially.
-#[derive(Clone, Debug, std::cmp::PartialEq)]
-pub struct Time {
- /// Milliseconds since start of day
- millis_of_day: i32,
-}
-
impl Serialize for Time {
fn serialize(&self) -> Result<Vec<std::primitive::u8>, failure::Error> {
let mut values: Vec<u8> = Vec::new();
- values.append(&mut i32::serialize(&self.millis_of_day)?);
+ let time: i32 = {
+ let hour: i32 = self.hour() as i32;
+ let minute: i32 = self.minute() as i32;
+ let second: i32 = self.second() as i32;
+ let milli: i32 = self.millisecond() as i32;
+
+ milli + (second * 1000) + (minute * 60000) + (hour * 60 * 60000)
+ };
+
+ values.extend(i32::serialize(&time)?);
Ok(values)
}
}
impl Deserialize for Time {
- fn parse(b: &[std::primitive::u8]) -> Result<(std::primitive::usize, Self), failure::Error>
- where
- Self: Sized,
- {
+ fn parse(b: &[std::primitive::u8]) -> Result<(std::primitive::usize, Self), failure::Error> {
let (_, millis_of_day) = i32::parse(&b[0..4])?;
- return Ok((4, Time { millis_of_day }));
+ let hour = millis_of_day / 60 / 60000;
+ let minute = (millis_of_day - (hour * 60 * 60000)) / 60000;
+ let seconds = (millis_of_day - (hour * 60 * 60000) - (minute * 60000)) / 1000;
+ let millis = millis_of_day - (hour * 60 * 60000) - (minute * 60000) - (seconds * 1000);
+
+ let time =
+ Time::try_from_hms_milli(hour as u8, minute as u8, seconds as u8, millis as u16)?;
+
+ Ok((4, time))
}
}
diff --git a/src/primitive/variant.rs b/src/primitive/variant.rs
index 71ddc4a..9242d90 100644
--- a/src/primitive/variant.rs
+++ b/src/primitive/variant.rs
@@ -12,9 +12,7 @@ use crate::{Serialize, SerializeUTF8};
extern crate bytes;
-use crate::primitive::{
- BufferInfo, Date, DateTime, Message, Time, VariantList, VariantMap,
-};
+use crate::primitive::{BufferInfo, Date, DateTime, Message, Time, VariantList, VariantMap};
/// Variant represents the possible types we can receive
///
@@ -204,17 +202,18 @@ impl Deserialize for Variant {
}
primitive::QDATETIME => {
trace!(target: "primitive::Variant", "Parsing Variant: Date");
- let (vlen, value) = Date::parse(&b[len..])?;
- return Ok((len + vlen, Variant::Date(value.clone())));
+ // let (vlen, value) = DateTime::parse(&b[len..])?;
+ let (vlen, value): (usize, DateTime) = Deserialize::parse(&b[len..])?;
+ return Ok((len + vlen, Variant::DateTime(value.clone())));
}
primitive::QDATE => {
trace!(target: "primitive::Variant", "Parsing Variant: Date");
- let (vlen, value) = Date::parse(&b[len..])?;
+ let (vlen, value): (usize, Date) = Deserialize::parse(&b[len..])?;
return Ok((len + vlen, Variant::Date(value.clone())));
}
primitive::QTIME => {
trace!(target: "primitive::Variant", "Parsing Variant: Time");
- let (vlen, value) = Time::parse(&b[len..])?;
+ let (vlen, value): (usize, Time) = Deserialize::parse(&b[len..])?;
return Ok((len + vlen, Variant::Time(value.clone())));
}
primitive::BOOL => {