aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--scratch.rs116
-rw-r--r--src/main.rs20
-rw-r--r--src/net.rs46
-rw-r--r--src/protocol/message/handshake.rs99
-rw-r--r--src/protocol/message/handshake/types.rs92
-rw-r--r--src/protocol/message/mod.rs3
-rw-r--r--src/protocol/mod.rs2
-rw-r--r--src/protocol/primitive/basic.rs270
-rw-r--r--src/protocol/primitive/mod.rs30
-rw-r--r--src/protocol/primitive/variant.rs334
-rw-r--r--src/tests/base_types.rs55
-rw-r--r--src/tests/handshake_types.rs29
-rw-r--r--src/tests/mod.rs8
-rw-r--r--src/tests/variant_types.rs88
-rw-r--r--src/types.rs54
-rw-r--r--src/types/basic.rs149
-rw-r--r--src/types/handshake.rs62
-rw-r--r--src/types/variant.rs298
-rw-r--r--src/util.rs27
-rw-r--r--test.hex0
20 files changed, 1208 insertions, 574 deletions
diff --git a/scratch.rs b/scratch.rs
new file mode 100644
index 0000000..f8a2fb8
--- /dev/null
+++ b/scratch.rs
@@ -0,0 +1,116 @@
+
+// pos: 0
+// pos: 18
+// pos: 23
+// pos: 23
+// pos: 43
+// pos: 51
+// pos: 51
+// pos: 71
+// pos: 76
+// pos: 76
+// pos: 91
+// pos: 125
+// pos: 125
+// pos: 148
+// pos: 156
+// pos: 156
+
+//
+// 0000 00 00 01 30 00 00 00 0a 00 00 00 0a|00|00 00 00 ...0............
+// 0010 16|00 46 00 65 00 61 00 74 00 75 00 72 00 65 00 ..F.e.a.t.u.r.e.
+// 0020 4c 00 69 00 73 00 74|00 00 00 0b|00|00 00 00 01| L.i.s.t.........
+// 0030 00 00 00 2c|00 53 00 79 00 6e 00 63 00 68 00 72 ...,.S.y.n.c.h.r
+// 0040 00 6f 00 6e 00 69 00 7a 00 65 00 64 00 4d 00 61 .o.n.i.z.e.d.M.a
+// 0050 00 72 00 6b 00 65 00 72 00 4c 00 69 00 6e 00 65| .r.k.e.r.L.i.n.e
+// 0060 00 00 00 0a|00|00 00 00 1a|00 43 00 6c 00 69 00 ..........C.l.i.
+// 0070 65 00 6e 00 74 00 56 00 65 00 72 00 73 00 69 00 e.n.t.V.e.r.s.i.
+// 0080 6f 00 6e|00 00 00 0a|00|00 00 00 14|00 52 00 75 o.n..........R.u
+// 0090 00 73 00 74 00 20 00 30 00 2e 00 30 00 2e 00 30| .s.t. .0...0...0
+// 00a0 00 00 00 0a|00|00 00 00 14|00 43 00 6c 00 69 00 ..........C.l.i.
+// 00b0 65 00 6e 00 74 00 44 00 61 00 74 00 65|00 00 00 e.n.t.D.a.t.e...
+// 00c0 0a|00|00 00 00 14|00 31 00 35 00 37 00 39 00 30 .......1.5.7.9.0
+// 00d0 00 30 00 39 00 32 00 31 00 31 00 00 00 0a 00 00 .0.9.2.1.1......
+// 00e0 00 00 10 00 46 00 65 00 61 00 74 00 75 00 72 00 ....F.e.a.t.u.r.
+// 00f0 65 00 73 00 00 00 03 00 00 00 00 00 00 00 00 0a e.s.............
+// 0100 00 00 00 00 0e 00 4d 00 73 00 67 00 54 00 79 00 ......M.s.g.T.y.
+// 0110 70 00 65 00 00 00 0a 00 00 00 00 14 00 43 00 6c p.e..........C.l
+// 0120 00 69 00 65 00 6e 00 74 00 49 00 6e 00 69 00 74 .i.e.n.t.I.n.i.t
+
+// 0000 00 00 04 cc 00 00 00 0a 00 00 00 0a|00|00 00 00 ................
+// 0010 0e|00 4d 00 73 00 67 00 54 00 79 00 70 00 65|00 ..M.s.g.T.y.p.e.
+// 0020 00 00 0a|00|00 00 00 14|00 43 00 6c 00 69 00 65 .........C.l.i.e
+// 0030 00 6e 00 74 00 49 00 6e 00 69 00 74 00 00 00 0a .n.t.I.n.i.t....
+// 0040 00 00 00 00 1a 00 43 00 6c 00 69 00 65 00 6e 00 ......C.l.i.e.n.
+// 0050 74 00 56 00 65 00 72 00 73 00 69 00 6f 00 6e 00 t.V.e.r.s.i.o.n.
+// 0060 00 00 0a 00 00 00 01 06 00 51 00 75 00 61 00 73 .........Q.u.a.s
+// 0070 00 73 00 65 00 6c 00 64 00 72 00 6f 00 69 00 64 .s.e.l.d.r.o.i.d
+// 0080 00 20 00 3c 00 61 00 20 00 68 00 72 00 65 00 66 . .<.a. .h.r.e.f
+// 0090 00 3d 00 22 00 68 00 74 00 74 00 70 00 73 00 3a .=.".h.t.t.p.s.:
+// 00a0 00 2f 00 2f 00 67 00 69 00 74 00 2e 00 6b 00 75 ././.g.i.t...k.u
+// 00b0 00 73 00 63 00 68 00 6b 00 75 00 2e 00 64 00 65 .s.c.h.k.u...d.e
+// 00c0 00 2f 00 6a 00 75 00 73 00 74 00 4a 00 61 00 6e ./.j.u.s.t.J.a.n
+// 00d0 00 6e 00 65 00 2f 00 51 00 75 00 61 00 73 00 73 .n.e./.Q.u.a.s.s
+// 00e0 00 65 00 6c 00 44 00 72 00 6f 00 69 00 64 00 2d .e.l.D.r.o.i.d.-
+// 00f0 00 6e 00 67 00 2f 00 63 00 6f 00 6d 00 6d 00 69 .n.g./.c.o.m.m.i
+// 0100 00 74 00 2f 00 65 00 34 00 62 00 37 00 64 00 65 .t./.e.4.b.7.d.e
+// 0110 00 37 00 39 00 33 00 37 00 37 00 38 00 34 00 65 .7.9.3.7.7.8.4.e
+// 0120 00 32 00 64 00 31 00 31 00 66 00 62 00 32 00 32 .2.d.1.1.f.b.2.2
+// 0130 00 35 00 66 00 39 00 38 00 31 00 62 00 36 00 37 .5.f.9.8.1.b.6.7
+// 0140 00 37 00 39 00 65 00 35 00 36 00 38 00 33 00 32 .7.9.e.5.6.8.3.2
+// 0150 00 34 00 35 00 22 00 3e 00 76 00 31 00 2e 00 32 .4.5.".>.v.1...2
+// 0160 00 2e 00 31 00 30 00 3c 00 2f 00 61 00 3e 00 00 ...1.0.<./.a.>..
+// 0170 00 0a 00 00 00 00 14 00 43 00 6c 00 69 00 65 00 ........C.l.i.e.
+// 0180 6e 00 74 00 44 00 61 00 74 00 65 00 00 00 0a 00 n.t.D.a.t.e.....
+// 0190 00 00 00 14 00 31 00 35 00 36 00 33 00 37 00 33 .....1.5.6.3.7.3
+// 01a0 00 37 00 31 00 34 00 35 00 00 00 0a 00 00 00 00 .7.1.4.5........
+// 01b0 10 00 46 00 65 00 61 00 74 00 75 00 72 00 65 00 ..F.e.a.t.u.r.e.
+// 01c0 73 00 00 00 03 00 00 00 fe ff 00 00 00 0a 00 00 s...............
+// 01d0 00 00 16 00 46 00 65 00 61 00 74 00 75 00 72 00 ....F.e.a.t.u.r.
+// 01e0 65 00 4c 00 69 00 73 00 74|00 00 00 0b|00|00 00 e.L.i.s.t.......
+// 01f0 00 15|00 00 00 2c 00 53 00 79 00 6e 00 63 00 68 .....,.S.y.n.c.h
+// 0200 00 72 00 6f 00 6e 00 69 00 7a 00 65 00 64 00 4d .r.o.n.i.z.e.d.M
+// 0210 00 61 00 72 00 6b 00 65 00 72 00 4c 00 69 00 6e .a.r.k.e.r.L.i.n
+// 0220 00 65 00 00 00 24 00 53 00 61 00 73 00 6c 00 41 .e...$.S.a.s.l.A
+// 0230 00 75 00 74 00 68 00 65 00 6e 00 74 00 69 00 63 .u.t.h.e.n.t.i.c
+// 0240 00 61 00 74 00 69 00 6f 00 6e 00 00 00 18 00 53 .a.t.i.o.n.....S
+// 0250 00 61 00 73 00 6c 00 45 00 78 00 74 00 65 00 72 .a.s.l.E.x.t.e.r
+// 0260 00 6e 00 61 00 6c 00 00 00 28 00 48 00 69 00 64 .n.a.l...(.H.i.d
+// 0270 00 65 00 49 00 6e 00 61 00 63 00 74 00 69 00 76 .e.I.n.a.c.t.i.v
+// 0280 00 65 00 4e 00 65 00 74 00 77 00 6f 00 72 00 6b .e.N.e.t.w.o.r.k
+// 0290 00 73 00 00 00 1c 00 50 00 61 00 73 00 73 00 77 .s.....P.a.s.s.w
+// 02a0 00 6f 00 72 00 64 00 43 00 68 00 61 00 6e 00 67 .o.r.d.C.h.a.n.g
+// 02b0 00 65 00 00 00 1c 00 43 00 61 00 70 00 4e 00 65 .e.....C.a.p.N.e
+// 02c0 00 67 00 6f 00 74 00 69 00 61 00 74 00 69 00 6f .g.o.t.i.a.t.i.o
+// 02d0 00 6e 00 00 00 1e 00 56 00 65 00 72 00 69 00 66 .n.....V.e.r.i.f
+// 02e0 00 79 00 53 00 65 00 72 00 76 00 65 00 72 00 53 .y.S.e.r.v.e.r.S
+// 02f0 00 53 00 4c 00 00 00 20 00 43 00 75 00 73 00 74 .S.L... .C.u.s.t
+// 0300 00 6f 00 6d 00 52 00 61 00 74 00 65 00 4c 00 69 .o.m.R.a.t.e.L.i
+// 0310 00 6d 00 69 00 74 00 73 00 00 00 26 00 41 00 77 .m.i.t.s...&.A.w
+// 0320 00 61 00 79 00 46 00 6f 00 72 00 6d 00 61 00 74 .a.y.F.o.r.m.a.t
+// 0330 00 54 00 69 00 6d 00 65 00 73 00 74 00 61 00 6d .T.i.m.e.s.t.a.m
+// 0340 00 70 00 00 00 1c 00 41 00 75 00 74 00 68 00 65 .p.....A.u.t.h.e
+// 0350 00 6e 00 74 00 69 00 63 00 61 00 74 00 6f 00 72 .n.t.i.c.a.t.o.r
+// 0360 00 73 00 00 00 24 00 42 00 75 00 66 00 66 00 65 .s...$.B.u.f.f.e
+// 0370 00 72 00 41 00 63 00 74 00 69 00 76 00 69 00 74 .r.A.c.t.i.v.i.t
+// 0380 00 79 00 53 00 79 00 6e 00 63 00 00 00 24 00 43 .y.S.y.n.c...$.C
+// 0390 00 6f 00 72 00 65 00 53 00 69 00 64 00 65 00 48 .o.r.e.S.i.d.e.H
+// 03a0 00 69 00 67 00 68 00 6c 00 69 00 67 00 68 00 74 .i.g.h.l.i.g.h.t
+// 03b0 00 73 00 00 00 1c 00 53 00 65 00 6e 00 64 00 65 .s.....S.e.n.d.e
+// 03c0 00 72 00 50 00 72 00 65 00 66 00 69 00 78 00 65 .r.P.r.e.f.i.x.e
+// 03d0 00 73 00 00 00 20 00 52 00 65 00 6d 00 6f 00 74 .s... .R.e.m.o.t
+// 03e0 00 65 00 44 00 69 00 73 00 63 00 6f 00 6e 00 6e .e.D.i.s.c.o.n.n
+// 03f0 00 65 00 63 00 74 00 00 00 20 00 45 00 78 00 74 .e.c.t... .E.x.t
+// 0400 00 65 00 6e 00 64 00 65 00 64 00 46 00 65 00 61 .e.n.d.e.d.F.e.a
+// 0410 00 74 00 75 00 72 00 65 00 73 00 00 00 10 00 4c .t.u.r.e.s.....L
+// 0420 00 6f 00 6e 00 67 00 54 00 69 00 6d 00 65 00 00 .o.n.g.T.i.m.e..
+// 0430 00 18 00 52 00 69 00 63 00 68 00 4d 00 65 00 73 ...R.i.c.h.M.e.s
+// 0440 00 73 00 61 00 67 00 65 00 73 00 00 00 22 00 42 .s.a.g.e.s...".B
+// 0450 00 61 00 63 00 6b 00 6c 00 6f 00 67 00 46 00 69 .a.c.k.l.o.g.F.i
+// 0460 00 6c 00 74 00 65 00 72 00 54 00 79 00 70 00 65 .l.t.e.r.T.y.p.e
+// 0470 00 00 00 1e 00 45 00 63 00 64 00 73 00 61 00 43 .....E.c.d.s.a.C
+// 0480 00 65 00 72 00 74 00 66 00 70 00 4b 00 65 00 79 .e.r.t.f.p.K.e.y
+// 0490 00 73 00 00 00 1a 00 4c 00 6f 00 6e 00 67 00 4d .s.....L.o.n.g.M
+// 04a0 00 65 00 73 00 73 00 61 00 67 00 65 00 49 00 64 .e.s.s.a.g.e.I.d
+// 04b0 00 00 00 1c 00 53 00 79 00 6e 00 63 00 65 00 64 .....S.y.n.c.e.d
+// 04c0 00 43 00 6f 00 72 00 65 00 49 00 6e 00 66 00 6f .C.o.r.e.I.n.f.o
diff --git a/src/main.rs b/src/main.rs
index cd45c87..78a4e2b 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -1,11 +1,17 @@
mod consts;
mod net;
-mod types;
+
+mod protocol;
#[macro_use]
mod util;
+#[cfg(test)]
+mod tests;
+
//use util::Hex;
+use protocol::primitive::{String, StringList};
+use protocol::message::{ClientInit};
fn main() -> std::io::Result<()> {
let mut server = net::connect(
@@ -15,11 +21,13 @@ fn main() -> std::io::Result<()> {
false,
)?;
- let client = types::handshake::ClientInit {
- client_version: String::from("Rust 0.0.0"),
- build_date: String::from("today"),
- client_features: 0x00000000,
- feature_list: types::StringList::new()
+ let mut features = StringList::new();
+ features.push("SynchronizedMarkerLine".to_string());
+ let client = ClientInit {
+ client_version:String::from("Rust 0.0.0"),
+ client_date: String::from("1579009211"),
+ feature_list: features,
+ client_features: 0,
};
server.login("audron", "audron", client);
diff --git a/src/net.rs b/src/net.rs
index 3d56437..5dd9552 100644
--- a/src/net.rs
+++ b/src/net.rs
@@ -8,8 +8,8 @@ use std::vec::Vec;
extern crate log;
// use log::{info, warn, debug};
-use super::types;
-use super::types::Serialize;
+
+use crate::protocol::message;
pub struct Client {
tcp_stream: TcpStream,
@@ -20,12 +20,30 @@ pub struct Client {
}
impl Client {
- pub fn login(&mut self, user: &'static str, pass: &'static str, client: types::handshake::ClientInit) {
- self.tcp_stream.write(&client.serialize()).unwrap();
+ pub fn login(&mut self, user: &'static str, pass: &'static str, client: message::ClientInit) {
+ use crate::protocol::message::handshake::{HandshakeDeserialize, HandshakeSerialize, HandshakeQRead, VariantMap};
+ use crate::protocol::message::handshake::{ClientInit, ClientInitAck};
+ use std::convert::TryInto;
+
+ let sclientinit = &client.serialize();
+ let len: u32 = sclientinit.len().try_into().unwrap();
+// self.tcp_stream.write(&len.to_be_bytes()).unwrap();
+ self.tcp_stream.write(sclientinit).unwrap();
+
+ let mut buf: Vec<u8> = [0; 2048].to_vec();
+ VariantMap::read(&mut self.tcp_stream, &mut buf);
+
+ // println!("{:?}", buf);
+ let res = ClientInitAck::parse(&buf);
+ println!("{:?}", res)
}
}
pub fn connect(address: &'static str, port: u32, tls: bool, compression: bool) -> Result<Client, Error> {
+ use crate::protocol::primitive::serialize::Serialize;
+ use crate::protocol::primitive::deserialize::Deserialize;
+ use crate::protocol::primitive::qread::QRead;
+
//let mut s = BufWriter::new(TcpStream::connect(format!("{}:{}", address, port)).unwrap());
let mut s = TcpStream::connect(format!("{}:{}", address, port)).unwrap();
@@ -45,9 +63,27 @@ pub fn connect(address: &'static str, port: u32, tls: bool, compression: bool) -
init.extend(proto.to_be_bytes().iter());
s.write(&init)?;
+ #[derive(Debug)]
+ struct ConnAck {
+ flags: u8,
+ extra: i16,
+ version: i8
+ }
+
+ impl Deserialize for ConnAck {
+ fn parse(b: &[u8]) -> (usize, Self) {
+ let (flen, flags) = u8::parse(b);
+ let (elen, extra) = i16::parse(&b[flen..]);
+ let (vlen, version) = i8::parse(&b[(flen+elen)..]);
+
+ return (flen+elen+vlen, Self {flags, extra, version});
+ }
+ }
+
let mut buf = [0; 4];
s.read_exact(&mut buf)?;
- println!("Received: {:?}", buf);
+ let (_, val) = ConnAck::parse(&buf);
+ println!("Received: {:?}", val);
let server: Client = Client {
tcp_stream: s,
diff --git a/src/protocol/message/handshake.rs b/src/protocol/message/handshake.rs
new file mode 100644
index 0000000..918c424
--- /dev/null
+++ b/src/protocol/message/handshake.rs
@@ -0,0 +1,99 @@
+use crate::protocol::primitive::{String, StringList, Variant, VariantList};
+use crate::protocol::primitive::{serialize, deserialize, qread};
+
+mod types;
+pub use types::{VariantMap, HandshakeDeserialize, HandshakeSerialize, HandshakeQRead};
+
+use crate::match_variant;
+#[derive(Debug)]
+pub struct ClientInit {
+ pub client_version: String, // Version of the client
+ pub client_date: String, // Build date of the client
+ pub client_features: u32,
+ pub feature_list: StringList // List of supported extended features
+}
+
+impl HandshakeSerialize for ClientInit {
+ fn serialize(&self) -> Vec<u8> {
+ let mut values: VariantMap = VariantMap::with_capacity(5);
+ values.insert("MsgType".to_string(), Variant::String("ClientInit".to_string()));
+ values.insert("ClientVersion".to_string(), Variant::String(self.client_version.clone()));
+ values.insert("ClientDate".to_string(), Variant::String(self.client_date.clone()));
+ values.insert("Features".to_string(), Variant::u32(self.client_features));
+ values.insert("FeatureList".to_string(), Variant::StringList(self.feature_list.clone()));
+ return HandshakeSerialize::serialize(&values);
+ }
+}
+
+impl HandshakeDeserialize for ClientInit {
+ fn parse(b: &[u8]) -> (usize, Self) {
+ let (len, values): (usize, VariantMap) = HandshakeDeserialize::parse(b);
+
+ return (len, Self {
+ client_version: match_variant!(values, Variant::String, "ClientVersion"),
+ client_date: match_variant!(values, Variant::String, "ClientDate"),
+ feature_list: match_variant!(values, Variant::StringList, "FeatureList"),
+ client_features: match_variant!(values, Variant::u32, "Features")
+ });
+ }
+}
+
+#[derive(Debug)]
+pub struct ClientInitReject {
+ pub error_string: String
+}
+
+impl HandshakeSerialize for ClientInitReject {
+ fn serialize(&self) -> Vec<u8> {
+ let mut values: VariantMap = VariantMap::with_capacity(2);
+ values.insert("MsgProtocol::Primitive".to_string(), Variant::String("ClientInitReject".to_string()));
+ values.insert("ErrorString".to_string(), Variant::String(self.error_string.clone()));
+ return HandshakeSerialize::serialize(&values);
+ }
+}
+
+impl HandshakeDeserialize for ClientInitReject {
+ fn parse(b: &[u8]) -> (usize, Self) {
+ let (len, values): (usize, VariantMap) = HandshakeDeserialize::parse(b);
+
+ return (len, Self {
+ error_string: match_variant!(values, Variant::String, "ErrorString")
+ });
+ }
+}
+
+#[derive(Debug)]
+pub struct ClientInitAck {
+ pub core_features: u32, // Flags of supported legacy features
+ pub core_configured: bool, // If the core has already been configured
+ pub backend_info: VariantList, // List of VariantMaps of info on available backends
+ pub authenticator_info: VariantList, // List of VariantMaps of info on available authenticators
+ pub feature_list: StringList, // List of supported extended features
+}
+
+impl HandshakeSerialize for ClientInitAck {
+ fn serialize(&self) -> Vec<u8> {
+ let mut values: VariantMap = VariantMap::with_capacity(2);
+ values.insert("MsgProtocol::Primitive".to_string(), Variant::String("ClientInitAck".to_string()));
+ values.insert("CoreFeatures".to_string(), Variant::u32(self.core_features));
+ values.insert("CoreConfigured".to_string(), Variant::bool(self.core_configured));
+ values.insert("BackendInfo".to_string(), Variant::VariantList(self.backend_info.clone()));
+ values.insert("AuthenticatorInfo".to_string(), Variant::VariantList(self.authenticator_info.clone()));
+ values.insert("FeatureList".to_string(), Variant::StringList(self.feature_list.clone()));
+ return HandshakeSerialize::serialize(&values);
+ }
+}
+
+impl HandshakeDeserialize for ClientInitAck {
+ fn parse(b: &[u8]) -> (usize, Self) {
+ let (len, values): (usize, VariantMap) = HandshakeDeserialize::parse(b);
+
+ return (len, Self {
+ core_features: match_variant!(values, Variant::u32, "CoreFeatures"),
+ core_configured: match_variant!(values, Variant::bool, "CoreConfigured"),
+ backend_info: match_variant!(values, Variant::VariantList, "BackendInfo"),
+ authenticator_info: match_variant!(values, Variant::VariantList, "AuthenticatorInfo"),
+ feature_list: match_variant!(values, Variant::StringList, "FeatureList")
+ });
+ }
+}
diff --git a/src/protocol/message/handshake/types.rs b/src/protocol/message/handshake/types.rs
new file mode 100644
index 0000000..d6ea346
--- /dev/null
+++ b/src/protocol/message/handshake/types.rs
@@ -0,0 +1,92 @@
+use std::io::Read;
+use std::vec::Vec;
+use std::net::TcpStream;
+use std::convert::TryInto;
+use std::collections::HashMap;
+
+use crate::util;
+use crate::protocol::primitive::{String, Variant};
+use crate::protocol::primitive::serialize::Serialize;
+use crate::protocol::primitive::deserialize::Deserialize;
+use crate::protocol::primitive::qread::QRead;
+
+pub trait HandshakeSerialize {
+ fn serialize(&self) -> Vec<u8>;
+}
+
+pub trait HandshakeDeserialize {
+ fn parse(b: &[u8]) -> (usize, Self);
+}
+
+pub trait HandshakeQRead {
+ fn read(stream: &mut std::net::TcpStream, buf: &mut [u8]) -> usize;
+}
+
+
+pub type VariantMap = HashMap<String, Variant>;
+
+impl HandshakeSerialize for VariantMap {
+ fn serialize<'a>(&'a self) -> Vec<u8> {
+ let mut res: Vec<u8> = Vec::new();
+
+ for (k, v) in self {
+ let key = Variant::String(k.clone());
+ res.extend(key.serialize());
+ res.extend(v.serialize());
+ }
+
+ util::insert_bytes(0, &mut res, &mut [0, 0, 0, 10]);
+
+ let len: i32 = res.len().try_into().unwrap();
+ util::insert_bytes(0, &mut res, &mut ((len + 4).to_be_bytes()));
+ println!("len: {:?}", len + 4);
+
+ return res;
+ }
+}
+
+impl HandshakeDeserialize for VariantMap {
+ fn parse(b: &[u8]) -> (usize, Self) {
+ let (_, len) = i32::parse(&b[0..4]);
+
+ let mut pos: usize = 8;
+ let mut map = VariantMap::new();
+ let ulen: usize = len as usize;
+ loop {
+ if (pos) >= ulen { break; }
+ let (nlen, name) = Variant::parse(&b[(pos)..]);
+ pos += nlen;
+
+ let (vlen, value) = Variant::parse(&b[(pos)..]);
+ pos += vlen;
+
+ if let Variant::StringUTF8(x) = name {
+ map.insert(x, value);
+ }
+ }
+
+ return (pos, map);
+ }
+}
+
+impl HandshakeQRead for VariantMap {
+ fn read(mut s: &mut TcpStream, b: &mut [u8]) -> usize {
+ s.read(&mut b[0..4]).unwrap();
+ let (_, len) = i32::parse(&b[0..4]);
+ println!("len: {:?}", len);
+
+ // Read the 00 00 00 0a VariantType bytes and discard
+ let mut tbuf = [0; 4];
+ s.read(&mut tbuf).unwrap();
+
+ let mut pos = 4;
+ let len: usize = len as usize;
+ loop {
+ if pos >= (len - 4) { break; }
+ pos += Variant::read(&mut s, &mut b[pos..]);
+ pos += Variant::read(&mut s, &mut b[(pos+4..)]);
+ }
+
+ return pos;
+ }
+}
diff --git a/src/protocol/message/mod.rs b/src/protocol/message/mod.rs
new file mode 100644
index 0000000..3b6d1a8
--- /dev/null
+++ b/src/protocol/message/mod.rs
@@ -0,0 +1,3 @@
+pub mod handshake;
+
+pub use handshake::*;
diff --git a/src/protocol/mod.rs b/src/protocol/mod.rs
new file mode 100644
index 0000000..044a28b
--- /dev/null
+++ b/src/protocol/mod.rs
@@ -0,0 +1,2 @@
+pub mod message;
+pub mod primitive;
diff --git a/src/protocol/primitive/basic.rs b/src/protocol/primitive/basic.rs
new file mode 100644
index 0000000..100da20
--- /dev/null
+++ b/src/protocol/primitive/basic.rs
@@ -0,0 +1,270 @@
+#[allow(dead_code)]
+pub const VOID: u32 = 0x00000000;
+pub const BOOL: u32 = 0x00000001;
+pub const QCHAR: u32 = 0x00000007;
+
+pub const QVARIANT: u32 = 0x00000090;
+pub const QVARIANTMAP: u32 = 0x00000008;
+pub const QVARIANTLIST: u32 = 0x00000009;
+
+pub const QSTRING: u32 = 0x0000000a;
+pub const QSTRINGLIST: u32 = 0x0000000b;
+pub const QBYTEARRAY: u32 = 0x0000000c;
+
+pub const QTIME: u32 = 0x0000000f;
+pub const QDATETIME: u32 = 0x00000010;
+pub const USERTYPE: u32 = 0x0000007f;
+
+
+// Basic types
+pub const LONG: u32 = 0x00000081; // int64_t
+pub const INT: u32 = 0x00000002; // int32_t
+pub const SHORT: u32 = 0x00000082; // int16_t
+pub const CHAR: u32 = 0x00000083; // int8_t
+
+pub const ULONG: u32 = 0x00000084; // uint64_t
+pub const UINT: u32 = 0x00000003; // uint32_t
+pub const USHORT: u32 = 0x00000085; // uint16_t
+pub const UCHAR: u32 = 0x00000086; // uint8_t
+
+extern crate byteorder;
+use std::io::Cursor;
+use byteorder::{ByteOrder, BigEndian, ReadBytesExt};
+
+use std::io::Read;
+use std::vec::Vec;
+use std::net::TcpStream;
+use std::convert::TryInto;
+
+use crate::util;
+use crate::protocol::primitive::{deserialize, serialize, qread};
+
+impl deserialize::Deserialize for bool {
+ fn parse(b: &[u8]) -> (usize, Self) {
+ if b[0] == 0 { return (1, false) } else { return (1, true) };
+ }
+}
+
+impl qread::QRead for bool {
+ fn read(s: &mut TcpStream, b: &mut [u8]) -> usize {
+ s.read(&mut [b[0]]).unwrap()
+ }
+}
+
+impl deserialize::Deserialize for u64 {
+ fn parse(b: &[u8]) -> (usize, Self) {
+ return (8, BigEndian::read_u64(b));
+ }
+}
+
+impl qread::QRead for u64 {
+ fn read(s: &mut TcpStream, b: &mut [u8]) -> usize {
+ s.read(&mut b[0..8]).unwrap()
+ }
+}
+
+impl deserialize::Deserialize for u32 {
+ fn parse(b: &[u8]) -> (usize, Self) {
+ // self = &rdr.read_u32::<BigEndian>().unwrap()
+ return (4, BigEndian::read_u32(b));
+ }
+}
+
+impl qread::QRead for u32 {
+ fn read(s: &mut TcpStream, b: &mut [u8]) -> usize {
+ s.read(&mut b[0..4]).unwrap()
+ }
+}
+
+impl deserialize::Deserialize for u16 {
+ fn parse(b: &[u8]) -> (usize, Self) {
+ return (2, BigEndian::read_u16(b));
+ }
+}
+
+impl qread::QRead for u16 {
+ fn read(s: &mut TcpStream, b: &mut [u8]) -> usize {
+ s.read(&mut b[0..2]).unwrap()
+ }
+}
+
+impl deserialize::Deserialize for u8 {
+ fn parse(b: &[u8]) -> (usize, Self) {
+ return (1, b[0]);
+ }
+}
+
+impl qread::QRead for u8 {
+ fn read(s: &mut TcpStream, b: &mut [u8]) -> usize {
+ s.read(&mut [b[0]]).unwrap()
+ }
+}
+
+impl deserialize::Deserialize for i64 {
+ fn parse(b: &[u8]) -> (usize, Self) {
+ return (8, BigEndian::read_i64(b));
+ }
+}
+
+impl qread::QRead for i64 {
+ fn read(s: &mut TcpStream, b: &mut [u8]) -> usize {
+ s.read(&mut b[0..8]).unwrap()
+ }
+}
+
+impl deserialize::Deserialize for i32 {
+ fn parse(b: &[u8]) -> (usize, Self) {
+ let mut rdr = Cursor::new(&b[0..4]);
+ return (4, rdr.read_i32::<BigEndian>().unwrap());
+ }
+}
+
+impl qread::QRead for i32 {
+ fn read(s: &mut TcpStream, b: &mut [u8]) -> usize {
+ s.read(&mut b[0..4]).unwrap()
+ }
+}
+
+impl deserialize::Deserialize for i16 {
+ fn parse(b: &[u8]) -> (usize, Self) {
+ return (2, BigEndian::read_i16(b));
+ }
+}
+
+impl qread::QRead for i16 {
+ fn read(s: &mut TcpStream, b: &mut [u8]) -> usize {
+ s.read(&mut b[0..2]).unwrap()
+ }
+}
+
+impl deserialize::Deserialize for i8 {
+ fn parse(b: &[u8]) -> (usize, Self) {
+ return (1, b[0].try_into().unwrap());
+ }
+}
+
+impl qread::QRead for i8 {
+ fn read(s: &mut TcpStream, b: &mut [u8]) -> usize {
+ s.read(&mut [b[0]]).unwrap()
+ }
+}
+
+
+
+pub type String = std::string::String;
+impl serialize::Serialize for String {
+ fn serialize(&self) -> Vec<u8> {
+ let mut res: Vec<u8> = Vec::new();
+
+ let utf16: Vec<u16> = self.encode_utf16().collect();
+ for i in utf16 {
+ res.extend(i.to_be_bytes().iter());
+ }
+
+ util::prepend_byte_len(&mut res);
+ return res;
+ }
+}
+
+impl serialize::SerializeUTF8 for String {
+ fn serialize_utf8(&self) -> Vec<u8> {
+ let mut res: Vec<u8> = Vec::new();
+ res.extend(self.clone().into_bytes());
+ util::prepend_byte_len(&mut res);
+ return res;
+ }
+}
+
+impl deserialize::Deserialize for String {
+ fn parse(b: &[u8]) -> (usize, Self) {
+ let (_, len) = i32::parse(&b[0..4]);
+
+ let ulen = len as usize;
+ let mut pos: usize = 4;
+ let mut chars: Vec<u16> = Vec::new();
+ loop {
+ if pos >= (ulen + 4) { break; }
+ let (slen, uchar) = u16::parse(&b[pos..(pos+2)]);
+ chars.push(uchar);
+ pos += slen;
+ }
+
+ let res: String = String::from_utf16(&chars).unwrap();
+ return (pos, res);
+ }
+}
+
+impl deserialize::DeserializeUTF8 for String {
+ fn parse_utf8(b: &[u8]) -> (usize, Self) {
+ use crate::protocol::primitive::deserialize::Deserialize;
+ let (_, len) = i32::parse(&b[0..4]);
+
+ let ulen = len as usize;
+
+ let res: String = String::from_utf8(b[4..(ulen+4)].to_vec()).unwrap();
+ return (ulen + 4, res);
+ }
+}
+
+impl qread::QRead for String {
+ fn read(s: &mut TcpStream, b: &mut [u8]) -> usize {
+ use crate::protocol::primitive::deserialize::Deserialize;
+
+ s.read(&mut b[0..4]).unwrap();
+ let (_, len) = i32::parse(&b[0..4]);
+
+ let ulen = len as usize;
+ s.read(&mut b[4..(4+ulen)]).unwrap();
+
+ return 4 + ulen;
+ }
+}
+
+pub type StringList = Vec<String>;
+impl serialize::Serialize for StringList {
+ fn serialize(&self) -> Vec<u8> {
+ let len: i32 = self.len().try_into().unwrap();
+ let mut res: Vec<u8> = Vec::new();
+
+ res.extend(len.to_be_bytes().iter());
+ for x in self {
+ res.extend(x.serialize());
+ }
+
+ return res;
+ }
+}
+
+impl deserialize::Deserialize for StringList {
+ fn parse(b: &[u8]) -> (usize, Self) {
+ let (_, len) = i32::parse(&b[0..4]);
+ let mut res: StringList = StringList::new();
+
+ let mut pos = 4;
+ if len > 0 {
+ for _ in 0..len {
+ let (lpos, val) = String::parse(&b[pos..]);
+ pos += lpos;
+ res.push(val);
+ }
+ }
+
+ return (pos, res);
+ }
+}
+
+impl qread::QRead for StringList {
+ fn read(s: &mut TcpStream, b: &mut [u8]) -> usize {
+ use crate::protocol::primitive::deserialize::Deserialize;
+
+ s.read(&mut b[0..4]).unwrap();
+ let (_, len) = i32::parse(&b[0..4]);
+
+ let mut pos: usize = 0;
+ for _ in 0..len {
+ pos += String::read(s, &mut b[pos..]);
+ }
+
+ return 4 + pos;
+ }
+}
diff --git a/src/protocol/primitive/mod.rs b/src/protocol/primitive/mod.rs
new file mode 100644
index 0000000..03c62bc
--- /dev/null
+++ b/src/protocol/primitive/mod.rs
@@ -0,0 +1,30 @@
+#[allow(dead_code)]
+pub mod basic;
+pub mod variant;
+
+pub use basic::*;
+pub use variant::*;
+
+pub mod serialize {
+ pub trait Serialize {
+ fn serialize(&self) -> Vec<u8>;
+ }
+ pub trait SerializeUTF8 {
+ fn serialize_utf8(&self) -> Vec<u8>;
+ }
+}
+
+pub mod deserialize {
+ pub trait Deserialize {
+ fn parse(b: &[u8]) -> (usize, Self);
+ }
+ pub trait DeserializeUTF8 {
+ fn parse_utf8(b: &[u8]) -> (usize, Self);
+ }
+}
+
+pub mod qread {
+ pub trait QRead {
+ fn read(stream: &mut std::net::TcpStream, buf: &mut [u8]) -> usize;
+ }
+}
diff --git a/src/protocol/primitive/variant.rs b/src/protocol/primitive/variant.rs
new file mode 100644
index 0000000..f868e9f
--- /dev/null
+++ b/src/protocol/primitive/variant.rs
@@ -0,0 +1,334 @@
+use std::vec::Vec;
+use std::convert::TryInto;
+use std::collections::HashMap;
+
+use std::io::Read;
+use std::net::TcpStream;
+
+use crate::util;
+use crate::protocol::primitive::serialize::{Serialize, SerializeUTF8};
+use crate::protocol::primitive::deserialize::{Deserialize, DeserializeUTF8};
+use crate::protocol::primitive::qread::QRead;
+use crate::protocol::primitive::{String,StringList};
+use crate::protocol::primitive;
+
+pub type VariantMap = HashMap<String, Variant>;
+
+impl Serialize for VariantMap {
+ fn serialize<'a>(&'a self) -> Vec<u8> {
+ let mut res: Vec<u8> = Vec::new();
+
+ for (k, v) in self {
+ res.extend(k.serialize());
+ res.extend(v.serialize());
+ }
+
+ let len: i32 = self.len().try_into().unwrap();
+ util::insert_bytes(0, &mut res, &mut len.to_be_bytes());
+
+ return res;
+ }
+}
+
+impl Deserialize for VariantMap {
+ fn parse(b: &[u8]) -> (usize, Self) {
+ let (_, len) = i32::parse(&b[0..4]);
+ println!("len: {:?}", len);
+
+ let mut pos = 4;
+ let mut map = VariantMap::new();
+ for _ in 0..len {
+ println!("pos: {:?}", pos);
+ let (nlen, name) = String::parse(&b[(pos)..]);
+ pos += nlen;
+ println!("pos: {:?}", pos);
+
+ let (vlen, value) = Variant::parse(&b[(pos)..]);
+ pos += vlen;
+ println!("pos: {:?}", pos);
+
+ map.insert(name, value);
+ }
+
+ return (pos, map);
+ }
+}
+
+impl QRead for VariantMap {
+ fn read(mut s: &mut TcpStream, b: &mut [u8]) -> usize {
+ s.read(&mut b[0..4]).unwrap();
+
+
+ let (_, len) = i32::parse(&b[0..4]);
+
+ let mut pos = 4;
+ for _ in 0..len {
+ pos += String::read(&mut s, &mut b[pos..]);
+ pos += Variant::read(&mut s, &mut b[(pos+3..)]);
+ }
+
+ return pos;
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////
+pub type VariantList = Vec<Variant>;
+
+impl Serialize for VariantList {
+ fn serialize(&self) -> Vec<u8> {
+ let len: i32 = self.len().try_into().unwrap();
+ let mut res: Vec<u8> = Vec::new();
+
+ res.extend(len.to_be_bytes().iter());
+ for v in self {
+ res.extend(v.serialize().iter());
+ }
+
+ return res;
+ }
+}
+
+impl Deserialize for VariantList {
+ fn parse(b: &[u8]) -> (usize, Self) {
+ let (_, len) = i32::parse(&b[0..4]);
+
+ let mut res: VariantList = VariantList::new();
+ let mut pos: usize = 4;
+ for _ in 0..len {
+ let (vlen, val) = Variant::parse(&b[pos..]);
+ res.push(val);
+ pos += vlen;
+ }
+
+ return (pos, res);
+ }
+}
+
+impl QRead for VariantList {
+ fn read(mut s: &mut TcpStream, b: &mut [u8]) -> usize {
+ s.read(&mut b[0..4]).unwrap();
+
+ let (_, len) = i32::parse(&b[0..4]);
+
+ let mut pos = 4;
+ for _ in 0..len {
+ pos += Variant::read(&mut s, &mut b[(pos+3..)]);
+ }
+
+ return pos;
+ }
+}
+
+/////////////////////////////////////////////////////////////////////////
+#[allow(non_camel_case_types, dead_code)]
+#[derive(Clone, Debug, std::cmp::PartialEq)]
+pub enum Variant {
+ Unknown,
+ VariantMap(VariantMap),
+ VariantList(VariantList),
+ String(String),
+ StringUTF8(String),
+ StringList(StringList),
+ bool(bool),
+ u64(u64),
+ u32(u32),
+ u16(u16),
+ u8(u8),
+ i64(i64),
+ i32(i32),
+ i16(i16),
+ i8(i8),
+}
+
+impl Serialize for Variant {
+ fn serialize(&self) -> Vec<u8> {
+ let unknown: u8 = 0x00;
+ let mut res: Vec<u8> = Vec::new();
+
+ match self {
+ Variant::Unknown => {
+ return res;
+ },
+ 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::String(v) => {
+ res.extend(primitive::QSTRING.to_be_bytes().iter());
+ res.extend(unknown.to_be_bytes().iter());
+ res.extend(v.serialize().iter());
+ },
+ Variant::StringUTF8(v) => {
+ res.extend(primitive::QBYTEARRAY.to_be_bytes().iter());
+ res.extend(unknown.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());
+ },
+ }
+
+ return res
+ }
+}
+
+impl Deserialize for Variant {
+ fn parse(b: &[u8]) -> (usize, Self) {
+ let (_, qtype) = i32::parse(&b[0..4]);
+ let qtype = qtype as u32;
+
+ #[allow(unused_variables)]
+ let unknown: u8 = b[4];
+
+ let len = 5;
+ match qtype {
+ primitive::QVARIANTMAP => {
+ let (vlen, value) = VariantMap::parse(&b[len..]);
+ return (len+vlen, Variant::VariantMap(value));
+ },
+ primitive::QVARIANTLIST => {
+ let (vlen, value) = VariantList::parse(&b[len..]);
+ return (len+vlen, Variant::VariantList(value));
+ },
+ primitive::QSTRING => {
+ let (vlen, value) = String::parse(&b[len..]);
+ return (len+vlen, Variant::String(value.clone()));
+ },
+ primitive::QBYTEARRAY => {
+ let (vlen, value) = String::parse_utf8(&b[len..]);
+ return (len+vlen, Variant::StringUTF8(value.clone()));
+ },
+ primitive::QSTRINGLIST => {
+ let (vlen, value) = StringList::parse(&b[len..]);
+ return (len+vlen, Variant::StringList(value.clone()));
+ },
+ primitive::BOOL => {
+ let (vlen, value) = bool::parse(&b[len..]);
+ return (len+vlen, Variant::bool(value));
+ },
+ primitive::ULONG => {
+ let (vlen, value) = u64::parse(&b[len..]);
+ return (len+vlen, Variant::u64(value));
+ },
+ primitive::UINT => {
+ let (vlen, value) = u32::parse(&b[len..]);
+ return (len+vlen, Variant::u32(value));
+ },
+ primitive::USHORT => {
+ let (vlen, value) = u16::parse(&b[len..]);
+ return (len+vlen, Variant::u16(value));
+ },
+ primitive::UCHAR => {
+ let (vlen, value) = u8::parse(&b[len..]);
+ return (len+vlen, Variant::u8(value));
+ },
+ primitive::LONG => {
+ let (vlen, value) = i64::parse(&b[len..]);
+ return (len+vlen, Variant::i64(value));
+ },
+ primitive::INT => {
+ let (vlen, value) = i32::parse(&b[len..]);
+ return (len+vlen, Variant::i32(value));
+ },
+ primitive::SHORT => {
+ let (vlen, value) = i16::parse(&b[len..]);
+ return (len+vlen, Variant::i16(value));
+ },
+ primitive::CHAR => {
+ let (vlen, value) = i8::parse(&b[len..]);
+ return (len+vlen, Variant::i8(value));
+ },
+ _ => {
+ return (0, Variant::Unknown);
+ }
+ }
+ }
+}
+
+impl QRead for Variant {
+ fn read(s: &mut TcpStream, b: &mut [u8]) -> usize {
+
+ s.read(&mut b[0..4]).unwrap();
+ let (_, qtype) = i32::parse(&b[0..4]);
+ let qtype = qtype as u32;
+
+ s.read(&mut [b[4]]).unwrap();
+ #[allow(unused_variables)]
+ let unknown: u8 = b[4];
+
+ let mut len = 5;
+ match qtype {
+ primitive::QVARIANTMAP => len += VariantMap::read(s, &mut b[5..]),
+ primitive::QVARIANTLIST => len += VariantList::read(s, &mut b[5..]),
+ primitive::QSTRING => len += String::read(s, &mut b[5..]),
+ primitive::QBYTEARRAY => len += String::read(s, &mut b[5..]),
+ primitive::QSTRINGLIST => len += StringList::read(s, &mut b[5..]),
+ primitive::BOOL => len += bool::read(s, &mut b[5..]),
+ primitive::ULONG => len += u64::read(s, &mut b[5..]),
+ primitive::UINT => len += u32::read(s, &mut b[5..]),
+ primitive::USHORT => len += u16::read(s, &mut b[5..]),
+ primitive::UCHAR => len += u8::read(s, &mut b[5..]),
+ primitive::LONG => len += i64::read(s, &mut b[5..]),
+ primitive::INT => len += i32::read(s, &mut b[5..]),
+ primitive::SHORT => len += i16::read(s, &mut b[5..]),
+ primitive::CHAR => len += i8::read(s, &mut b[5..]),
+ _ => return len
+ }
+
+ return len;
+ }
+}
diff --git a/src/tests/base_types.rs b/src/tests/base_types.rs
new file mode 100644
index 0000000..a35f243
--- /dev/null
+++ b/src/tests/base_types.rs
@@ -0,0 +1,55 @@
+use crate::protocol::primitive::serialize::{Serialize, SerializeUTF8};
+use crate::protocol::primitive::deserialize::{Deserialize, DeserializeUTF8};
+
+use crate::protocol::primitive::*;
+
+#[test]
+pub fn serialize_string() {
+ let test_string: String = String::from("Configured");
+
+ assert_eq!(test_string.serialize(), [0, 0, 0, 20, 0, 67, 0, 111, 0, 110, 0, 102, 0, 105, 0, 103, 0, 117, 0, 114, 0, 101, 0, 100]);
+}
+
+#[test]
+pub fn serialize_string_utf8() {
+ let test_string: String = String::from("Configured");
+
+ assert_eq!(test_string.serialize_utf8(), [0, 0, 0, 10, 67, 111, 110, 102, 105, 103, 117, 114, 101, 100]);
+}
+
+#[test]
+pub fn deserialize_string() {
+ let test_bytes: &[u8] = &[0, 0, 0, 20, 0, 67, 0, 111, 0, 110, 0, 102, 0, 105, 0, 103, 0, 117, 0, 114, 0, 101, 0, 100, 0, 0, 0, 1];
+ let (len, res) = String::parse(test_bytes);
+ assert_eq!(res, "Configured");
+ assert_eq!(len, 24);
+}
+
+#[test]
+pub fn deserialize_string_utf8() {
+ let test_bytes: &[u8] = &[0, 0, 0, 10, 67, 111, 110, 102, 105, 103, 117, 114, 101, 100, 0, 0, 0, 1];
+ let (len, res) = String::parse_utf8(test_bytes);
+ assert_eq!(len, 14);
+ assert_eq!(res, "Configured");
+}
+
+#[test]
+pub fn serialize_string_list() {
+ let mut test_list = StringList::new();
+ test_list.push("Configured".to_string());
+ assert_eq!(
+ test_list.serialize(),
+ [0, 0, 0, 1, 0, 0, 0, 20, 0, 67, 0, 111, 0, 110, 0, 102, 0, 105, 0, 103, 0, 117, 0, 114, 0, 101, 0, 100]
+ )
+}
+
+#[test]
+pub fn deserialize_string_list() {
+ let test_bytes: &[u8] = &[0, 0, 0, 24, 0, 0, 0, 20, 0, 67, 0, 111, 0, 110, 0, 102, 0, 105, 0, 103, 0, 117, 0, 114, 0, 101, 0, 100, 0, 0, 0, 1];
+ let mut test_list = StringList::new();
+ test_list.push("Configured".to_string());
+ println!("aaaaa");
+ let (len, res) = StringList::parse(test_bytes);
+ assert_eq!(len, 28);
+ assert_eq!(test_list, res);
+}
diff --git a/src/tests/handshake_types.rs b/src/tests/handshake_types.rs
new file mode 100644
index 0000000..99fc1ed
--- /dev/null
+++ b/src/tests/handshake_types.rs
@@ -0,0 +1,29 @@
+use crate::protocol::message::handshake::{VariantMap, HandshakeSerialize, HandshakeDeserialize};
+use crate::protocol::primitive::{Variant};
+
+#[test]
+pub fn serialize_variantmap() {
+ let mut test_variantmap = VariantMap::new();
+ test_variantmap.insert("Configured".to_string(), Variant::bool(true));
+ let bytes = [0, 0, 0, 43, 0, 0, 0, 10, 0, 0, 0, 10, 0,
+ 0, 0, 0, 20, 0, 67, 0, 111, 0, 110, 0, 102, 0, 105, 0, 103, 0, 117, 0, 114, 0, 101, 0, 100,
+ 0, 0, 0, 1, 0, 1].to_vec();
+ assert_eq!(
+ test_variantmap.serialize(),
+ bytes
+ );
+}
+
+// #[test]
+// pub fn deserialize_variantmap() {
+// let test_bytes: &[u8] = &[0, 0, 0, 43, 0, 0, 0, 10, 0, 0, 0, 10, 0,
+// 0, 0, 0, 20, 0, 67, 0, 111, 0, 110, 0, 102, 0, 105, 0, 103, 0, 117, 0, 114, 0, 101, 0, 100,
+// 0, 0, 0, 1, 0, 1, 0, 0, 0, 1];
+// let mut test_variantmap = VariantMap::new();
+// test_variantmap.insert("Configured".to_string(), Variant::bool(true));
+//
+// let (len, res) = VariantMap::parse(test_bytes);
+//
+// assert_eq!(len, 43);
+// assert_eq!(res, test_variantmap);
+// }
diff --git a/src/tests/mod.rs b/src/tests/mod.rs
new file mode 100644
index 0000000..873046b
--- /dev/null
+++ b/src/tests/mod.rs
@@ -0,0 +1,8 @@
+#[cfg(test)]
+pub mod handshake_types;
+pub mod variant_types;
+pub mod base_types;
+
+use handshake_types::*;
+use variant_types::*;
+use base_types::*;
diff --git a/src/tests/variant_types.rs b/src/tests/variant_types.rs
new file mode 100644
index 0000000..8c4dedc
--- /dev/null
+++ b/src/tests/variant_types.rs
@@ -0,0 +1,88 @@
+use crate::protocol::primitive::serialize::Serialize;
+use crate::protocol::primitive::deserialize::Deserialize;
+
+use crate::protocol::primitive::{Variant, VariantList, VariantMap};
+
+#[test]
+pub fn serialize_variant_bool() {
+ let test_variant_true = Variant::bool(true);
+ let test_variant_false = Variant::bool(false);
+ assert_eq!(
+ test_variant_true.serialize(),
+ [0, 0, 0, 1, 0, 1]
+ );
+ assert_eq!(
+ test_variant_false.serialize(),
+ [0, 0, 0, 1, 0, 0]
+ );
+}
+
+#[test]
+pub fn deserialize_variant_bool() {
+ let test_bytes: &[u8] = &[0, 0, 0, 1, 0, 1, 0, 0, 0, 1];
+ let (len, res) = Variant::parse(test_bytes);
+ assert_eq!(len, 6);
+ assert_eq!(res, Variant::bool(true));
+}
+
+#[test]
+pub fn serialize_variantlist() {
+ let mut test_variantlist = VariantList::new();
+ test_variantlist.push(Variant::bool(true));
+ assert_eq!(
+ test_variantlist.serialize(),
+ [0, 0, 0, 1, 0, 0, 0, 1, 0, 1]
+ );
+}
+
+#[test]
+pub fn deserialize_variantlist() {
+ let test_bytes: &[u8] = &[0, 0, 0, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1];
+ let (len, res) = VariantList::parse(test_bytes);
+ let mut test_variantlist = VariantList::new();
+ test_variantlist.push(Variant::bool(true));
+ assert_eq!(len, 10);
+ assert_eq!(res, test_variantlist);
+}
+
+#[test]
+pub fn serialize_variantmap() {
+ let mut test_variantmap = VariantMap::new();
+ test_variantmap.insert("Configured".to_string(), Variant::bool(true));
+ let bytes = [0, 0, 0, 1,
+ 0, 0, 0, 20, 0, 67, 0, 111, 0, 110, 0, 102, 0, 105, 0, 103, 0, 117, 0, 114, 0, 101, 0, 100,
+ 0, 0, 0, 1, 0, 1].to_vec();
+ assert_eq!(
+ test_variantmap.serialize(),
+ bytes
+ );
+}
+
+#[test]
+pub fn deserialize_variantmap() {
+ let test_bytes: &[u8] = &[0, 0, 0, 1,
+ 0, 0, 0, 20, 0, 67, 0, 111, 0, 110, 0, 102, 0, 105, 0, 103, 0, 117, 0, 114, 0, 101, 0, 100,
+ 0, 0, 0, 1, 0, 1, 0, 0, 0, 1];
+ let (len, res) = VariantMap::parse(test_bytes);
+ let mut test_variantmap = VariantMap::new();
+ test_variantmap.insert("Configured".to_string(), Variant::bool(true));
+ assert_eq!(len, 34);
+ assert_eq!(res, test_variantmap);
+}
+
+//
+// 0000 00 00 00 00 00 00 00 00 00 00 00 00 08 00 45 00 ..............E.
+// 0010 00 e2 36 3d 40 00 40 06 05 d7 7f 00 00 01 7f 00 ..6=@.@.........
+// 0020 00 01 10 92 c0 dc e8 73 50 fe 2f 68 6d 9e 80 18 .......sP./hm...
+// 0030 02 00 fe d6 00 00 01 01 08 0a 5f 0a 31 00 5f 0a .........._.1._.
+// 0040 31 00 00 00 00 aa 00 00 00 0a 00 00 00 0c 00 00 1...............
+// 0050 00 00 0a 43 6f 6e 66 69 67 75 72 65 64 00 00 00 ...Configured...
+// 0060 01 00 01 00 00 00 0c 00 00 00 00 0c 43 6f 72 65 ............Core
+// 0070 46 65 61 74 75 72 65 73 00 00 00 03 00 00 00 fe Features........
+// 0080 ff 00 00 00 0c 00 00 00 00 0c 4c 6f 67 69 6e 45 ..........LoginE
+// 0090 6e 61 62 6c 65 64 00 00 00 01 00 01 00 00 00 0c nabled..........
+// 00a0 00 00 00 00 07 4d 73 67 54 79 70 65 00 00 00 0a .....MsgType....
+// 00b0 00 00 00 00 1a 00 43 00 6c 00 69 00 65 00 6e 00 ......C.l.i.e.n.
+// 00c0 74 00 49 00 6e 00 69 00 74 00 41 00 63 00 6b 00 t.I.n.i.t.A.c.k.
+// 00d0 00 00 0c 00 00 00 00 0f 53 74 6f 72 61 67 65 42 ........StorageB
+// 00e0 61 63 6b 65 6e 64 73 00 00 00 09 00 00 00 00 00 ackends.........
diff --git a/src/types.rs b/src/types.rs
deleted file mode 100644
index 1c22ce6..0000000
--- a/src/types.rs
+++ /dev/null
@@ -1,54 +0,0 @@
-#[allow(dead_code)]
-pub mod basic;
-pub mod variant;
-pub mod handshake;
-
-pub use basic::*;
-
-pub trait Serialize {
- fn serialize(&self) -> Vec<u8>;
-}
-
-pub trait Deserialize {
- fn parse(&mut self, b: &[u8]) -> usize;
-}
-
-
-// 78 da 6c 54 6d 6b d3 50 14 7e 44 41 d1 09
-// 7e 50 10 19 a3 14 91 89 2f db fa b2 75 32 05 cd
-// 2c 16 3b 19 6b d9 f7 98 dc a6 61 69 12 93 db ce
-// f8 6f fc a3 ea 73 ce 4d ca 64 23 dc e4 bc 3c e7
-// 39 6f b7 05 ee fc 06 70 9f 67 03 22 78 49 6c 52
-// 7b ec 5b 53 9b f1 18 7b e8 e3 00 03 7d 1f a0 8b
-// 1e e5 1a ff d0 e1 cf 4d 51 c6 59 5a 87 dc da c0
-// 0a bb 78 cb c0 1e de 20 47 01 83 16 b6 af d9 5e
-// 51 1b 60 9f be 08 31 2c ed 47 f0 a9 cd d5 3b c3
-// 7b b4 29 5b 3e 39 4a bc c3 0e 1f 87 9c 63 89 ef
-// 64 0b 90 61 41 eb 0f ea 3e 31 25 e3 92 1b 74 87
-// 5b 68 ec 0e 9b e8 31 73 87 0c 7b 08 99 7f 40 3d
-// 60 be 0e e5 be 7a a4 49 83 43 3e 5d ea e2 e9 10
-// d9 a7 d4 65 17 33 fa 76 a9 1f f2 2b 83 69 e3 c3
-// 35 ce 23 e6 f1 69 7f d9 8c ea c1 d0 f8 76 59 98
-// 71 5c 5a 51 c5 f6 84 e7 35 26 a8 90 b2 00 69 3b
-// a3 14 e3 17 89 43 9c 90 a0 c0 05 e5 02 63 5a 53
-// c8 52 9e 13 2f ad 25 f8 c8 26 65 14 86 1e 4b 7f
-// 40 bb 7c 85 03 78 ba c6 7d c6 4f da 85 25 a5 25
-// a1 6f 1b 5f 88 0b 69 1b a9 2d d0 b8 15 f5 6f 3c
-// 16 97 e4 90 cc 25 b1 9b 38 ad 47 e9 ac 21 3c e6
-// f4 19 17 69 3d 9b d4 7d 2e 48 22 23 22 84 e9 6a
-// 1d 5b 38 d7 dc 31 c7 56 b1 26 91 57 fa 9e f0 19
-// 13 d1 22 c3 92 fc 56 97 74 a6 d1 46 3b 76 0b 93
-// 2a 5e b0 db 4b 7a 2a 0c b5 8a 85 a2 a6 8a 31 1a
-// eb 53 ca b5 9e 9b e7 22 51 a5 ce ef 13 fd 33 5d
-// 62 41 6c d3 bb 64 aa d6 bb 10 9c a7 31 86 36 37
-// 2b 99 59 44 de a4 fe da 7a 3e 13 cd 14 2a df 69
-// 7d 75 63 ce dc a8 bf c5 8e 0c 6b cb b4 ab 63 7a
-// 4a bd 8e a9 ee 53 b2 0b a6 d9 91 e3 09 d9 a5 d1
-// aa 97 ca 27 3c 8f 38 91 4c a7 de 74 2d 3b 3e d3
-// fe e6 bc 2b 46 77 e4 eb 56 04 df 66 9f b2 d9 0b
-// d6 9b d1 3a 24 32 a9 ef c1 94 5d e6 ca b0 c5 cc
-// 01 f3 49 a4 a7 3e cb ea 73 7c a5 5c 29 cf b3 75
-// de ff 73 8c 18 e5 ba 77 13 33 7a 33 dc c4 e4 56
-// cd 28 d7 57 ff 5e 7d f5 85 ee 36 cf 9f bf 8d e7
-// ee 49 19 4d ab fc ca 9f 8d a7 e3 75 ab 1b e9 8f
-// c1 fe 13
diff --git a/src/types/basic.rs b/src/types/basic.rs
deleted file mode 100644
index dc5e8d5..0000000
--- a/src/types/basic.rs
+++ /dev/null
@@ -1,149 +0,0 @@
-#[allow(dead_code)]
-pub const VOID: u32 = 0x00000000;
-pub const BOOL: u32 = 0x00000001;
-pub const QCHAR: u32 = 0x00000007;
-
-pub const QVARIANT: u32 = 0x00000090;
-pub const QVARIANTMAP: u32 = 0x00000008;
-pub const QVARIANTLIST: u32 = 0x00000009;
-
-pub const QSTRING: u32 = 0x0000000a;
-pub const QSTRINGLIST: u32 = 0x0000000b;
-pub const QBYTEARRAY: u32 = 0x0000000c;
-
-pub const QTIME: u32 = 0x0000000f;
-pub const QDATETIME: u32 = 0x00000010;
-pub const USERTYPE: u32 = 0x0000007f;
-
-
-// Basic types
-pub const LONG: u32 = 0x00000081; // int64_t
-pub const INT: u32 = 0x00000002; // int32_t
-pub const SHORT: u32 = 0x00000082; // int16_t
-pub const CHAR: u32 = 0x00000083; // int8_t
-
-pub const ULONG: u32 = 0x00000084; // uint64_t
-pub const UINT: u32 = 0x00000003; // uint32_t
-pub const USHORT: u32 = 0x00000085; // uint16_t
-pub const UCHAR: u32 = 0x00000086; // uint8_t
-
-extern crate byteorder;
-use byteorder::{ByteOrder, BigEndian};
-
-use std::vec::Vec;
-use std::convert::TryInto;
-
-use crate::types;
-
-impl types::Deserialize for bool {
- fn parse(&mut self, b: &[u8]) -> usize {
- if b[0] == 0 { *self = false } else { *self = true };
- return 1;
- }
-}
-
-impl types::Deserialize for u64 {
- fn parse(&mut self, b: &[u8]) -> usize {
- *self = BigEndian::read_u64(b);
- return 8;
- }
-}
-impl types::Deserialize for u32 {
- fn parse(&mut self, b: &[u8]) -> usize {
- // self = &rdr.read_u32::<BigEndian>().unwrap()
- *self = BigEndian::read_u32(b);
- return 4;
- }
-}
-impl types::Deserialize for u16 {
- fn parse(&mut self, b: &[u8]) -> usize {
- *self = BigEndian::read_u16(b);
- return 2;
- }
-}
-impl types::Deserialize for u8 {
- fn parse(&mut self, b: &[u8]) -> usize {
- *self = b[0];
- return 1;
- }
-}
-
-impl types::Deserialize for i64 {
- fn parse(&mut self, b: &[u8]) -> usize {
- *self = BigEndian::read_i64(b);
- return 8;
- }
-}
-impl types::Deserialize for i32 {
- fn parse(&mut self, b: &[u8]) -> usize {
- *self = BigEndian::read_i32(b);
- return 4;
- }
-}
-impl types::Deserialize for i16 {
- fn parse(&mut self, b: &[u8]) -> usize {
- *self = BigEndian::read_i16(b);
- return 2;
- }
-}
-impl types::Deserialize for i8 {
- fn parse(&mut self, b: &[u8]) -> usize {
- *self = b[0].try_into().unwrap();
- return 1;
- }
-}
-
-
-pub type String = std::string::String;
-impl types::Serialize for String {
- fn serialize(&self) -> Vec<u8> {
- let len: i32 = self.len().try_into().unwrap();
- let mut res: Vec<u8> = Vec::new();
-
- res.extend(len.to_be_bytes().iter());
- res.extend(self.parse::<u16>().unwrap().to_be_bytes().iter());
-
- return res;
- }
-}
-
-impl types::Deserialize for String {
- fn parse(&mut self, b: &[u8]) -> usize {
- let mut len: i32 = 0;
- len.parse(&b[0..4]);
- let ulen: usize = len as usize;
- *self = BigEndian::read_u16(&b[(5)..(5+ulen)]).to_string();
- b.len()
- }
-}
-
-pub type StringList = Vec<String>;
-impl types::Serialize for StringList {
- fn serialize(&self) -> Vec<u8> {
- let len: i32 = self.len().try_into().unwrap();
- let mut res: Vec<u8> = Vec::new();
-
- res.extend(len.to_be_bytes().iter());
- for x in self {
- res.extend(x.parse::<u16>().unwrap().to_be_bytes().iter());
- }
-
- return res;
- }
-}
-
-impl types::Deserialize for StringList {
- fn parse(&mut self, b: &[u8]) -> usize {
- let len: i32 = self.len().try_into().unwrap();
- let res: StringList = StringList::new();
-
- let mut pos: usize = 0;
- for _ in 0..len {
- let mut val: String = String::new();
- pos = pos + val.parse(&b[pos..]);
- }
-
- *self = res;
- return pos;
- }
-}
diff --git a/src/types/handshake.rs b/src/types/handshake.rs
deleted file mode 100644
index cd79d29..0000000
--- a/src/types/handshake.rs
+++ /dev/null
@@ -1,62 +0,0 @@
-use crate::types::{Serialize, Deserialize};
-use crate::types::variant::{Variant, VariantMap, VariantList};
-use crate::types::basic::{String, StringList};
-
-pub struct ClientInit {
- pub client_version: String, // Version of the client
- pub build_date: String, // Build date of the client
- pub client_features: u32, // Flags of supported legacy features
- pub feature_list: StringList // List of supported extended features
-}
-
-impl Serialize for ClientInit {
- fn serialize(&self) -> Vec<u8> {
- let mut values: VariantMap = VariantMap::with_capacity(5);
- values.insert("MsgType".to_string(), Variant::String("ClientInit".to_string()));
- values.insert("ClientVersion".to_string(), Variant::String(self.client_version.clone()));
- values.insert("BuildDate".to_string(), Variant::String(self.build_date.clone()));
- values.insert("ClientFeatures".to_string(), Variant::u32(self.client_features));
- values.insert("FeatureList".to_string(), Variant::StringList(self.feature_list.clone()));
- return values.serialize();
- }
-}
-
-// impl Deserialize for ClientInit {
-// fn deserialize(&mut self, b: &[u8]) {
-//
-// }
-// }
-
-pub struct ClientInitReject {
- pub error_string: String
-}
-
-impl Serialize for ClientInitReject {
- fn serialize(&self) -> Vec<u8> {
- let mut values: VariantMap = VariantMap::with_capacity(2);
- values.insert("MsgTypes".to_string(), Variant::String("ClientInitReject".to_string()));
- values.insert("ErrorString".to_string(), Variant::String(self.error_string.clone()));
- return values.serialize();
- }
-}
-
-pub struct ClientInitAck {
- pub core_features: u32, // Flags of supported legacy features
- pub core_configured: bool, // If the core has already been configured
- pub backend_info: VariantList, // List of VariantMaps of info on available backends
- pub authenticator_info: VariantList, // List of VariantMaps of info on available authenticators
- pub feature_list: StringList, // List of supported extended features
-}
-
-impl Serialize for ClientInitAck {
- fn serialize(&self) -> Vec<u8> {
- let mut values: VariantMap = VariantMap::with_capacity(2);
- values.insert("MsgTypes".to_string(), Variant::String("ClientInitAck".to_string()));
- values.insert("CoreFeatures".to_string(), Variant::u32(self.core_features));
- values.insert("CoreConfigured".to_string(), Variant::bool(self.core_configured));
- values.insert("BackendInfo".to_string(), Variant::VariantList(self.backend_info.clone()));
- values.insert("AuthenticatorInfo".to_string(), Variant::VariantList(self.authenticator_info.clone()));
- values.insert("FeatureList".to_string(), Variant::StringList(self.feature_list.clone()));
- return values.serialize();
- }
-}
diff --git a/src/types/variant.rs b/src/types/variant.rs
deleted file mode 100644
index 59c287f..0000000
--- a/src/types/variant.rs
+++ /dev/null
@@ -1,298 +0,0 @@
-use std::vec::Vec;
-use std::convert::TryInto;
-use std::collections::HashMap;
-
-use crate::types::{Serialize, Deserialize};
-use crate::types::basic;
-use crate::types::basic::*;
-use crate::types::basic::{String,StringList};
-
-pub type VariantMap = HashMap<String, Variant>;
-impl Serialize for VariantMap {
- fn serialize<'a>(&'a self) -> Vec<u8> {
- let len: i32 = self.len().try_into().unwrap();
- let mut res: Vec<u8> = Vec::new();
-
- res.extend(len.to_be_bytes().iter());
- for (k, v) in self {
- res.extend(k.serialize().iter());
- res.extend(v.serialize().iter());
- }
-
- return res;
- }
-}
-
-impl Deserialize for VariantMap {
- fn parse(&mut self, b: &[u8]) -> usize {
- let mut len: i32 = 0;
- len.parse(&b[0..3]);
-
- let mut pos = 4;
- let map = VariantMap::new();
- for _ in 0..len {
- let mut name: String = String::new();
- name.parse(&b[(pos)..(pos+2)]);
-
- let mut value: Variant = Variant::Unknown;
- let res = value.parse(&b[(pos+3)..]);
-
- pos = pos + 2 + res;
- }
-
- *self = map;
- return pos;
- }
-}
-
-pub type VariantList = Vec<Variant>;
-impl Serialize for VariantList {
- fn serialize(&self) -> Vec<u8> {
- let len: i32 = self.len().try_into().unwrap();
- let mut res: Vec<u8> = Vec::new();
-
- res.extend(len.to_be_bytes().iter());
- for v in self {
- res.extend(v.serialize().iter());
- }
-
- return res;
- }
-}
-
-impl Deserialize for VariantList {
- fn parse(&mut self, b: &[u8]) -> usize {
- let len: i32 = self.len().try_into().unwrap();
- let res: VariantList = VariantList::new();
-
- let mut pos: usize = 0;
- for _ in 0..len {
- let mut val: Variant = Variant::Unknown;
- pos = pos + val.parse(&b[pos..]);
- }
-
- *self = res;
- return pos;
- }
-}
-
-#[allow(non_camel_case_types, dead_code)]
-#[derive(Clone)]
-pub enum Variant {
- Unknown,
- VariantMap(VariantMap),
- VariantList(VariantList),
- String(String),
- StringList(StringList),
- bool(bool),
- u64(u64),
- u32(u32),
- u16(u16),
- u8(u8),
- i64(i64),
- i32(i32),
- i16(i16),
- i8(i8),
-}
-
-impl Serialize for Variant {
- fn serialize(&self) -> Vec<u8> {
- let unknown: u32 = 0x00000000;
- let mut res: Vec<u8> = Vec::new();
-
- match self {
- Variant::Unknown => {
- return res;
- },
- Variant::VariantMap(v) => {
- res.extend(basic::QVARIANTMAP.to_be_bytes().iter());
- res.extend(unknown.to_be_bytes().iter());
- res.extend(v.serialize().iter());
- },
- Variant::VariantList(v) => {
- res.extend(basic::QVARIANTLIST.to_be_bytes().iter());
- res.extend(unknown.to_be_bytes().iter());
- res.extend(v.serialize().iter());
- },
- Variant::String(v) => {
- res.extend(basic::QSTRING.to_be_bytes().iter());
- res.extend(unknown.to_be_bytes().iter());
- res.extend(v.serialize().iter());
- },
- Variant::StringList(v) => {
- res.extend(basic::QSTRINGLIST.to_be_bytes().iter());
- res.extend(unknown.to_be_bytes().iter());
- res.extend(v.serialize().iter());
- },
- Variant::bool(v) => {
- res.extend(basic::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(basic::ULONG.to_be_bytes().iter());
- res.extend(unknown.to_be_bytes().iter());
- res.extend(v.to_be_bytes().iter());
- },
- Variant::u32(v) => {
- res.extend(basic::UINT.to_be_bytes().iter());
- res.extend(unknown.to_be_bytes().iter());
- res.extend(v.to_be_bytes().iter());
- },
- Variant::u16(v) => {
- res.extend(basic::USHORT.to_be_bytes().iter());
- res.extend(unknown.to_be_bytes().iter());
- res.extend(v.to_be_bytes().iter());
- },
- Variant::u8(v) => {
- res.extend(basic::UCHAR.to_be_bytes().iter());
- res.extend(unknown.to_be_bytes().iter());
- res.extend(v.to_be_bytes().iter());
- },
- Variant::i64(v) => {
- res.extend(basic::LONG.to_be_bytes().iter());
- res.extend(unknown.to_be_bytes().iter());
- res.extend(v.to_be_bytes().iter());
- },
- Variant::i32(v) => {
- res.extend(basic::INT.to_be_bytes().iter());
- res.extend(unknown.to_be_bytes().iter());
- res.extend(v.to_be_bytes().iter());
- },
- Variant::i16(v) => {
- res.extend(basic::SHORT.to_be_bytes().iter());
- res.extend(unknown.to_be_bytes().iter());
- res.extend(v.to_be_bytes().iter());
- },
- Variant::i8(v) => {
- res.extend(basic::CHAR.to_be_bytes().iter());
- res.extend(unknown.to_be_bytes().iter());
- res.extend(v.to_be_bytes().iter());
- },
- }
-
- return res
- }
-}
-
-impl Deserialize for Variant {
- fn parse(&mut self, b: &[u8]) -> usize {
- let mut qtype: i32 = 0;
- qtype.parse(&b[0..6]);
- let qtype: u32 = qtype as u32;
-
- #[allow(unused_variables)]
- let unknown: u8 = b[7];
-
- match qtype {
- QVARIANTMAP => {
- let mut value: VariantMap = VariantMap::new();
-
- let len = value.parse(&b[8..]);
- *self = Variant::VariantMap(value.clone());
-
- return len;
- },
- QVARIANTLIST => {
- let mut value: VariantList = VariantList::new();
-
- let len = value.parse(&b[8..]);
- *self = Variant::VariantList(value.clone());
-
- return len;
- },
- QSTRING => {
- let mut value: String = String::new();
-
- let len = value.parse(&b[8..]);
- *self = Variant::String(value.clone());
-
- return len;
- },
- QSTRINGLIST => {
- let mut value: StringList = StringList::new();
-
- let len = value.parse(&b[8..]);
- *self = Variant::StringList(value.clone());
-
- return len;
- },
- BOOL => {
- let mut value: bool = false;
-
- let len = value.parse(&b[8..]);
- *self = Variant::bool(value);
-
- return len;
- },
- ULONG => {
- let mut value: u64 = 0;
-
- let len = value.parse(&b[8..]);
- *self = Variant::u64(value);
-
- return len;
- },
- UINT => {
- let mut value: u32 = 0;
-
- let len = value.parse(&b[8..]);
- *self = Variant::u32(value);
-
- return len;
- },
- USHORT => {
- let mut value: u16 = 0;
-
- let len = value.parse(&b[8..]);
- *self = Variant::u16(value);
-
- return len;
- },
- UCHAR => {
- let mut value: u8 = 0;
-
- let len = value.parse(&b[8..]);
- *self = Variant::u8(value);
-
- return len;
- },
- LONG => {
- let mut value: i64 = 0;
-
- let len = value.parse(&b[8..]);
- *self = Variant::i64(value);
-
- return len;
- },
- INT => {
- let mut value: i32 = 0;
-
- let len = value.parse(&b[8..]);
- *self = Variant::i32(value);
-
- return len;
- },
- SHORT => {
- let mut value: i16 = 0;
-
- let len = value.parse(&b[8..]);
- *self = Variant::i16(value);
-
- return len;
- },
- CHAR => {
- let mut value: i8 = 0;
-
- let len = value.parse(&b[8..]);
- *self = Variant::i8(value);
-
- return len;
- },
- _ => {
- return 0;
- }
- }
- }
-}
diff --git a/src/util.rs b/src/util.rs
index 809287f..48ab55e 100644
--- a/src/util.rs
+++ b/src/util.rs
@@ -13,3 +13,30 @@ macro_rules! parse_match {
};
};
}
+
+#[macro_export]
+macro_rules! match_variant {
+ ( $values:expr, $x:path, $field:expr ) => {
+ match &$values[$field] {
+ $x(x) => { Ok(x.clone()) },
+ _ => { Err("") }
+ }.unwrap();
+ }
+}
+
+pub fn prepend_byte_len(buf: &mut Vec<u8>) {
+ use std::convert::TryInto;
+ let len: i32 = buf.len().try_into().unwrap();
+ let ulen: &[u8] = &len.to_be_bytes();
+ buf.insert(0, ulen[3]);
+ buf.insert(0, ulen[2]);
+ buf.insert(0, ulen[1]);
+ buf.insert(0, ulen[0]);
+}
+
+pub fn insert_bytes(pos: usize, buf: &mut Vec<u8>, input: &mut [u8]) {
+ input.reverse();
+ for i in input {
+ buf.insert(pos, *i)
+ }
+}
diff --git a/test.hex b/test.hex
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/test.hex