diff options
| author | Max Audron <audron@cocaine.farm> | 2020-04-25 19:35:29 +0200 |
|---|---|---|
| committer | Max Audron <audron@cocaine.farm> | 2020-04-25 19:35:29 +0200 |
| commit | c546e2ef6c69bb1c6a86093f3cc7b2dab20d6ac4 (patch) | |
| tree | 5f761765863f39405a3ae6e27cb865ead6be2e38 /src/protocol/primitive/variant.rs | |
| parent | finish FramedCodec (diff) | |
finish parsing of primitive types
Diffstat (limited to 'src/protocol/primitive/variant.rs')
| -rw-r--r-- | src/protocol/primitive/variant.rs | 337 |
1 files changed, 149 insertions, 188 deletions
diff --git a/src/protocol/primitive/variant.rs b/src/protocol/primitive/variant.rs index 1c90574..84150a8 100644 --- a/src/protocol/primitive/variant.rs +++ b/src/protocol/primitive/variant.rs @@ -1,130 +1,37 @@ -use std::io::Read; use std::vec::Vec; -use std::convert::TryInto; -use std::collections::HashMap; use failure::Error; -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 log::{error, trace}; + use crate::protocol::error::ProtocolError; use crate::protocol::primitive; +use crate::protocol::primitive::deserialize::{Deserialize, DeserializeUTF8}; +use crate::protocol::primitive::serialize::{Serialize, SerializeUTF8}; +use crate::protocol::primitive::{String, StringList}; -pub type VariantMap = HashMap<String, Variant>; - -impl Serialize for VariantMap { - fn serialize<'a>(&'a self) -> Result<Vec<u8>, Error> { - 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()?; - util::insert_bytes(0, &mut res, &mut len.to_be_bytes()); - - return Ok(res); - } -} - -impl Deserialize for VariantMap { - fn parse(b: &[u8]) -> Result<(usize, Self), Error> { - let (_, len) = i32::parse(&b[0..4])?; - - let mut pos = 4; - let mut map = VariantMap::new(); - for _ in 0..len { - let (nlen, name) = String::parse(&b[(pos)..])?; - pos += nlen; - - let (vlen, value) = Variant::parse(&b[(pos)..])?; - pos += vlen; - - map.insert(name, value); - } - - return Ok((pos, map)); - } -} - -impl QRead for VariantMap { - fn read<T: Read>(s: &mut T, b: &mut [u8]) -> Result<usize, Error> { - s.read(&mut b[0..4])?; - - - let (_, len) = i32::parse(&b[0..4])?; - - let mut pos = 4; - for _ in 0..len { - pos += String::read(s, &mut b[pos..])?; - pos += Variant::read(s, &mut b[(pos+3..)])?; - } - - return Ok(pos); - } -} - -///////////////////////////////////////////////////////////////////////// -pub type VariantList = Vec<Variant>; - -impl Serialize for VariantList { - fn serialize(&self) -> Result<Vec<u8>, Error> { - let len: i32 = self.len().try_into()?; - let mut res: Vec<u8> = Vec::new(); - - res.extend(len.to_be_bytes().iter()); - for v in self { - res.extend(v.serialize()?.iter()); - } - - return Ok(res); - } -} - -impl Deserialize for VariantList { - fn parse(b: &[u8]) -> Result<(usize, Self), Error> { - 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 Ok((pos, res)); - } -} - -impl QRead for VariantList { - fn read<T: Read>(s: &mut T, b: &mut [u8]) -> Result<usize, Error> { - s.read(&mut b[0..4])?; - - let (_, len) = i32::parse(&b[0..4])?; - - let mut pos = 4; - for _ in 0..len { - pos += Variant::read(s, &mut b[(pos+3..)])?; - } +extern crate bytes; +use bytes::BytesMut; - return Ok(pos); - } -} +use crate::protocol::primitive::{ + BufferInfo, Date, DateTime, Message, Time, VariantList, VariantMap, +}; -///////////////////////////////////////////////////////////////////////// #[allow(non_camel_case_types, dead_code)] #[derive(Clone, Debug, std::cmp::PartialEq)] pub enum Variant { Unknown, + UserType(String, BytesMut), + BufferInfo(BufferInfo), + Message(Message), + Time(Time), + Date(Date), + DateTime(DateTime), VariantMap(VariantMap), VariantList(VariantList), String(String), StringUTF8(String), + ByteArray(String), StringList(StringList), bool(bool), u64(u64), @@ -144,82 +51,106 @@ impl Serialize for Variant { match self { Variant::Unknown => { - bail!(ProtocolError::UnknownVariant); - }, + bail!(ProtocolError::UnknownVariant); + } Variant::VariantMap(v) => { res.extend(primitive::QVARIANTMAP.to_be_bytes().iter()); res.extend(unknown.to_be_bytes().iter()); res.extend(v.serialize()?.iter()); - }, + } Variant::VariantList(v) => { res.extend(primitive::QVARIANTLIST.to_be_bytes().iter()); res.extend(unknown.to_be_bytes().iter()); res.extend(v.serialize()?.iter()); - }, + } Variant::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::ByteArray(v) => { + res.extend(primitive::QBYTEARRAY.to_be_bytes().iter()); + res.extend(unknown.to_be_bytes().iter()); + res.extend(v.serialize_utf8()?.iter()); + res.extend(vec![0x00]); + } 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()); - }, + } + Variant::UserType(_, _) => unimplemented!(), + Variant::BufferInfo(_) => unimplemented!(), + Variant::Message(_) => unimplemented!(), + Variant::DateTime(v) => { + res.extend(primitive::QDATETIME.to_be_bytes().iter()); + res.extend(unknown.to_be_bytes().iter()); + res.append(&mut v.serialize()?); + } + Variant::Time(v) => { + res.extend(primitive::QTIME.to_be_bytes().iter()); + res.extend(unknown.to_be_bytes().iter()); + res.append(&mut v.serialize()?); + } + Variant::Date(v) => { + res.extend(primitive::QDATE.to_be_bytes().iter()); + res.extend(unknown.to_be_bytes().iter()); + res.append(&mut v.serialize()?); + } } - return Ok(res) + return Ok(res); } } @@ -234,96 +165,126 @@ impl Deserialize for Variant { let len = 5; match qtype { primitive::QVARIANTMAP => { + trace!(target: "protocol::primitive::Variant", "Parsing Variant: VariantMap"); let (vlen, value) = VariantMap::parse(&b[len..])?; - return Ok((len+vlen, Variant::VariantMap(value))); - }, + return Ok((len + vlen, Variant::VariantMap(value))); + } primitive::QVARIANTLIST => { + trace!(target: "protocol::primitive::Variant", "Parsing Variant: VariantList"); let (vlen, value) = VariantList::parse(&b[len..])?; - return Ok((len+vlen, Variant::VariantList(value))); - }, + return Ok((len + vlen, Variant::VariantList(value))); + } primitive::QSTRING => { + trace!(target: "protocol::primitive::Variant", "Parsing Variant: String"); let (vlen, value) = String::parse(&b[len..])?; - return Ok((len+vlen, Variant::String(value.clone()))); - }, + return Ok((len + vlen, Variant::String(value.clone()))); + } primitive::QBYTEARRAY => { + trace!(target: "protocol::primitive::Variant", "Parsing Variant: ByteArray"); let (vlen, value) = String::parse_utf8(&b[len..])?; - return Ok((len+vlen, Variant::StringUTF8(value.clone()))); - }, + return Ok((len + vlen, Variant::StringUTF8(value.clone()))); + } primitive::QSTRINGLIST => { + trace!(target: "protocol::primitive::Variant", "Parsing Variant: StringList"); let (vlen, value) = StringList::parse(&b[len..])?; - return Ok((len+vlen, Variant::StringList(value.clone()))); - }, + return Ok((len + vlen, Variant::StringList(value.clone()))); + } + primitive::QDATETIME => { + trace!(target: "protocol::primitive::Variant", "Parsing Variant: Date"); + let (vlen, value) = Date::parse(&b[len..])?; + return Ok((len + vlen, Variant::Date(value.clone()))); + } + primitive::QDATE => { + trace!(target: "protocol::primitive::Variant", "Parsing Variant: Date"); + let (vlen, value) = Date::parse(&b[len..])?; + return Ok((len + vlen, Variant::Date(value.clone()))); + } + primitive::QTIME => { + trace!(target: "protocol::primitive::Variant", "Parsing Variant: Time"); + let (vlen, value) = Time::parse(&b[len..])?; + return Ok((len + vlen, Variant::Time(value.clone()))); + } primitive::BOOL => { let (vlen, value) = bool::parse(&b[len..])?; - return Ok((len+vlen, Variant::bool(value))); - }, + return Ok((len + vlen, Variant::bool(value))); + } primitive::ULONG => { let (vlen, value) = u64::parse(&b[len..])?; - return Ok((len+vlen, Variant::u64(value))); - }, + return Ok((len + vlen, Variant::u64(value))); + } primitive::UINT => { let (vlen, value) = u32::parse(&b[len..])?; - return Ok((len+vlen, Variant::u32(value))); - }, + return Ok((len + vlen, Variant::u32(value))); + } primitive::USHORT => { let (vlen, value) = u16::parse(&b[len..])?; - return Ok((len+vlen, Variant::u16(value))); - }, + return Ok((len + vlen, Variant::u16(value))); + } primitive::UCHAR => { let (vlen, value) = u8::parse(&b[len..])?; - return Ok((len+vlen, Variant::u8(value))); - }, + return Ok((len + vlen, Variant::u8(value))); + } primitive::LONG => { let (vlen, value) = i64::parse(&b[len..])?; - return Ok((len+vlen, Variant::i64(value))); - }, + return Ok((len + vlen, Variant::i64(value))); + } primitive::INT => { let (vlen, value) = i32::parse(&b[len..])?; - return Ok((len+vlen, Variant::i32(value))); - }, + return Ok((len + vlen, Variant::i32(value))); + } primitive::SHORT => { let (vlen, value) = i16::parse(&b[len..])?; - return Ok((len+vlen, Variant::i16(value))); - }, + return Ok((len + vlen, Variant::i16(value))); + } primitive::CHAR => { let (vlen, value) = i8::parse(&b[len..])?; - return Ok((len+vlen, Variant::i8(value))); - }, - _ => { + return Ok((len + vlen, Variant::i8(value))); + } + primitive::USERTYPE => { + trace!(target: "protocol::primitive::Variant", "Parsing UserType"); + // Parse UserType name + let (user_type_len, user_type) = String::parse_utf8(&b[len..])?; + + trace!(target: "protocol::primitive::Variant", "Parsing UserType: {:?}", user_type); + + // Match Possible User Types to basic structures + match user_type.as_str() { + // As VariantMap + "IrcUser" | "IrcChannel" | "Identity" | "NetworkInfo" | "Network::Server" => { + trace!(target: "protocol::primitive::Variant", "UserType is VariantMap"); + let (vlen, value) = VariantMap::parse(&b[(len + user_type_len)..])?; + return Ok((len + user_type_len + vlen, Variant::VariantMap(value))); + } + // As i32 + "BufferId" | "IdentityId" | "NetworkId" | "MsgId" => { + trace!(target: "protocol::primitive::Variant", "UserType is i32"); + + let (vlen, value) = i32::parse(&b[(len + user_type_len)..])?; + return Ok((len + user_type_len + vlen, Variant::i32(value))); + } + // As i64 + "PeerPtr" => { + trace!(target: "protocol::primitive::Variant", "UserType is i64"); + let (vlen, value) = i64::parse(&b[(len + user_type_len)..])?; + return Ok((len + user_type_len + vlen, Variant::i64(value))); + } + "BufferInfo" => { + trace!(target: "protocol::primitive::Variant", "UserType is BufferInfo"); + let (vlen, value) = BufferInfo::parse(&b[(len + user_type_len)..])?; + return Ok((len + user_type_len + vlen, Variant::BufferInfo(value))); + } + "Message" => { + trace!(target: "protocol::primitive::Variant", "UserType is Message"); + let (vlen, value) = Message::parse(&b[(len + user_type_len)..])?; + return Ok((len + user_type_len + vlen, Variant::Message(value))); + } + _ => unimplemented!(), + } + } + err => { + error!(target: "parser", "UnknownVariant: {:x?}", err); bail!(ProtocolError::UnknownVariant); } } } } - -impl QRead for Variant { - fn read<T: Read>(s: &mut T, b: &mut [u8]) -> Result<usize, Error> { - - s.read(&mut b[0..4])?; - let (_, qtype) = i32::parse(&b[0..4])?; - let qtype = qtype as u32; - - s.read(&mut [b[4]])?; - - let mut len = 5; - match qtype { - primitive::QVARIANTMAP => len += VariantMap::read(s, &mut b[len..])?, - primitive::QVARIANTLIST => len += VariantList::read(s, &mut b[len..])?, - primitive::QSTRING => len += String::read(s, &mut b[len..])?, - primitive::QBYTEARRAY => len += String::read(s, &mut b[len..])?, - primitive::QSTRINGLIST => len += StringList::read(s, &mut b[len..])?, - primitive::BOOL => len += bool::read(s, &mut b[len..])?, - primitive::ULONG => len += u64::read(s, &mut b[len..])?, - primitive::UINT => len += u32::read(s, &mut b[len..])?, - primitive::USHORT => len += u16::read(s, &mut b[len..])?, - primitive::UCHAR => len += u8::read(s, &mut b[len..])?, - primitive::LONG => len += i64::read(s, &mut b[len..])?, - primitive::INT => len += i32::read(s, &mut b[len..])?, - primitive::SHORT => len += i16::read(s, &mut b[len..])?, - primitive::CHAR => len += i8::read(s, &mut b[len..])?, - _ => bail!(ProtocolError::UnknownVariant) - } - - return Ok(len); - } -} |
