aboutsummaryrefslogtreecommitdiff
path: root/src/protocol
diff options
context:
space:
mode:
Diffstat (limited to '')
-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
7 files changed, 830 insertions, 0 deletions
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;
+ }
+}