diff options
Diffstat (limited to '')
| -rw-r--r-- | src/deserialize.rs | 21 | ||||
| -rw-r--r-- | src/lib.rs | 46 | ||||
| -rw-r--r-- | src/message/signalproxy/objects/backlogmanager.rs | 37 | ||||
| -rw-r--r-- | src/primitive/bufferid.rs | 15 | ||||
| -rw-r--r-- | src/primitive/bufferinfo.rs | 13 | ||||
| -rw-r--r-- | src/primitive/datetime.rs | 16 | ||||
| -rw-r--r-- | src/primitive/message.rs | 43 | ||||
| -rw-r--r-- | src/primitive/mod.rs | 2 | ||||
| -rw-r--r-- | src/primitive/msgid.rs | 17 | ||||
| -rw-r--r-- | src/primitive/peerptr.rs | 56 | ||||
| -rw-r--r-- | src/primitive/signedint.rs | 20 | ||||
| -rw-r--r-- | src/primitive/string.rs | 33 | ||||
| -rw-r--r-- | src/primitive/stringlist.rs | 6 | ||||
| -rw-r--r-- | src/primitive/unsignedint.rs | 24 | ||||
| -rw-r--r-- | src/primitive/variant.rs | 212 | ||||
| -rw-r--r-- | src/primitive/variantlist.rs | 6 | ||||
| -rw-r--r-- | src/primitive/variantmap.rs | 6 | ||||
| -rw-r--r-- | src/serialize.rs | 88 |
18 files changed, 405 insertions, 256 deletions
diff --git a/src/deserialize.rs b/src/deserialize.rs new file mode 100644 index 0000000..e13f21f --- /dev/null +++ b/src/deserialize.rs @@ -0,0 +1,21 @@ +use crate::error::ProtocolError; + +/// Deserialization of types and structs to the quassel byteprotocol +pub trait Deserialize { + fn parse(b: &[u8]) -> Result<(usize, Self), ProtocolError> + where + Self: std::marker::Sized; +} + +/// Deserialization of UTF-8 based Strings to the quassel byteprotocol +pub trait DeserializeUTF8 { + fn parse_utf8(b: &[u8]) -> Result<(usize, Self), ProtocolError> + where + Self: std::marker::Sized; +} + +pub trait DeserializeVariant { + fn parse_variant(b: &[u8]) -> Result<(usize, Self), ProtocolError> + where + Self: std::marker::Sized; +} @@ -19,7 +19,7 @@ pub mod session; #[allow(dead_code)] /// Error Types -pub mod error; +mod error; #[allow(unused_variables, dead_code)] #[cfg(feature = "framing")] @@ -30,51 +30,13 @@ pub mod frame; #[cfg(all(feature = "client", feature = "server"))] compile_error!("feature \"client\" and feature \"server\" cannot be enabled at the same time"); -use crate::error::ProtocolError; +pub use crate::error::ProtocolError; /// Traits for Serialization of objects -pub mod serialize { - use crate::error::ProtocolError; - - /// Serialization of types and structs to the quassel byteprotocol - pub trait Serialize { - fn serialize(&self) -> Result<Vec<u8>, ProtocolError>; - } - - /// Serialization of UTF-8 based Strings to the quassel byteprotocol - pub trait SerializeUTF8 { - fn serialize_utf8(&self) -> Result<Vec<u8>, ProtocolError>; - } - - pub trait SerializeVariant { - fn serialize_variant(&self) -> Result<Vec<u8>, ProtocolError>; - } -} +pub mod serialize; /// Traits for parsing objects -pub mod deserialize { - use crate::error::ProtocolError; - - /// Deserialization of types and structs to the quassel byteprotocol - pub trait Deserialize { - fn parse(b: &[u8]) -> Result<(usize, Self), ProtocolError> - where - Self: std::marker::Sized; - } - - /// Deserialization of UTF-8 based Strings to the quassel byteprotocol - pub trait DeserializeUTF8 { - fn parse_utf8(b: &[u8]) -> Result<(usize, Self), ProtocolError> - where - Self: std::marker::Sized; - } - - pub trait DeserializeVariant { - fn parse_variant(b: &[u8]) -> Result<(usize, Self), ProtocolError> - where - Self: std::marker::Sized; - } -} +pub mod deserialize; /// HandshakeSerialize implements the serialization needed during the handhake phase. /// diff --git a/src/message/signalproxy/objects/backlogmanager.rs b/src/message/signalproxy/objects/backlogmanager.rs index 93d065d..dbf4697 100644 --- a/src/message/signalproxy/objects/backlogmanager.rs +++ b/src/message/signalproxy/objects/backlogmanager.rs @@ -53,7 +53,7 @@ use libquassel_derive::{sync, NetworkMap}; -use crate::message::{Class, StatefulSyncableClient, Syncable}; +use crate::message::{Class, Syncable}; use crate::primitive::{BufferId, MessageType, MsgId, VariantList}; /// Receive and Request Backlog @@ -74,10 +74,7 @@ impl BacklogManager { limit: i32, additional: i32, ) { - sync!( - "requestBacklog", - [buffer_id, first, last, limit, additional] - ); + sync!("requestBacklog", [buffer_id, first, last, limit, additional]); } /// Same as `requestBacklog`, but only messages of a certain message `type` @@ -94,15 +91,7 @@ impl BacklogManager { ) { sync!( "requestBacklogFiltered", - [ - buffer_id, - first, - last, - limit, - additional, - msgtype.bits(), - flags - ] + [buffer_id, first, last, limit, additional, msgtype.bits(), flags] ); } @@ -159,7 +148,16 @@ impl BacklogManager { ) { sync!( "receiveBacklogFiltered", - [buffer_id, first, last, limit, additional, msgtype.bits(), flags, messages] + [ + buffer_id, + first, + last, + limit, + additional, + msgtype.bits(), + flags, + messages + ] ); } @@ -172,10 +170,7 @@ impl BacklogManager { additional: i32, messages: VariantList, ) { - sync!( - "receiveBacklogAll", - [first, last, limit, additional, messages] - ); + sync!("receiveBacklogAll", [first, last, limit, additional, messages]); } /// Same as `receiveBacklogFiltered`, but applied to all buffers. @@ -197,10 +192,10 @@ impl BacklogManager { } #[cfg(feature = "client")] -impl StatefulSyncableClient for BacklogManager {} +impl crate::message::StatefulSyncableClient for BacklogManager {} #[cfg(feature = "server")] -impl StatefulSyncableServer for BacklogManager {} +impl crate::message::StatefulSyncableServer for BacklogManager {} impl Syncable for BacklogManager { const CLASS: Class = Class::BacklogManager; diff --git a/src/primitive/bufferid.rs b/src/primitive/bufferid.rs index 4be867d..1735473 100644 --- a/src/primitive/bufferid.rs +++ b/src/primitive/bufferid.rs @@ -4,9 +4,16 @@ pub struct BufferId(pub i32); use crate::{deserialize::*, error::ProtocolError, serialize::*}; +use crate::serialize::UserType; + impl Serialize for BufferId { fn serialize(&self) -> Result<Vec<u8>, ProtocolError> { - self.0.serialize() + let mut res = Vec::new(); + + res.append(&mut Self::NAME.serialize_utf8()?); + res.extend(self.0.serialize()?); + + Ok(res) } } @@ -31,6 +38,10 @@ impl std::ops::Deref for BufferId { } } +impl UserType for BufferId { + const NAME: &str = "BufferId"; +} + #[cfg(test)] mod tests { use super::*; @@ -46,7 +57,7 @@ mod tests { #[test] pub fn bufferid_serialize_test() { let res = BufferId(1).serialize().unwrap(); - let expected_bytes: &[u8] = &[0, 0, 0, 1]; + let expected_bytes: &[u8] = &[0, 0, 0, 8, 66, 117, 102, 102, 101, 114, 73, 100, 0, 0, 0, 1]; assert_eq!(res, expected_bytes); } } diff --git a/src/primitive/bufferinfo.rs b/src/primitive/bufferinfo.rs index 0383bc4..f2f13bf 100644 --- a/src/primitive/bufferinfo.rs +++ b/src/primitive/bufferinfo.rs @@ -3,6 +3,8 @@ use std::vec::Vec; use crate::primitive::BufferId; use crate::{deserialize::*, error::ProtocolError, serialize::*}; +use crate::serialize::UserType; + /// The BufferInfo struct represents a BufferInfo as received in IRC /// /// BufferInfo is, like all other struct based types, serialized sequentially. @@ -22,6 +24,7 @@ impl Serialize for BufferInfo { fn serialize(&self) -> Result<Vec<u8>, ProtocolError> { let mut values: Vec<u8> = Vec::new(); + values.append(&mut Self::NAME.serialize_utf8()?); values.append(&mut BufferId::serialize(&self.id)?); values.append(&mut i32::serialize(&self.network_id)?); values.append(&mut i16::serialize(&(self.buffer_type as i16))?); @@ -55,6 +58,10 @@ impl Deserialize for BufferInfo { } } +impl UserType for BufferInfo { + const NAME: &str = "BufferInfo"; +} + /// The Type of the Buffer #[repr(i16)] #[derive(Copy, Clone, Debug, std::cmp::PartialEq)] @@ -92,7 +99,11 @@ mod tests { assert_eq!( buffer.serialize().unwrap(), - [0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 5, 35, 116, 101, 115, 116] + [ + 0, 0, 0, 10, 66, 117, 102, 102, 101, 114, 73, 110, 102, 111, 0, 0, 0, 8, 66, 117, 102, 102, + 101, 114, 73, 100, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 5, 35, 116, 101, 115, + 116 + ] ) } diff --git a/src/primitive/datetime.rs b/src/primitive/datetime.rs index 303716a..2159af3 100644 --- a/src/primitive/datetime.rs +++ b/src/primitive/datetime.rs @@ -1,4 +1,4 @@ -use crate::{deserialize::*, error::ProtocolError, serialize::*}; +use crate::{deserialize::*, error::ProtocolError, primitive, serialize::*}; use time::{OffsetDateTime, PrimitiveDateTime, UtcOffset}; @@ -18,6 +18,8 @@ use time::{OffsetDateTime, PrimitiveDateTime, UtcOffset}; pub type DateTime = OffsetDateTime; pub use time::{Date, Time}; +use crate::serialize::SerializeVariant; + /// 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)] @@ -111,6 +113,10 @@ impl Deserialize for OffsetDateTime { } } +impl SerializeVariant for OffsetDateTime { + const TYPE: u32 = primitive::QDATETIME; +} + impl Serialize for Date { fn serialize(&self) -> Result<Vec<std::primitive::u8>, ProtocolError> { let mut values: Vec<u8> = Vec::new(); @@ -130,6 +136,10 @@ impl Deserialize for Date { } } +impl SerializeVariant for Date { + const TYPE: u32 = primitive::QDATE; +} + impl Serialize for Time { fn serialize(&self) -> Result<Vec<std::primitive::u8>, ProtocolError> { let mut values: Vec<u8> = Vec::new(); @@ -164,6 +174,10 @@ impl Deserialize for Time { } } +impl SerializeVariant for Time { + const TYPE: u32 = primitive::QTIME; +} + #[test] pub fn datetime_serialize() { let datetime = DateTime::parse( diff --git a/src/primitive/message.rs b/src/primitive/message.rs index 3d6f560..bac3899 100644 --- a/src/primitive/message.rs +++ b/src/primitive/message.rs @@ -6,6 +6,7 @@ use crate::{deserialize::*, serialize::*}; use crate::primitive::{BufferInfo, MsgId}; use super::{Variant, VariantList}; +use crate::serialize::UserType; /// The Message struct represents a Message as received in IRC /// @@ -158,30 +159,10 @@ impl Deserialize for Message { } } -// #[repr(i32)] -// #[derive(Copy, Clone, Debug, std::cmp::PartialEq, FromPrimitive, ToPrimitive)] -// pub enum MessageType { -// None = 0x00000000, -// Plain = 0x00000001, -// Notice = 0x00000002, -// Action = 0x00000004, -// Nick = 0x00000008, -// Mode = 0x00000010, -// Join = 0x00000020, -// Part = 0x00000040, -// Quit = 0x00000080, -// Kick = 0x00000100, -// Kill = 0x00000200, -// Server = 0x00000400, -// Info = 0x00000800, -// Error = 0x00001000, -// DayChange = 0x00002000, -// Topic = 0x00004000, -// NetsplitJoin = 0x00008000, -// NetsplitQuit = 0x00010000, -// Invite = 0x00020000, -// Markerline = 0x00040000, -// } +impl UserType for Message { + const NAME: &str = "Message"; +} + use bitflags::bitflags; bitflags! { @@ -276,12 +257,14 @@ mod tests { assert_eq!( message.serialize().unwrap(), [ - 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 95, 244, 79, 69, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1, - 0, 2, 0, 0, 0, 0, 0, 0, 0, 5, 35, 116, 101, 115, 116, 0, 0, 0, 4, 116, 101, 115, 116, 0, 0, - 0, 6, 98, 108, 97, 98, 108, 97, 0, 0, 0, 9, 116, 101, 115, 116, 32, 117, 115, 101, 114, 0, 0, - 0, 28, 104, 116, 116, 112, 115, 58, 47, 47, 106, 102, 107, 97, 108, 115, 100, 107, 106, 102, - 106, 46, 99, 111, 109, 47, 107, 106, 107, 106, 0, 0, 0, 22, 116, 104, 105, 115, 32, 105, 115, - 32, 97, 32, 116, 101, 115, 116, 32, 109, 101, 115, 115, 97, 103, 101 + 0, 0, 0, 5, 77, 115, 103, 73, 100, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 95, 244, 79, 69, 0, 0, + 0, 1, 0, 0, 0, 0, 10, 66, 117, 102, 102, 101, 114, 73, 110, 102, 111, 0, 0, 0, 8, 66, 117, + 102, 102, 101, 114, 73, 100, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 5, 35, 116, + 101, 115, 116, 0, 0, 0, 4, 116, 101, 115, 116, 0, 0, 0, 6, 98, 108, 97, 98, 108, 97, 0, 0, 0, + 9, 116, 101, 115, 116, 32, 117, 115, 101, 114, 0, 0, 0, 28, 104, 116, 116, 112, 115, 58, 47, + 47, 106, 102, 107, 97, 108, 115, 100, 107, 106, 102, 106, 46, 99, 111, 109, 47, 107, 106, + 107, 106, 0, 0, 0, 22, 116, 104, 105, 115, 32, 105, 115, 32, 97, 32, 116, 101, 115, 116, 32, + 109, 101, 115, 115, 97, 103, 101 ] ) } diff --git a/src/primitive/mod.rs b/src/primitive/mod.rs index 67bb2ac..7e629b0 100644 --- a/src/primitive/mod.rs +++ b/src/primitive/mod.rs @@ -3,6 +3,7 @@ mod bufferinfo; mod datetime; mod message; mod msgid; +mod peerptr; mod signedint; mod string; mod stringlist; @@ -16,6 +17,7 @@ pub use bufferinfo::*; pub use datetime::*; pub use message::*; pub use msgid::*; +pub use peerptr::*; #[allow(unused_imports)] pub use signedint::*; #[allow(unused_imports)] diff --git a/src/primitive/msgid.rs b/src/primitive/msgid.rs index 27608fe..7f3e32f 100644 --- a/src/primitive/msgid.rs +++ b/src/primitive/msgid.rs @@ -8,9 +8,16 @@ pub struct MsgId( use crate::error::ProtocolError; use crate::{deserialize::*, serialize::*}; +use crate::serialize::UserType; + impl Serialize for MsgId { fn serialize(&self) -> Result<Vec<u8>, ProtocolError> { - self.0.serialize() + let mut res = Vec::new(); + + res.append(&mut Self::NAME.serialize_utf8()?); + res.extend(self.0.serialize()?); + + Ok(res) } } @@ -49,6 +56,10 @@ impl std::ops::Deref for MsgId { } } +impl UserType for MsgId { + const NAME: &str = "MsgId"; +} + #[cfg(test)] mod tests { use super::*; @@ -69,9 +80,9 @@ mod tests { pub fn msgid_serialize_test() { let res = MsgId(1).serialize().unwrap(); let expected_bytes: &[u8] = if cfg!(feature = "long-message-id") { - &[0, 0, 0, 0, 0, 0, 0, 1] + &[0, 0, 0, 5, 77, 115, 103, 73, 100, 0, 0, 0, 0, 0, 0, 0, 1] } else { - &[0, 0, 0, 1] + &[0, 0, 0, 5, 77, 115, 103, 73, 100, 0, 0, 0, 1] }; assert_eq!(res, expected_bytes); } diff --git a/src/primitive/peerptr.rs b/src/primitive/peerptr.rs new file mode 100644 index 0000000..f2a3e05 --- /dev/null +++ b/src/primitive/peerptr.rs @@ -0,0 +1,56 @@ +use crate::{ + deserialize::Deserialize, + serialize::{Serialize, SerializeUTF8}, +}; + +use crate::serialize::UserType; + +#[derive(Copy, Clone, Debug, std::cmp::PartialEq)] +#[repr(transparent)] +pub struct PeerPtr(pub i64); + +impl Serialize for PeerPtr { + fn serialize(&self) -> Result<Vec<u8>, crate::error::ProtocolError> { + let mut res = Vec::new(); + + res.append(&mut Self::NAME.serialize_utf8()?); + res.extend(self.0.serialize()?); + + Ok(res) + } +} + +impl Deserialize for PeerPtr { + fn parse(b: &[u8]) -> Result<(usize, Self), crate::error::ProtocolError> { + let (size, value) = i64::parse(b)?; + return Ok((size, PeerPtr(value))); + } +} + +impl UserType for PeerPtr { + const NAME: &str = "PeerPtr"; +} + +#[cfg(test)] +mod tests { + use super::*; + + // #[test] + // pub fn peerptr_parse_test() { + // let test_bytes: &[u8] = &[ + // 0, 0, 0, 7, 80, 101, 101, 114, 80, 116, 114, 0, 0, 0, 0, 0, 0, 0, 1, + // ]; + // let (len, res) = PeerPtr::parse(test_bytes).unwrap(); + // assert_eq!(len, test_bytes.len()); + // assert_eq!(res, PeerPtr(1)); + // } + + #[test] + pub fn peerptr_serialize_test() { + let res = PeerPtr(1).serialize().unwrap(); + let expected_bytes: &[u8] = &[ + 0, 0, 0, 7, 80, 101, 101, 114, 80, 116, 114, 0, 0, 0, 0, 0, 0, 0, 1, + ]; + assert_eq!(res, expected_bytes); + } +} diff --git a/src/primitive/signedint.rs b/src/primitive/signedint.rs index b139685..d8361a3 100644 --- a/src/primitive/signedint.rs +++ b/src/primitive/signedint.rs @@ -4,7 +4,9 @@ use std::io::Cursor; use std::result::Result; use std::vec::Vec; -use crate::{deserialize::*, error::ProtocolError, serialize::*}; +use crate::{deserialize::*, error::ProtocolError, primitive, serialize::*}; + +use crate::serialize::SerializeVariant; impl Serialize for i64 { fn serialize(&self) -> Result<Vec<u8>, ProtocolError> { @@ -19,6 +21,10 @@ impl Deserialize for i64 { } } +impl SerializeVariant for i64 { + const TYPE: u32 = primitive::LONG; +} + impl Serialize for i32 { fn serialize(&self) -> Result<Vec<u8>, ProtocolError> { Ok(Vec::from(self.to_be_bytes())) @@ -32,6 +38,10 @@ impl Deserialize for i32 { } } +impl SerializeVariant for i32 { + const TYPE: u32 = primitive::INT; +} + impl Serialize for i16 { fn serialize(&self) -> Result<Vec<u8>, ProtocolError> { Ok(Vec::from(self.to_be_bytes())) @@ -45,6 +55,10 @@ impl Deserialize for i16 { } } +impl SerializeVariant for i16 { + const TYPE: u32 = primitive::SHORT; +} + impl Serialize for i8 { fn serialize(&self) -> Result<Vec<u8>, ProtocolError> { Ok(Vec::from(self.to_be_bytes())) @@ -57,3 +71,7 @@ impl Deserialize for i8 { return Ok((1, rdr.read_i8()?)); } } + +impl SerializeVariant for i8 { + const TYPE: u32 = primitive::CHAR; +} diff --git a/src/primitive/string.rs b/src/primitive/string.rs index 30bdffa..1d6f0af 100644 --- a/src/primitive/string.rs +++ b/src/primitive/string.rs @@ -5,7 +5,9 @@ use std::vec::Vec; use log::trace; -use crate::{deserialize::*, error::ProtocolError, serialize::*, util}; +use crate::{deserialize::*, error::ProtocolError, primitive, serialize::*, util}; + +use crate::serialize::SerializeVariant; impl Deserialize for char { fn parse(b: &[u8]) -> Result<(usize, Self), ProtocolError> { @@ -25,13 +27,34 @@ impl Serialize for char { } } -/// We Shadow the String type here as we can only use impl on types in our own scope. -/// +impl SerializeVariant for char { + const TYPE: u32 = crate::primitive::QCHAR; +} + /// Strings are serialized as an i32 for the length in bytes, then the chars represented in UTF-16 in bytes. /// /// Strings can only be serialized as UTF-8 null-terminated ByteArrays with (de)serialize_utf8(). impl Serialize for String { fn serialize(&self) -> Result<Vec<u8>, ProtocolError> { + self.as_str().serialize() + } +} + +impl SerializeUTF8 for String { + fn serialize_utf8(&self) -> Result<Vec<u8>, ProtocolError> { + self.as_str().serialize_utf8() + } +} + +impl SerializeVariant for String { + const TYPE: u32 = primitive::QSTRING; +} + +/// Strings are serialized as an i32 for the length in bytes, then the chars represented in UTF-16 in bytes. +/// +/// Strings can only be serialized as UTF-8 null-terminated ByteArrays with (de)serialize_utf8(). +impl Serialize for &str { + fn serialize(&self) -> Result<Vec<u8>, ProtocolError> { let mut res: Vec<u8> = Vec::new(); self.encode_utf16() @@ -42,10 +65,10 @@ impl Serialize for String { } } -impl SerializeUTF8 for String { +impl SerializeUTF8 for &str { fn serialize_utf8(&self) -> Result<Vec<u8>, ProtocolError> { let mut res: Vec<u8> = Vec::new(); - res.extend(self.clone().into_bytes()); + res.extend(self.bytes()); util::prepend_byte_len(&mut res); return Ok(res); } diff --git a/src/primitive/stringlist.rs b/src/primitive/stringlist.rs index 872f5be..f76e95d 100644 --- a/src/primitive/stringlist.rs +++ b/src/primitive/stringlist.rs @@ -7,6 +7,8 @@ use log::trace; use crate::{deserialize::*, error::ProtocolError, serialize::*}; +use crate::serialize::SerializeVariant; + /// StringList are represented as a Vec of Strings /// /// StringLists are serialized as an i32 of the amount of elements and then each element as a String @@ -45,6 +47,10 @@ impl Deserialize for StringList { } } +impl SerializeVariant for StringList { + const TYPE: u32 = crate::primitive::QSTRINGLIST; +} + #[test] pub fn string_list_serialize() { let mut test_list = StringList::new(); diff --git a/src/primitive/unsignedint.rs b/src/primitive/unsignedint.rs index b5d76cd..f0a78f7 100644 --- a/src/primitive/unsignedint.rs +++ b/src/primitive/unsignedint.rs @@ -6,7 +6,9 @@ use std::result::Result; use std::vec::Vec; use crate::error::ProtocolError; -use crate::{deserialize::*, serialize::*}; +use crate::{deserialize::*, primitive, serialize::*}; + +use crate::serialize::SerializeVariant; impl Serialize for bool { fn serialize(&self) -> Result<Vec<u8>, ProtocolError> { @@ -29,6 +31,10 @@ impl Deserialize for bool { } } +impl SerializeVariant for bool { + const TYPE: u32 = primitive::BOOL; +} + impl Serialize for u64 { fn serialize(&self) -> Result<Vec<u8>, ProtocolError> { Ok(Vec::from(self.to_be_bytes())) @@ -42,6 +48,10 @@ impl Deserialize for u64 { } } +impl SerializeVariant for u64 { + const TYPE: u32 = primitive::ULONG; +} + impl Serialize for u32 { fn serialize(&self) -> Result<Vec<u8>, ProtocolError> { Ok(Vec::from(self.to_be_bytes())) @@ -55,6 +65,10 @@ impl Deserialize for u32 { } } +impl SerializeVariant for u32 { + const TYPE: u32 = primitive::UINT; +} + impl Serialize for u16 { fn serialize(&self) -> Result<Vec<u8>, ProtocolError> { Ok(Vec::from(self.to_be_bytes())) @@ -68,6 +82,10 @@ impl Deserialize for u16 { } } +impl SerializeVariant for u16 { + const TYPE: u32 = primitive::USHORT; +} + impl Serialize for u8 { fn serialize(&self) -> Result<Vec<u8>, ProtocolError> { Ok(Vec::from(self.to_be_bytes())) @@ -79,3 +97,7 @@ impl Deserialize for u8 { return Ok((1, b[0])); } } + +impl SerializeVariant for u8 { + const TYPE: u32 = primitive::UCHAR; +} diff --git a/src/primitive/variant.rs b/src/primitive/variant.rs index a7ff8ca..3678ca7 100644 --- a/src/primitive/variant.rs +++ b/src/primitive/variant.rs @@ -4,8 +4,8 @@ use itertools::Itertools; use log::{error, trace}; use crate::error::ProtocolError; -use crate::primitive; use crate::primitive::StringList; +use crate::primitive::{self, PeerPtr}; use crate::{deserialize::*, serialize::*}; use crate::primitive::{BufferId, BufferInfo, Date, DateTime, Message, MsgId, Time, VariantList, VariantMap}; @@ -40,6 +40,7 @@ pub enum Variant { #[from(ignore)] ByteArray(String), StringList(StringList), + PeerPtr(PeerPtr), char(char), bool(bool), u64(u64), @@ -156,133 +157,46 @@ where impl Serialize for Variant { fn serialize(&self) -> Result<Vec<u8>, ProtocolError> { - let unknown: u8 = 0x00; - let mut res: Vec<u8> = Vec::new(); - match self { - Variant::Unknown => { - return Err(ProtocolError::UnknownVariant); - } - Variant::VariantMap(v) => { - res.extend(primitive::QVARIANTMAP.to_be_bytes().iter()); - res.extend(unknown.to_be_bytes().iter()); - res.extend(v.serialize()?.iter()); - } - Variant::VariantList(v) => { - res.extend(primitive::QVARIANTLIST.to_be_bytes().iter()); - res.extend(unknown.to_be_bytes().iter()); - res.extend(v.serialize()?.iter()); - } - Variant::char(v) => { - res.extend(primitive::QCHAR.to_be_bytes().iter()); - res.extend(unknown.to_be_bytes().iter()); - res.extend(v.serialize()?.iter()); - } - Variant::String(v) => { - res.extend(primitive::QSTRING.to_be_bytes().iter()); - res.extend(unknown.to_be_bytes().iter()); - res.extend(v.serialize()?.iter()); - } + Variant::Unknown => Err(ProtocolError::UnknownVariant), + Variant::VariantMap(v) => v.serialize_variant(), + Variant::VariantList(v) => v.serialize_variant(), + Variant::char(v) => v.serialize_variant(), + Variant::String(v) => v.serialize_variant(), Variant::ByteArray(v) => { + let mut res: Vec<u8> = Vec::new(); res.extend(primitive::QBYTEARRAY.to_be_bytes().iter()); - res.extend(unknown.to_be_bytes().iter()); + res.extend(0x00u8.to_be_bytes().iter()); res.extend(v.serialize_utf8()?.iter()); - } - Variant::StringList(v) => { - res.extend(primitive::QSTRINGLIST.to_be_bytes().iter()); - res.extend(unknown.to_be_bytes().iter()); - res.extend(v.serialize()?.iter()); - } - Variant::bool(v) => { - res.extend(primitive::BOOL.to_be_bytes().iter()); - res.extend(unknown.to_be_bytes().iter()); - let i = *v as i8; - res.extend(i.to_be_bytes().iter()); - } - Variant::u64(v) => { - res.extend(primitive::ULONG.to_be_bytes().iter()); - res.extend(unknown.to_be_bytes().iter()); - res.extend(v.to_be_bytes().iter()); - } - Variant::u32(v) => { - res.extend(primitive::UINT.to_be_bytes().iter()); - res.extend(unknown.to_be_bytes().iter()); - res.extend(v.to_be_bytes().iter()); - } - Variant::u16(v) => { - res.extend(primitive::USHORT.to_be_bytes().iter()); - res.extend(unknown.to_be_bytes().iter()); - res.extend(v.to_be_bytes().iter()); - } - Variant::u8(v) => { - res.extend(primitive::UCHAR.to_be_bytes().iter()); - res.extend(unknown.to_be_bytes().iter()); - res.extend(v.to_be_bytes().iter()); - } - Variant::i64(v) => { - res.extend(primitive::LONG.to_be_bytes().iter()); - res.extend(unknown.to_be_bytes().iter()); - res.extend(v.to_be_bytes().iter()); - } - Variant::i32(v) => { - res.extend(primitive::INT.to_be_bytes().iter()); - res.extend(unknown.to_be_bytes().iter()); - res.extend(v.to_be_bytes().iter()); - } - Variant::i16(v) => { - res.extend(primitive::SHORT.to_be_bytes().iter()); - res.extend(unknown.to_be_bytes().iter()); - res.extend(v.to_be_bytes().iter()); - } - Variant::i8(v) => { - res.extend(primitive::CHAR.to_be_bytes().iter()); - res.extend(unknown.to_be_bytes().iter()); - res.extend(v.to_be_bytes().iter()); - } + Ok(res) + } + Variant::StringList(v) => v.serialize_variant(), + Variant::bool(v) => v.serialize_variant(), + Variant::u64(v) => v.serialize_variant(), + Variant::u32(v) => v.serialize_variant(), + Variant::u16(v) => v.serialize_variant(), + Variant::u8(v) => v.serialize_variant(), + Variant::i64(v) => v.serialize_variant(), + Variant::i32(v) => v.serialize_variant(), + Variant::i16(v) => v.serialize_variant(), + Variant::i8(v) => v.serialize_variant(), Variant::UserType(name, bytes) => { + let mut res: Vec<u8> = Vec::new(); res.extend(primitive::USERTYPE.to_be_bytes().iter()); - res.extend(unknown.to_be_bytes().iter()); + res.extend(0x00u8.to_be_bytes().iter()); res.append(&mut name.serialize_utf8()?); res.extend(bytes); - } - Variant::BufferId(v) => { - let bytes = BufferId::serialize(v)?; - let user = Variant::UserType("BufferId".to_string(), bytes); - return Variant::serialize(&user); - } - Variant::BufferInfo(v) => { - let bytes = BufferInfo::serialize(v)?; - let user = Variant::UserType("BufferInfo".to_string(), bytes); - Variant::serialize(&user).unwrap(); - } - Variant::Message(v) => { - let bytes = Message::serialize(v)?; - let user = Variant::UserType("Message".to_string(), bytes); - Variant::serialize(&user).unwrap(); - } - Variant::MsgId(v) => { - let bytes = MsgId::serialize(v)?; - let user = Variant::UserType("MsgId".to_string(), bytes); - return Variant::serialize(&user); - } - Variant::DateTime(v) => { - res.extend(primitive::QDATETIME.to_be_bytes().iter()); - res.extend(unknown.to_be_bytes().iter()); - res.append(&mut v.serialize()?); - } - Variant::Time(v) => { - res.extend(primitive::QTIME.to_be_bytes().iter()); - res.extend(unknown.to_be_bytes().iter()); - res.append(&mut v.serialize()?); - } - Variant::Date(v) => { - res.extend(primitive::QDATE.to_be_bytes().iter()); - res.extend(unknown.to_be_bytes().iter()); - res.append(&mut v.serialize()?); - } + Ok(res) + } + Variant::BufferId(v) => v.serialize_variant(), + Variant::BufferInfo(v) => v.serialize_variant(), + Variant::Message(v) => v.serialize_variant(), + Variant::MsgId(v) => v.serialize_variant(), + Variant::PeerPtr(v) => v.serialize_variant(), + Variant::DateTime(v) => v.serialize_variant(), + Variant::Time(v) => v.serialize_variant(), + Variant::Date(v) => v.serialize_variant(), } - - return Ok(res); } } @@ -297,22 +211,22 @@ impl Deserialize for Variant { let len = 5; match qtype { - primitive::QVARIANTMAP => { + VariantMap::TYPE => { trace!(target: "primitive::Variant", "Parsing Variant: VariantMap"); let (vlen, value) = VariantMap::parse(&b[len..])?; return Ok((len + vlen, Variant::VariantMap(value))); } - primitive::QVARIANTLIST => { + VariantList::TYPE => { trace!(target: "primitive::Variant", "Parsing Variant: VariantList"); let (vlen, value) = VariantList::parse(&b[len..])?; return Ok((len + vlen, Variant::VariantList(value))); } - primitive::QCHAR => { + char::TYPE => { trace!(target: "primitive::Variant", "Parsing Variant: Char"); let (vlen, value) = char::parse(&b[len..])?; return Ok((len + vlen, Variant::char(value))); } - primitive::QSTRING => { + String::TYPE => { trace!(target: "primitive::Variant", "Parsing Variant: String"); let (vlen, value) = String::parse(&b[len..])?; return Ok((len + vlen, Variant::String(value.clone()))); @@ -322,59 +236,59 @@ impl Deserialize for Variant { let (vlen, value) = String::parse_utf8(&b[len..])?; return Ok((len + vlen, Variant::ByteArray(value.clone()))); } - primitive::QSTRINGLIST => { + StringList::TYPE => { trace!(target: "primitive::Variant", "Parsing Variant: StringList"); let (vlen, value) = StringList::parse(&b[len..])?; return Ok((len + vlen, Variant::StringList(value.clone()))); } - primitive::QDATETIME => { + DateTime::TYPE => { trace!(target: "primitive::Variant", "Parsing Variant: DateTime"); let (vlen, value): (usize, DateTime) = Deserialize::parse(&b[len..])?; return Ok((len + vlen, Variant::DateTime(value.clone()))); } - primitive::QDATE => { + Date::TYPE => { trace!(target: "primitive::Variant", "Parsing Variant: Date"); let (vlen, value): (usize, Date) = Deserialize::parse(&b[len..])?; return Ok((len + vlen, Variant::Date(value.clone()))); } - primitive::QTIME => { + Time::TYPE => { trace!(target: "primitive::Variant", "Parsing Variant: Time"); let (vlen, value): (usize, Time) = Deserialize::parse(&b[len..])?; return Ok((len + vlen, Variant::Time(value.clone()))); } - primitive::BOOL => { + bool::TYPE => { let (vlen, value) = bool::parse(&b[len..])?; return Ok((len + vlen, Variant::bool(value))); } - primitive::ULONG => { + u64::TYPE => { let (vlen, value) = u64::parse(&b[len..])?; return Ok((len + vlen, Variant::u64(value))); } - primitive::UINT => { + u32::TYPE => { let (vlen, value) = u32::parse(&b[len..])?; return Ok((len + vlen, Variant::u32(value))); } - primitive::USHORT => { + u16::TYPE => { let (vlen, value) = u16::parse(&b[len..])?; return Ok((len + vlen, Variant::u16(value))); } - primitive::UCHAR => { + u8::TYPE => { let (vlen, value) = u8::parse(&b[len..])?; return Ok((len + vlen, Variant::u8(value))); } - primitive::LONG => { + i64::TYPE => { let (vlen, value) = i64::parse(&b[len..])?; return Ok((len + vlen, Variant::i64(value))); } - primitive::INT => { + i32::TYPE => { let (vlen, value) = i32::parse(&b[len..])?; return Ok((len + vlen, Variant::i32(value))); } - primitive::SHORT => { + i16::TYPE => { let (vlen, value) = i16::parse(&b[len..])?; return Ok((len + vlen, Variant::i16(value))); } - primitive::CHAR => { + i8::TYPE => { let (vlen, value) = i8::parse(&b[len..])?; return Ok((len + vlen, Variant::i8(value))); } @@ -406,11 +320,10 @@ impl Deserialize for Variant { let (vlen, value) = i32::parse(&b[(len + user_type_len)..])?; return Ok((len + user_type_len + vlen, Variant::i32(value))); } - // As i64 - "PeerPtr" => { - trace!(target: "primitive::Variant", "UserType is i64"); - let (vlen, value) = i64::parse(&b[(len + user_type_len)..])?; - return Ok((len + user_type_len + vlen, Variant::i64(value))); + PeerPtr::NAME => { + trace!(target: "primitive::Variant", "UserType is PeerPtr"); + let (vlen, value) = PeerPtr::parse(&b[(len + user_type_len)..])?; + return Ok((len + user_type_len + vlen, Variant::PeerPtr(value))); } "BufferInfo" => { trace!(target: "primitive::Variant", "UserType is BufferInfo"); @@ -604,16 +517,17 @@ mod tests { #[test] pub fn buffer_info_serialize() { - let test_buffer_info = BufferInfo { - id: BufferId(0), - network_id: 0, - buffer_type: primitive::BufferType::Status, - name: "test".to_string(), - }; + let test_buffer_info = Variant::BufferInfo(BufferInfo { + id: BufferId(1), + network_id: 1, + buffer_type: primitive::BufferType::Channel, + name: "#test".to_string(), + }); let bytes = vec![ - 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x4, 0x74, - 0x65, 0x73, 0x74, + 0, 0, 0, 127, 0, 0, 0, 0, 10, 66, 117, 102, 102, 101, 114, 73, 110, 102, 111, 0, 0, 0, 8, 66, + 117, 102, 102, 101, 114, 73, 100, 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 5, 35, 116, + 101, 115, 116, ]; assert_eq!(test_buffer_info.serialize().unwrap(), bytes); } diff --git a/src/primitive/variantlist.rs b/src/primitive/variantlist.rs index 58286e3..ac8cc07 100644 --- a/src/primitive/variantlist.rs +++ b/src/primitive/variantlist.rs @@ -7,6 +7,8 @@ use crate::{deserialize::*, serialize::*}; use crate::primitive::Variant; +use crate::serialize::SerializeVariant; + /// VariantLists are represented as a Vec of Variants. /// /// They are serialized as the amount of entries as a i32 and then a Variant for each entry @@ -45,6 +47,10 @@ impl Deserialize for VariantList { } } +impl SerializeVariant for VariantList { + const TYPE: u32 = crate::primitive::QVARIANTLIST; +} + impl<S> crate::message::NetworkMap for Vec<S> where S: std::convert::TryFrom<Variant> + Into<Variant> + Clone + std::hash::Hash + std::cmp::Eq, diff --git a/src/primitive/variantmap.rs b/src/primitive/variantmap.rs index 3cb30cc..7a847c5 100644 --- a/src/primitive/variantmap.rs +++ b/src/primitive/variantmap.rs @@ -9,6 +9,8 @@ use crate::{deserialize::*, serialize::*}; use crate::primitive::Variant; use crate::util; +use crate::serialize::SerializeVariant; + /// VariantMaps are represented as a HashMap with String as key and Variant as value /// /// They are serialized as the amount of keys as an i32 then for each entry a String and a Variant. @@ -52,3 +54,7 @@ impl Deserialize for VariantMap { return Ok((pos, map)); } } + +impl SerializeVariant for VariantMap { + const TYPE: u32 = crate::primitive::QVARIANTMAP; +} diff --git a/src/serialize.rs b/src/serialize.rs new file mode 100644 index 0000000..52fc2fe --- /dev/null +++ b/src/serialize.rs @@ -0,0 +1,88 @@ +use crate::{error::ProtocolError, primitive}; + +/// Serialization of types and structs to the quassel byteprotocol +pub trait Serialize { + fn serialize(&self) -> Result<Vec<u8>, ProtocolError>; +} + +/// Serialization of UTF-8 based Strings to the quassel byteprotocol +pub trait SerializeUTF8 { + fn serialize_utf8(&self) -> Result<Vec<u8>, ProtocolError>; +} + +/// Sets the usertype name to be used in serialization and deserialization of the types variants. +/// Automaticly implements the [SerializeVariant] trait. +/// +/// Example [Serialize] impl for a `struct NewType(T: Serialize)`: +/// ```rust +/// use libquassel::serialize::{Serialize, SerializeUTF8, UserType}; +/// +/// struct NewType(i64); +/// impl Serialize for NewType { +/// fn serialize(&self) -> Result<Vec<u8>, libquassel::ProtocolError> { +/// let mut res = Vec::new(); +/// +/// res.append(&mut Self::NAME.serialize_utf8()?); +/// res.extend(self.0.serialize()?); +/// +/// Ok(res) +/// } +/// } +/// +/// impl UserType for NewType { +/// const NAME: &str = "NewType"; +/// } +/// ``` +pub trait UserType { + const NAME: &str; +} + +/// Provides a easy default implementation for serializing a type to it's [Variant] given it's QT type id. +/// +/// If the type is a UserType implement only [UserType], SerializeVariant is implemented automaticly. +/// +/// ```rust ignore +/// impl SerializeVariant for VariantList { +/// const TYPE: u32 = primitive::QVARIANTLIST; +/// } +/// ``` +pub trait SerializeVariant { + /// QT Type as defined by the [Primitive Constants] + /// + /// [Primitive Constants]: primitive#constants + const TYPE: u32; + + /// Default implementation that passes the serialization through to [SerializeVariantInner]. + /// [SerializeVariantInner] is automaticly implemented for all types that implement [Serialize] + /// + /// ```rust ignore + /// self.serialize_variant_inner(Self::TYPE) + /// ``` + fn serialize_variant(&self) -> Result<Vec<u8>, ProtocolError> + where + Self: SerializeVariantInner, + { + self.serialize_variant_inner(Self::TYPE) + } +} + +/// Implemented automaticly for all types that implement [Serialize] refer to [SerializeVariant] +pub trait SerializeVariantInner { + fn serialize_variant_inner(&self, t: u32) -> Result<Vec<u8>, ProtocolError>; +} + +impl<T: Serialize> SerializeVariantInner for T { + fn serialize_variant_inner(&self, t: u32) -> Result<Vec<u8>, ProtocolError> { + let mut res: Vec<u8> = Vec::new(); + + res.extend(t.to_be_bytes().iter()); + res.extend(0x00u8.to_be_bytes().iter()); + res.extend(self.serialize()?); + + Ok(res) + } +} + +impl<T: UserType> SerializeVariant for T { + const TYPE: u32 = primitive::USERTYPE; +} |
