aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/deserialize.rs21
-rw-r--r--src/lib.rs46
-rw-r--r--src/message/signalproxy/objects/backlogmanager.rs37
-rw-r--r--src/primitive/bufferid.rs15
-rw-r--r--src/primitive/bufferinfo.rs13
-rw-r--r--src/primitive/datetime.rs16
-rw-r--r--src/primitive/message.rs43
-rw-r--r--src/primitive/mod.rs2
-rw-r--r--src/primitive/msgid.rs17
-rw-r--r--src/primitive/peerptr.rs56
-rw-r--r--src/primitive/signedint.rs20
-rw-r--r--src/primitive/string.rs33
-rw-r--r--src/primitive/stringlist.rs6
-rw-r--r--src/primitive/unsignedint.rs24
-rw-r--r--src/primitive/variant.rs212
-rw-r--r--src/primitive/variantlist.rs6
-rw-r--r--src/primitive/variantmap.rs6
-rw-r--r--src/serialize.rs88
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;
+}
diff --git a/src/lib.rs b/src/lib.rs
index 64a30cd..a2daaa3 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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;
+}