1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
|
//! Traits for Serializing and Deserializing types to their byte representations
//!
//! example for a simple type would look like this with the `TYPE` usually fetched from [libquassel::primitive#constants]
//!
//! ```rust
//! use libquassel::{ProtocolError, serialize::*};
//!
//! pub struct Example;
//!
//! impl Serialize for Example {
//! fn serialize(&self) -> Result<Vec<u8>, ProtocolError> {
//! // Serialize here
//! # todo!()
//! }
//! }
//!
//! impl Deserialize for Example {
//! fn parse(b: &[u8]) -> Result<(usize, Self), ProtocolError> {
//! // Deserialize here
//! # todo!()
//! }
//! }
//!
//! impl VariantType for Example {
//! // The QT Type identifier
//! const TYPE: u32 = 0x18;
//! }
//! ```
//!
//! Some types are not serialized directly but are a [UserType]:
//! ```rust
//! use libquassel::{ProtocolError, serialize::*};
//!
//! pub struct Example;
//!
//! impl Serialize for Example {
//! fn serialize(&self) -> Result<Vec<u8>, ProtocolError> {
//! // Serialize here
//! # todo!()
//! }
//! }
//!
//! impl UserType for Example {
//! const NAME: &str = "Example";
//! }
//! ```
//! [UserType]: libquassel::serialize::UserType
use crate::{
error::ProtocolError,
primitive::{self, Variant},
};
/// 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;
}
impl<T: UserType> VariantType for T {
const TYPE: u32 = primitive::USERTYPE;
}
// =============================================
// Serialization
//
/// 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>;
}
/// 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 VariantType {
/// QT Type as defined by the [Primitive Constants]
///
/// [Primitive Constants]: primitive#constants
const TYPE: u32;
}
/// Serialize a Type directly to it's Variant.
///
/// Has a default implementation and is automaticly implemented for all types that
/// have a [VariantType] set and [Serialize] implemented.
pub trait SerializeVariant: VariantType + Serialize {
fn serialize_variant(&self) -> Result<Vec<u8>, ProtocolError> {
let mut res: Vec<u8> = Vec::new();
res.extend(Self::TYPE.to_be_bytes().iter());
res.extend(0x00u8.to_be_bytes().iter());
res.extend(self.serialize()?);
Ok(res)
}
}
impl<T: VariantType + Serialize> SerializeVariant for T {}
// =============================================
// Deserialization
//
/// 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;
}
/// Deserialize a Type for use in the Variant parsing. In opposite to [SerializeVariant] this does not deal
/// with the variant type itself as we have to match onto it genericly before passing it on to per Type
/// functions.
///
/// Still using this gives us automatic implementations and more code reuse
///
/// Has a default implementation and is automaticly implemented for all types that
/// have a [VariantType] set and [Deserialize] implemented.
pub trait DeserializeVariant: VariantType + Deserialize
where
Variant: From<Self>,
Self: Sized,
{
fn parse_variant(b: &[u8], len: usize) -> Result<(usize, Variant), ProtocolError> {
let (vlen, value) = Self::parse(&b[len..])?;
Ok((len + vlen, value.into()))
}
}
impl<T: VariantType + Deserialize> DeserializeVariant for T where Variant: From<T> {}
|