From b69cdca85d2a2e7563b086426ab0165b45ea5eb4 Mon Sep 17 00:00:00 2001 From: Max Audron Date: Sat, 2 May 2020 18:32:28 +0200 Subject: add parsing of signalproxy messages --- src/primitive/datetime.rs | 171 ++++++++++++++++++++++++++++++---------------- src/primitive/variant.rs | 13 ++-- 2 files changed, 118 insertions(+), 66 deletions(-) (limited to 'src/primitive') 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, failure::Error> { +impl From 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, failure::Error> { let mut values: Vec = 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, failure::Error> { let mut values: Vec = 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, failure::Error> { let mut values: Vec = 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 => { -- cgit v1.2.3 d docs and reorganize filesMax Audron-1281/+321 2025-02-26implement NetworkId UserTypeMax Audron-108/+196 2025-02-26implement IdentityIdMax Audron-8/+79 2025-02-26refactor variant deserializationMax Audron-123/+59 2025-02-26refactor deserialize and serializevariant traitMax Audron-90/+80 2025-02-26refactor variant serialization codeMax Audron-256/+405 2025-02-26add MsgId and BufferId to objects where neededMax Audron-141/+157 2025-02-25enable transparent repr for msgid and bufferidMax Audron-0/+2 2025-02-25Implement BacklogManagerTobias Deiminger-59/+113 2025-02-25Use BufferId in BufferInfoTobias Deiminger-10/+11 2025-02-25Use BufferId in VariantTobias Deiminger-2/+33 2025-02-25Add BufferId as Rust typeTobias Deiminger-0/+39 2025-02-25Use MsgId in MessageTobias Deiminger-18/+6 2025-02-25Use MsgId in VariantTobias Deiminger-20/+37 2025-02-25Add MsgId as Rust typeTobias Deiminger-0/+56 2025-02-24added session manager comments and log messageMax Audron-1/+3 2025-02-23add identity syncable to SessionManagerMax Audron-1/+8 2025-02-23add syncables for IrcUserMax Audron-2/+53 2025-02-23move network config to it's own file and impl it's syncMax Audron-23/+84 2025-02-23add basic network syncablesMax Audron-39/+420 2025-02-23clean up unused_import and unused_variables a bitMax Audron-2/+8 2025-02-23fix server feature errorsMax Audron-28/+23 2025-02-23fix ircchannel and maplist network representationMax Audron-154/+137 2025-02-22replace deprecated failure crate with thiserrorMax Audron-278/+194 2025-02-22update dependencies and fix errorsMax Audron-508/+332 2025-02-22update flakeMax Audron-94/+117 2024-05-22add todos to readmeMax Audron-16/+35