From 5d50a5f0c03baf460fee394decce5898812dbd2c Mon Sep 17 00:00:00 2001 From: Max Audron Date: Tue, 14 Jan 2020 12:35:46 +0100 Subject: refactor parse impl --- src/protocol/message/handshake.rs | 99 ++++++++++ src/protocol/message/handshake/types.rs | 92 +++++++++ src/protocol/message/mod.rs | 3 + src/protocol/mod.rs | 2 + src/protocol/primitive/basic.rs | 270 ++++++++++++++++++++++++++ src/protocol/primitive/mod.rs | 30 +++ src/protocol/primitive/variant.rs | 334 ++++++++++++++++++++++++++++++++ 7 files changed, 830 insertions(+) create mode 100644 src/protocol/message/handshake.rs create mode 100644 src/protocol/message/handshake/types.rs create mode 100644 src/protocol/message/mod.rs create mode 100644 src/protocol/mod.rs create mode 100644 src/protocol/primitive/basic.rs create mode 100644 src/protocol/primitive/mod.rs create mode 100644 src/protocol/primitive/variant.rs (limited to 'src/protocol') 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 { + 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 { + 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 { + 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; +} + +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; + +impl HandshakeSerialize for VariantMap { + fn serialize<'a>(&'a self) -> Vec { + let mut res: Vec = 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::().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::().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 { + let mut res: Vec = Vec::new(); + + let utf16: Vec = 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 { + let mut res: Vec = 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 = 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; +impl serialize::Serialize for StringList { + fn serialize(&self) -> Vec { + let len: i32 = self.len().try_into().unwrap(); + let mut res: Vec = 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; + } + pub trait SerializeUTF8 { + fn serialize_utf8(&self) -> Vec; + } +} + +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; + +impl Serialize for VariantMap { + fn serialize<'a>(&'a self) -> Vec { + let mut res: Vec = 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; + +impl Serialize for VariantList { + fn serialize(&self) -> Vec { + let len: i32 = self.len().try_into().unwrap(); + let mut res: Vec = 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 { + let unknown: u8 = 0x00; + let mut res: Vec = 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; + } +} -- cgit v1.2.3