aboutsummaryrefslogtreecommitdiff
path: root/src/protocol/primitive/variant.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/protocol/primitive/variant.rs')
-rw-r--r--src/protocol/primitive/variant.rs337
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);
- }
-}