aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Audron <audron@cocaine.farm>2021-01-21 14:57:22 +0100
committerMax Audron <audron@cocaine.farm>2021-01-21 14:57:22 +0100
commit2405fa686a53f1d895807b1658c38a5e7e7693a0 (patch)
treed40a9430a421d3ca4a28ce2ad98b51e3d731f265
parentMerge branch 'client' (diff)
reorganize tests and add quassel features
Diffstat (limited to '')
-rw-r--r--.gitignore1
-rw-r--r--Cargo.toml26
-rw-r--r--src/frame/mod.rs4
-rw-r--r--src/frame/tests.rs209
-rw-r--r--src/lib.rs4
-rw-r--r--src/message/handshake/clientinitack.rs4
-rw-r--r--src/message/handshake/clientloginack.rs2
-rw-r--r--src/message/handshake/mod.rs2
-rw-r--r--src/message/handshake/types.rs49
-rw-r--r--src/primitive/bufferinfo.rs37
-rw-r--r--src/primitive/datetime.rs34
-rw-r--r--src/primitive/message.rs80
-rw-r--r--src/primitive/signedint.rs5
-rw-r--r--src/primitive/string.rs56
-rw-r--r--src/primitive/stringlist.rs26
-rw-r--r--src/primitive/variant.rs326
-rw-r--r--src/primitive/variantlist.rs2
-rw-r--r--src/primitive/variantmap.rs2
-rw-r--r--src/tests/base_types.rs84
-rw-r--r--src/tests/datetime.rs28
-rw-r--r--src/tests/frame.rs240
-rw-r--r--src/tests/handshake_types.rs44
-rw-r--r--src/tests/mod.rs17
-rw-r--r--src/tests/variant_types.rs100
-rw-r--r--src/util.rs19
25 files changed, 850 insertions, 551 deletions
diff --git a/.gitignore b/.gitignore
index 0986dc1..707473a 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,4 @@ Cargo.lock
/target
**/*.rs.bk
examples/testserver
+lcov.info
diff --git a/Cargo.toml b/Cargo.toml
index 5087e2c..94366cf 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -15,24 +15,24 @@ autobins = true
log = "0.4"
byteorder = "1.3.2"
failure = "0.1"
-either = "1.5"
time = "0.2"
-async-trait = "0.1"
-default-macro = { path = "../default-macro" }
+num-traits = "0.2"
+num-derive = "0.3"
-bytes = { version = "1.0" }
+libquassel-derive = { path = "./derive" }
+
+
+bytes = { version = "1.0", optional = true }
flate2 = { version = "1.0", features = ["tokio"], optional = true }
tokio = { version = "1.0", features = [], optional = true }
tokio-util = { version = "0.6", features = ["codec"], optional = true }
-futures-util = { version = "0.3", features = ["std"], optional = true }
-futures = { version = "0.3", optional = true }
[features]
-framing = ["tokio", "tokio-util", "flate2"]
+framing = ["tokio", "tokio-util", "flate2", "bytes"]
# Enable all the quassel features
-all-quassel-features = ["long-message-id", "long-time", "rich-messages", "sender-prefixes"]
+all-quassel-features = ["long-message-id", "long-time", "rich-messages", "sender-prefixes", "authenticators"]
# Serialize message IDs as i64
long-message-id = []
@@ -42,6 +42,8 @@ long-time = []
rich-messages = []
# Show prefixes for senders in backlog
sender-prefixes = []
+# Support for exchangeable auth backends
+authenticators = []
default = []
@@ -53,8 +55,12 @@ all-features = true
rustdoc-args = ["--cfg", "docsrs"]
[dev-dependencies]
-# futures = { version = "0.3" }
+futures = { version = "0.3" }
# flate2 = { version = "1.0", features = ["tokio"] }
# tokio = { version = "0.3", features = ["full"] }
# tokio-util = { version = "0.5", features = ["codec"] }
-# tokio-test = { version = "0.3" }
+tokio-test = { version = "0.4" }
+pretty_assertions = "0.6"
+
+[workspace]
+members = ["derive", "examples/quasselproxy"]
diff --git a/src/frame/mod.rs b/src/frame/mod.rs
index cbeddb0..34a8514 100644
--- a/src/frame/mod.rs
+++ b/src/frame/mod.rs
@@ -15,6 +15,9 @@ use flate2::Decompress;
use flate2::FlushCompress;
use flate2::FlushDecompress;
+#[cfg(test)]
+mod tests;
+
/// Builder for the QuasselCodec
#[derive(Debug, Clone, Copy)]
pub struct Builder {
@@ -28,6 +31,7 @@ pub struct Builder {
}
// An error when the number of bytes read is more than max frame length.
+#[derive(PartialEq)]
pub struct QuasselCodecError {
_priv: (),
}
diff --git a/src/frame/tests.rs b/src/frame/tests.rs
new file mode 100644
index 0000000..5029ea3
--- /dev/null
+++ b/src/frame/tests.rs
@@ -0,0 +1,209 @@
+use tokio_test::assert_ready;
+use tokio_test::task;
+use tokio_util::codec::*;
+
+use futures::{pin_mut, Stream};
+
+use crate::frame::*;
+
+macro_rules! assert_next_eq {
+ ($io:ident, $expect:expr) => {{
+ task::spawn(()).enter(|cx, _| {
+ let res = assert_ready!($io.as_mut().poll_next(cx));
+ match res {
+ Some(Ok(v)) => assert_eq!(v, $expect.as_ref()),
+ Some(Err(e)) => panic!("error = {:?}", e),
+ None => panic!("none"),
+ }
+ });
+ }};
+}
+
+// macro_rules! assert_next_pending {
+// ($io:ident) => {{
+// task::spawn(()).enter(|cx, _| match $io.as_mut().poll_next(cx) {
+// Ready(Some(Ok(v))) => panic!("value = {:?}", v),
+// Ready(Some(Err(e))) => panic!("error = {:?}", e),
+// Ready(None) => panic!("done"),
+// Pending => {}
+// });
+// }};
+// }
+
+// macro_rules! assert_next_err {
+// ($io:ident) => {{
+// task::spawn(()).enter(|cx, _| match $io.as_mut().poll_next(cx) {
+// Ready(Some(Ok(v))) => panic!("value = {:?}", v),
+// Ready(Some(Err(_))) => {}
+// Ready(None) => panic!("done"),
+// Pending => panic!("pending"),
+// });
+// }};
+// }
+
+macro_rules! assert_done {
+ ($io:ident) => {{
+ task::spawn(()).enter(|cx, _| {
+ let res = assert_ready!($io.as_mut().poll_next(cx));
+ match res {
+ Some(Ok(v)) => panic!("value = {:?}", v),
+ Some(Err(e)) => panic!("error = {:?}", e),
+ None => {}
+ }
+ });
+ }};
+}
+
+// ======================
+// ===== Test =====
+// ======================
+
+use tokio_test::io::Builder;
+
+#[test]
+fn quasselcodec_set_options() {
+ use flate2::Compression;
+
+ let mut codec = QuasselCodec::default();
+
+ assert_eq!(codec.max_frame_length(), 64 * 1024 * 1024);
+ assert_eq!(codec.compression(), false);
+ assert_eq!(codec.compression_level(), Compression::default());
+
+ codec.set_max_frame_length(42);
+ codec.set_compression(true);
+ codec.set_compression_level(Compression::best());
+
+ assert_eq!(codec.max_frame_length(), 42);
+ assert_eq!(codec.compression(), true);
+ assert_eq!(codec.compression_level(), Compression::best());
+}
+
+#[test]
+fn quasselcodec_write_oversized() {
+ use futures::sink::SinkExt;
+
+ let mut io = Framed::new(
+ Builder::new()
+ .write_error(std::io::Error::new(
+ std::io::ErrorKind::InvalidInput,
+ QuasselCodecError { _priv: () },
+ ))
+ .build(),
+ QuasselCodec::builder().max_frame_length(5).new_codec(),
+ );
+
+ tokio_test::block_on(async move {
+ let res = io.send(b"abcdefghi".to_vec()).await.map_err(|e| e.kind());
+ let want = Err(std::io::ErrorKind::InvalidInput);
+
+ assert_eq!(want, res);
+ });
+}
+
+#[test]
+fn quasselcodec_read_oversized() {
+ use futures::stream::StreamExt;
+
+ let mut io = FramedRead::new(
+ Builder::new().read(b"\x00\x00\x00\x09abcdefghi").build(),
+ QuasselCodec::builder().max_frame_length(5).new_codec(),
+ );
+
+ tokio_test::block_on(async move {
+ let res = io.next().await.unwrap().map_err(|e| e.kind());
+ let want = Err(std::io::ErrorKind::InvalidData);
+
+ assert_eq!(want, res);
+ });
+}
+
+#[test]
+pub fn read_single_frame() {
+ let io = FramedRead::new(
+ Builder::new().read(b"\x00\x00\x00\x09abcdefghi").build(),
+ QuasselCodec::new(),
+ );
+ pin_mut!(io);
+
+ assert_next_eq!(io, b"abcdefghi");
+ assert_done!(io);
+}
+
+#[test]
+pub fn read_multi_frame() {
+ let mut d: Vec<u8> = vec![];
+ d.extend_from_slice(b"\x00\x00\x00\x09abcdefghi");
+ d.extend_from_slice(b"\x00\x00\x00\x03123");
+ d.extend_from_slice(b"\x00\x00\x00\x0bhello world");
+
+ let io = FramedRead::new(Builder::new().read(&d).build(), QuasselCodec::new());
+ pin_mut!(io);
+
+ assert_next_eq!(io, b"abcdefghi");
+ assert_next_eq!(io, b"123");
+ assert_next_eq!(io, b"hello world");
+ assert_done!(io);
+}
+
+#[test]
+pub fn read_single_frame_compressed() {
+ let io = FramedRead::new(
+ Builder::new().read(b"\x78\x9c\x63\x60\x60\xe0\x4c\x4c\x4a\x4e\x49\x4d\x4b\xcf\xc8\x04\x00\x11\xec\x03\x97").build(),
+ QuasselCodec::builder().compression(true).new_codec(),
+ );
+ pin_mut!(io);
+
+ assert_next_eq!(io, b"abcdefghi");
+ assert_done!(io);
+}
+
+#[test]
+fn write_single_frame() {
+ use futures::sink::SinkExt;
+
+ let mut io = Framed::new(
+ Builder::new().write(b"\x00\x00\x00\x09abcdefghi").build(),
+ QuasselCodec::new(),
+ );
+
+ tokio_test::block_on(async move {
+ io.send(b"abcdefghi".to_vec()).await.unwrap();
+ });
+}
+
+#[test]
+fn write_multi_frame() {
+ use futures::sink::SinkExt;
+
+ let mut io = Framed::new(
+ Builder::new()
+ .write(b"\x00\x00\x00\x09abcdefghi")
+ .write(b"\x00\x00\x00\x03123")
+ .write(b"\x00\x00\x00\x0bhello world")
+ .build(),
+ QuasselCodec::new(),
+ );
+
+ tokio_test::block_on(async move {
+ io.send(b"abcdefghi".to_vec()).await.unwrap();
+ io.send(b"123".to_vec()).await.unwrap();
+ io.send(b"hello world".to_vec()).await.unwrap();
+ });
+}
+
+#[test]
+fn write_single_frame_compressed() {
+ use futures::sink::SinkExt;
+
+ let mut io = Framed::new(
+ Builder::new()
+ .write(&[120, 156, 98, 96, 96, 224, 76, 76, 74, 78, 73, 77, 75])
+ .build(),
+ QuasselCodec::builder().compression(true).new_codec(),
+ );
+
+ tokio_test::block_on(async move {
+ io.send(b"abcdefghi".to_vec()).await.unwrap();
+ });
+}
diff --git a/src/lib.rs b/src/lib.rs
index 223a2da..f96e7a7 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,3 +1,4 @@
+#![feature(array_value_iter)]
#![feature(external_doc)]
#![feature(doc_cfg)]
#![doc(include = "../README.md")]
@@ -5,9 +6,6 @@
#[macro_use]
mod util;
-#[cfg(test)]
-pub mod tests;
-
#[macro_use]
extern crate failure;
diff --git a/src/message/handshake/clientinitack.rs b/src/message/handshake/clientinitack.rs
index f881113..a259f9c 100644
--- a/src/message/handshake/clientinitack.rs
+++ b/src/message/handshake/clientinitack.rs
@@ -13,6 +13,8 @@ pub struct ClientInitAck {
/// List of VariantMaps of info on available backends
pub storage_backends: VariantList,
/// List of VariantMaps of info on available authenticators
+ #[cfg(feature = "authenticators")]
+ #[cfg_attr(docsrs, doc(cfg(feature = "authenticators")))]
pub authenticators: VariantList,
/// List of supported extended features
pub feature_list: Vec<String>,
@@ -34,6 +36,7 @@ impl HandshakeSerialize for ClientInitAck {
"StorageBackends".to_string(),
Variant::VariantList(self.storage_backends.clone()),
);
+ #[cfg(feature = "authenticators")]
values.insert(
"Authenticators".to_string(),
Variant::VariantList(self.authenticators.clone()),
@@ -56,6 +59,7 @@ impl From<VariantMap> for ClientInitAck {
input.get("StorageBackends").unwrap(),
Variant::VariantList
),
+ #[cfg(feature = "authenticators")]
authenticators: match_variant!(
input.get("Authenticators").unwrap(),
Variant::VariantList
diff --git a/src/message/handshake/clientloginack.rs b/src/message/handshake/clientloginack.rs
index e385a81..72dd6ac 100644
--- a/src/message/handshake/clientloginack.rs
+++ b/src/message/handshake/clientloginack.rs
@@ -24,7 +24,7 @@ impl HandshakeDeserialize for ClientLoginAck {
fn parse(b: &[u8]) -> Result<(usize, Self), Error> {
let (len, values): (usize, VariantMap) = HandshakeDeserialize::parse(b)?;
- let msgtype = match_variant!(&values["MsgType"], Variant::StringUTF8);
+ let msgtype = match_variant!(&values["MsgType"], Variant::ByteArray);
if msgtype == "ClientLogin" {
return Ok((len, Self {}));
diff --git a/src/message/handshake/mod.rs b/src/message/handshake/mod.rs
index 9885012..c180c5e 100644
--- a/src/message/handshake/mod.rs
+++ b/src/message/handshake/mod.rs
@@ -5,6 +5,7 @@ mod clientlogin;
mod clientloginack;
mod clientloginreject;
mod connack;
+mod features;
mod init;
mod protocol;
mod sessioninit;
@@ -17,6 +18,7 @@ pub use clientlogin::*;
pub use clientloginack::*;
pub use clientloginreject::*;
pub use connack::*;
+pub use features::*;
pub use init::*;
pub use protocol::*;
pub use sessioninit::*;
diff --git a/src/message/handshake/types.rs b/src/message/handshake/types.rs
index 04e1dd0..24d847b 100644
--- a/src/message/handshake/types.rs
+++ b/src/message/handshake/types.rs
@@ -6,9 +6,9 @@ use failure::Error;
use crate::error::ProtocolError;
use crate::primitive::Variant;
+use crate::util;
use crate::Deserialize;
use crate::Serialize;
-use crate::util;
use crate::primitive::VariantMap;
use crate::{HandshakeDeserialize, HandshakeSerialize};
@@ -46,7 +46,7 @@ impl HandshakeDeserialize for VariantMap {
match name {
Variant::String(x) => map.insert(x, value),
- Variant::StringUTF8(x) => map.insert(x, value),
+ Variant::ByteArray(x) => map.insert(x, value),
_ => bail!(ProtocolError::WrongVariant),
};
}
@@ -54,3 +54,48 @@ impl HandshakeDeserialize for VariantMap {
return Ok((pos, map));
}
}
+
+#[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, 2, 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!(
+ HandshakeSerialize::serialize(&test_variantmap).unwrap(),
+ bytes
+ );
+}
+
+#[test]
+pub fn deserialize_variantmap() {
+ let test_bytes: &[u8] = &[
+ 0, 0, 0, 2, 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): (usize, VariantMap) = HandshakeDeserialize::parse(test_bytes).unwrap();
+
+ assert_eq!(len, 39);
+ assert_eq!(res, test_variantmap);
+}
+
+#[test]
+pub fn deserialize_variantmap_utf8() {
+ let test_bytes: &[u8] = &[
+ 0, 0, 0, 2, 0, 0, 0, 12, 0, 0, 0, 0, 10, 67, 111, 110, 102, 105, 103, 117, 114, 101, 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): (usize, VariantMap) = HandshakeDeserialize::parse(test_bytes).unwrap();
+
+ assert_eq!(len, 29);
+ assert_eq!(res, test_variantmap);
+}
diff --git a/src/primitive/bufferinfo.rs b/src/primitive/bufferinfo.rs
index 9cbaa2d..1c4e206 100644
--- a/src/primitive/bufferinfo.rs
+++ b/src/primitive/bufferinfo.rs
@@ -5,8 +5,6 @@ use failure::Error;
use crate::{Deserialize, DeserializeUTF8};
use crate::{Serialize, SerializeUTF8};
-extern crate bytes;
-
/// The BufferInfo struct represents a BufferInfo as received in IRC
///
/// BufferInfo is, like all other struct based types, serialized sequentially.
@@ -79,3 +77,38 @@ impl From<i16> for BufferType {
}
}
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn bufferinfo_serialize() {
+ let buffer = BufferInfo {
+ id: 1,
+ network_id: 1,
+ buffer_type: BufferType::Channel,
+ name: "#test".to_string(),
+ };
+
+ assert_eq!(
+ buffer.serialize().unwrap(),
+ [0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 5, 35, 116, 101, 115, 116]
+ )
+ }
+
+ #[test]
+ fn bufferinfo_deserialize() {
+ let buffer = BufferInfo {
+ id: 1,
+ network_id: 1,
+ buffer_type: BufferType::Channel,
+ name: "#test".to_string(),
+ };
+ let bytes = vec![
+ 0, 0, 0, 1, 0, 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 5, 35, 116, 101, 115, 116,
+ ];
+
+ assert_eq!(BufferInfo::parse(&bytes).unwrap(), (23, buffer))
+ }
+}
diff --git a/src/primitive/datetime.rs b/src/primitive/datetime.rs
index fadd6a5..e4c4c83 100644
--- a/src/primitive/datetime.rs
+++ b/src/primitive/datetime.rs
@@ -166,3 +166,37 @@ impl Deserialize for Time {
Ok((4, time))
}
}
+
+#[test]
+pub fn datetime_serialize() {
+ let datetime = DateTime::parse("2020-02-19 13:00 +0200", "%Y-%m-%d %R %z").unwrap();
+
+ let sers = datetime.serialize().unwrap();
+ let bytes = vec![0, 37, 133, 19, 2, 202, 28, 128, 3, 0, 0, 28, 32];
+
+ assert_eq!(sers, bytes)
+}
+
+#[test]
+pub fn datetime_deserialize() {
+ let datetime = DateTime::parse("2020-02-19 13:00 +0200", "%Y-%m-%d %R %z").unwrap();
+
+ let bytes = vec![0, 37, 133, 19, 2, 202, 28, 128, 3, 0, 0, 28, 32];
+ let (_, res): (usize, DateTime) = Deserialize::parse(&bytes).unwrap();
+
+ assert_eq!(res, datetime)
+}
+
+#[test]
+pub fn datetime_deserialize_epoch() {
+ let datetime = DateTime::unix_epoch();
+
+ let bytes = vec![0, 37, 133, 19, 0xff, 0xff, 0xff, 0xff, 3, 0, 0, 28, 32];
+ let (_, res): (usize, DateTime) = Deserialize::parse(&bytes).unwrap();
+
+ let bytes = vec![0xff, 0xff, 0xff, 0xff, 2, 202, 28, 128, 3, 0, 0, 28, 32];
+ let (_, res2): (usize, DateTime) = Deserialize::parse(&bytes).unwrap();
+
+ assert_eq!(res, datetime);
+ assert_eq!(res2, datetime)
+}
diff --git a/src/primitive/message.rs b/src/primitive/message.rs
index 56bae22..04c427e 100644
--- a/src/primitive/message.rs
+++ b/src/primitive/message.rs
@@ -7,8 +7,6 @@ use crate::{Serialize, SerializeUTF8};
use crate::primitive::BufferInfo;
-extern crate bytes;
-
/// The Message struct represents a Message as received in IRC
///
/// Messages are, like all other struct based types, serialized sequentially.
@@ -22,7 +20,9 @@ pub struct Message {
#[cfg(not(feature = "long-message-id"))]
#[cfg_attr(docsrs, doc(cfg(not(feature = "long-message-id"))))]
pub msg_id: i32,
- /// The timestamp of the message in UNIX time (32-bit, seconds, 64-bit if long-time feature enabled)
+ /// The timestamp of the message in UNIX time.
+ /// If long-time is disabled this is an i32 representing the seconds since EPOCH.
+ /// If long-time is enabled this is an i64 representing the miliseconds since EPOCH.
#[cfg(feature = "long-time")]
#[cfg_attr(docsrs, doc(cfg(feature = "long-time")))]
pub timestamp: i64,
@@ -220,3 +220,77 @@ impl From<i32> for MessageType {
}
}
}
+
+#[cfg(test)]
+#[cfg(feature = "all-quassel-features")]
+mod tests {
+ use super::*;
+ use crate::primitive::{BufferInfo, BufferType};
+
+ #[test]
+ fn message_serialize() {
+ let message = Message {
+ msg_id: 1,
+ timestamp: 1609846597,
+ msg_type: MessageType::Plain,
+ flags: 0,
+ buffer: BufferInfo {
+ id: 1,
+ network_id: 1,
+ buffer_type: BufferType::Channel,
+ name: "#test".to_string(),
+ },
+ sender: "test".to_string(),
+ content: "this is a test message".to_string(),
+ sender_prefixes: "blabla".to_string(),
+ real_name: "test user".to_string(),
+ avatar_url: "https://jfkalsdkjfj.com/kjkj".to_string(),
+ };
+
+ assert_eq!(
+ message.serialize().unwrap(),
+ [
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 95, 244, 79, 69, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0,
+ 0, 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 5, 35, 116, 101, 115, 116, 0, 0, 0, 4, 116,
+ 101, 115, 116, 0, 0, 0, 6, 98, 108, 97, 98, 108, 97, 0, 0, 0, 9, 116, 101, 115,
+ 116, 32, 117, 115, 101, 114, 0, 0, 0, 28, 104, 116, 116, 112, 115, 58, 47, 47, 106,
+ 102, 107, 97, 108, 115, 100, 107, 106, 102, 106, 46, 99, 111, 109, 47, 107, 106,
+ 107, 106, 0, 0, 0, 22, 116, 104, 105, 115, 32, 105, 115, 32, 97, 32, 116, 101, 115,
+ 116, 32, 109, 101, 115, 115, 97, 103, 101
+ ]
+ )
+ }
+
+ #[test]
+ fn message_deserialize() {
+ let message = Message {
+ msg_id: 1,
+ timestamp: 1609846597,
+ msg_type: MessageType::Plain,
+ flags: 0,
+ buffer: BufferInfo {
+ id: 1,
+ network_id: 1,
+ buffer_type: BufferType::Channel,
+ name: "#test".to_string(),
+ },
+ sender: "test".to_string(),
+ content: "this is a test message".to_string(),
+ sender_prefixes: "blabla".to_string(),
+ real_name: "test user".to_string(),
+ avatar_url: "https://jfkalsdkjfj.com/kjkj".to_string(),
+ };
+
+ let bytes = vec![
+ 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 95, 244, 79, 69, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0,
+ 0, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0, 5, 35, 116, 101, 115, 116, 0, 0, 0, 4, 116, 101, 115,
+ 116, 0, 0, 0, 6, 98, 108, 97, 98, 108, 97, 0, 0, 0, 9, 116, 101, 115, 116, 32, 117,
+ 115, 101, 114, 0, 0, 0, 28, 104, 116, 116, 112, 115, 58, 47, 47, 106, 102, 107, 97,
+ 108, 115, 100, 107, 106, 102, 106, 46, 99, 111, 109, 47, 107, 106, 107, 106, 0, 0, 0,
+ 22, 116, 104, 105, 115, 32, 105, 115, 32, 97, 32, 116, 101, 115, 116, 32, 109, 101,
+ 115, 115, 97, 103, 101,
+ ];
+
+ assert_eq!(Message::parse(&bytes).unwrap(), (133, message))
+ }
+}
diff --git a/src/primitive/signedint.rs b/src/primitive/signedint.rs
index 4c21a69..a1254fb 100644
--- a/src/primitive/signedint.rs
+++ b/src/primitive/signedint.rs
@@ -1,8 +1,6 @@
-extern crate byteorder;
use byteorder::{BigEndian, ReadBytesExt};
use std::io::Cursor;
-use std::convert::TryInto;
use std::result::Result;
use std::vec::Vec;
@@ -57,6 +55,7 @@ impl Serialize for i8 {
impl Deserialize for i8 {
fn parse(b: &[u8]) -> Result<(usize, Self), Error> {
- return Ok((1, b[0].try_into()?));
+ let mut rdr = Cursor::new(&b[0..1]);
+ return Ok((1, rdr.read_i8()?));
}
}
diff --git a/src/primitive/string.rs b/src/primitive/string.rs
index dcd4f7c..590c529 100644
--- a/src/primitive/string.rs
+++ b/src/primitive/string.rs
@@ -50,6 +50,7 @@ impl Deserialize for String {
// length as usize
let ulen = len as usize;
+ trace!("parsed bytes: {:x?}", &b[0..ulen]);
let mut pos: usize = 4;
let mut chars: Vec<u16> = Vec::new();
loop {
@@ -91,7 +92,62 @@ impl DeserializeUTF8 for String {
}
trace!("parsed string after trunc: {}", res);
+ trace!("parsed bytes: {:x?}", &b[0..ulen]);
return Ok((ulen + 4, res));
}
}
+
+#[test]
+pub fn string_serialize() {
+ let test_string: String = String::from("Configured");
+
+ assert_eq!(
+ test_string.serialize().unwrap(),
+ [
+ 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 string_serialize_utf8() {
+ let test_string: String = String::from("Configured");
+
+ assert_eq!(
+ test_string.serialize_utf8().unwrap(),
+ [0, 0, 0, 10, 67, 111, 110, 102, 105, 103, 117, 114, 101, 100]
+ );
+}
+
+#[test]
+pub fn string_deserialize() {
+ 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).unwrap();
+ assert_eq!(res, "Configured");
+ assert_eq!(len, 24);
+}
+
+#[test]
+pub fn string_deserialize_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).unwrap();
+ assert_eq!(len, 14);
+ assert_eq!(res, "Configured");
+}
+
+#[test]
+pub fn string_deserialize_utf8_null_terminated() {
+ let test_bytes: &[u8] = &[
+ 0, 0, 0, 11, 67, 111, 110, 102, 105, 103, 117, 114, 101, 100, 0, 0, 0, 0, 1,
+ ];
+ let (len, res) = String::parse_utf8(test_bytes).unwrap();
+ assert_eq!(len, 15);
+ assert_eq!(res, "Configured");
+}
diff --git a/src/primitive/stringlist.rs b/src/primitive/stringlist.rs
index e5d1a44..df6d281 100644
--- a/src/primitive/stringlist.rs
+++ b/src/primitive/stringlist.rs
@@ -47,3 +47,29 @@ impl Deserialize for StringList {
return Ok((pos, res));
}
}
+
+#[test]
+pub fn string_list_serialize() {
+ let mut test_list = StringList::new();
+ test_list.push("Configured".to_string());
+ assert_eq!(
+ test_list.serialize().unwrap(),
+ [
+ 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 string_list_deserialize() {
+ 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,
+ ];
+ let mut test_list = StringList::new();
+ test_list.push("Configured".to_string());
+ let (len, res) = StringList::parse(test_bytes).unwrap();
+ assert_eq!(len, 28);
+ assert_eq!(test_list, res);
+}
diff --git a/src/primitive/variant.rs b/src/primitive/variant.rs
index be2bebe..e9e032e 100644
--- a/src/primitive/variant.rs
+++ b/src/primitive/variant.rs
@@ -10,8 +10,6 @@ use crate::primitive::StringList;
use crate::{Deserialize, DeserializeUTF8};
use crate::{Serialize, SerializeUTF8};
-extern crate bytes;
-
use crate::primitive::{BufferInfo, Date, DateTime, Message, Time, VariantList, VariantMap};
/// Variant represents the possible types we can receive
@@ -21,7 +19,7 @@ use crate::primitive::{BufferInfo, Date, DateTime, Message, Time, VariantList, V
/// BufferInfo and Message are UserTypes
/// but we represent them as a native Type here.
///
-/// StringUTF8 is de-/serialized as a C ByteArray.
+/// ByteArray is de-/serialized as a C ByteArray.
#[allow(non_camel_case_types, dead_code)]
#[derive(Clone, Debug, std::cmp::PartialEq)]
pub enum Variant {
@@ -35,7 +33,6 @@ pub enum Variant {
VariantMap(VariantMap),
VariantList(VariantList),
String(String),
- StringUTF8(String),
ByteArray(String),
StringList(StringList),
bool(bool),
@@ -73,11 +70,6 @@ impl Serialize for Variant {
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());
@@ -199,7 +191,7 @@ impl Deserialize for Variant {
primitive::QBYTEARRAY => {
trace!(target: "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::ByteArray(value.clone())));
}
primitive::QSTRINGLIST => {
trace!(target: "primitive::Variant", "Parsing Variant: StringList");
@@ -320,3 +312,317 @@ impl Deserialize for Variant {
}
}
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+
+ #[test]
+ fn signed_serialize() {
+ let i_64 = Variant::i64(847291274197592);
+ let i_32 = Variant::i32(897911521);
+ let i_16 = Variant::i16(8179);
+ let i_8 = Variant::i8(78);
+
+ let i_n_64 = Variant::i64(-847291274197592);
+ let i_n_32 = Variant::i32(-897911521);
+ let i_n_16 = Variant::i16(-8179);
+ let i_n_8 = Variant::i8(-78);
+
+ assert_eq!(
+ i_64.serialize().unwrap(),
+ [0, 0, 0, 129, 0, 0, 3, 2, 155, 95, 107, 122, 88]
+ );
+ assert_eq!(i_32.serialize().unwrap(), [0, 0, 0, 2, 0, 53, 133, 10, 225]);
+ assert_eq!(i_16.serialize().unwrap(), [0, 0, 0, 130, 0, 31, 243]);
+ assert_eq!(i_8.serialize().unwrap(), [0, 0, 0, 131, 0, 78]);
+
+ assert_eq!(
+ i_n_64.serialize().unwrap(),
+ [0, 0, 0, 129, 0, 255, 252, 253, 100, 160, 148, 133, 168]
+ );
+ assert_eq!(
+ i_n_32.serialize().unwrap(),
+ [0, 0, 0, 2, 0, 202, 122, 245, 31]
+ );
+ assert_eq!(i_n_16.serialize().unwrap(), [0, 0, 0, 130, 0, 224, 13]);
+ assert_eq!(i_n_8.serialize().unwrap(), [0, 0, 0, 131, 0, 178]);
+ }
+
+ #[test]
+ fn unsigned_serialize() {
+ let u_64 = Variant::u64(847291274197592);
+ let u_32 = Variant::u32(897911521);
+ let u_16 = Variant::u16(8179);
+ let u_8 = Variant::u8(78);
+
+ assert_eq!(
+ u_64.serialize().unwrap(),
+ [0, 0, 0, 132, 0, 0, 3, 2, 155, 95, 107, 122, 88]
+ );
+ assert_eq!(u_32.serialize().unwrap(), [0, 0, 0, 3, 0, 53, 133, 10, 225]);
+ assert_eq!(u_16.serialize().unwrap(), [0, 0, 0, 133, 0, 31, 243]);
+ assert_eq!(u_8.serialize().unwrap(), [0, 0, 0, 134, 0, 78]);
+ }
+
+ #[test]
+ fn variant_signed_deserialize() {
+ let i_64 = Variant::i64(847291274197592);
+ let i_32 = Variant::i32(897911521);
+ let i_16 = Variant::i16(8179);
+ let i_8 = Variant::i8(78);
+
+ let i_n_64 = Variant::i64(-847291274197592);
+ let i_n_32 = Variant::i32(-897911521);
+ let i_n_16 = Variant::i16(-8179);
+ let i_n_8 = Variant::i8(-78);
+
+ let (_, v_i_64) =
+ Variant::parse(&[0, 0, 0, 129, 0, 0, 3, 2, 155, 95, 107, 122, 88]).unwrap();
+ let (_, v_i_32) = Variant::parse(&[0, 0, 0, 2, 0, 53, 133, 10, 225]).unwrap();
+ let (_, v_i_16) = Variant::parse(&[0, 0, 0, 130, 0, 31, 243]).unwrap();
+ let (_, v_i_8) = Variant::parse(&[0, 0, 0, 131, 0, 78]).unwrap();
+
+ let (_, v_i_n_64) =
+ Variant::parse(&[0, 0, 0, 129, 0, 255, 252, 253, 100, 160, 148, 133, 168]).unwrap();
+ let (_, v_i_n_32) = Variant::parse(&[0, 0, 0, 2, 0, 202, 122, 245, 31]).unwrap();
+ let (_, v_i_n_16) = Variant::parse(&[0, 0, 0, 130, 0, 224, 13]).unwrap();
+ let (_, v_i_n_8) = Variant::parse(&[0, 0, 0, 131, 0, 178]).unwrap();
+
+ assert_eq!(i_64, v_i_64);
+ assert_eq!(i_32, v_i_32);
+ assert_eq!(i_16, v_i_16);
+ assert_eq!(i_8, v_i_8);
+
+ assert_eq!(i_n_64, v_i_n_64);
+ assert_eq!(i_n_32, v_i_n_32);
+ assert_eq!(i_n_16, v_i_n_16);
+ assert_eq!(i_n_8, v_i_n_8);
+ }
+
+ #[test]
+ fn unsigned_deserialize() {
+ let u_64 = Variant::u64(847291274197592);
+ let u_32 = Variant::u32(897911521);
+ let u_16 = Variant::u16(8179);
+ let u_8 = Variant::u8(78);
+
+ let (_, v_u_64) =
+ Variant::parse(&[0, 0, 0, 132, 0, 0, 3, 2, 155, 95, 107, 122, 88]).unwrap();
+ let (_, v_u_32) = Variant::parse(&[0, 0, 0, 3, 0, 53, 133, 10, 225]).unwrap();
+ let (_, v_u_16) = Variant::parse(&[0, 0, 0, 133, 0, 31, 243]).unwrap();
+ let (_, v_u_8) = Variant::parse(&[0, 0, 0, 134, 0, 78]).unwrap();
+
+ assert_eq!(u_64, v_u_64);
+ assert_eq!(u_32, v_u_32);
+ assert_eq!(u_16, v_u_16);
+ assert_eq!(u_8, v_u_8);
+ }
+
+ #[test]
+ pub fn bool_serialize() {
+ let test_variant_true = Variant::bool(true);
+ let test_variant_false = Variant::bool(false);
+ assert_eq!(test_variant_true.serialize().unwrap(), [0, 0, 0, 1, 0, 1]);
+ assert_eq!(test_variant_false.serialize().unwrap(), [0, 0, 0, 1, 0, 0]);
+ }
+
+ #[test]
+ pub fn bool_deserialize() {
+ let test_bytes: &[u8] = &[0, 0, 0, 1, 0, 1, 0, 0, 0, 1];
+ let (len, res) = Variant::parse(test_bytes).unwrap();
+ assert_eq!(len, 6);
+ assert_eq!(res, Variant::bool(true));
+ }
+
+ #[test]
+ pub fn variantlist_serialize() {
+ let mut test_variantlist = VariantList::new();
+ test_variantlist.push(Variant::bool(true));
+ assert_eq!(
+ test_variantlist.serialize().unwrap(),
+ [0, 0, 0, 1, 0, 0, 0, 1, 0, 1]
+ );
+ }
+
+ #[test]
+ pub fn variantlist_deserialize() {
+ 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).unwrap();
+ let mut test_variantlist = VariantList::new();
+ test_variantlist.push(Variant::bool(true));
+ assert_eq!(len, 10);
+ assert_eq!(res, test_variantlist);
+ }
+
+ #[test]
+ pub fn variantmap_serialize() {
+ 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().unwrap(), bytes);
+ }
+
+ #[test]
+ pub fn variantmap_deserialize() {
+ 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,
+ ];
+ let (len, res) = VariantMap::parse(test_bytes).unwrap();
+ let mut test_variantmap = VariantMap::new();
+ test_variantmap.insert("Configured".to_string(), Variant::bool(true));
+ assert_eq!(len, 34);
+ assert_eq!(res, test_variantmap);
+ }
+
+ #[test]
+ pub fn buffer_info_serialize() {
+ let test_buffer_info = BufferInfo {
+ id: 0,
+ network_id: 0,
+ buffer_type: primitive::BufferType::Status,
+ name: "test".to_string(),
+ };
+
+ let bytes = vec![
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x4, 0x74, 0x65, 0x73, 0x74,
+ ];
+ assert_eq!(test_buffer_info.serialize().unwrap(), bytes);
+ }
+
+ #[test]
+ pub fn buffer_info_deserialize() {
+ let test_buffer_info = BufferInfo {
+ id: 0,
+ network_id: 0,
+ buffer_type: primitive::BufferType::Status,
+ name: "test".to_string(),
+ };
+
+ let bytes = vec![
+ 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0,
+ 0x5, 0x74, 0x65, 0x73, 0x74, 0x0,
+ ];
+ let (len, res) = BufferInfo::parse(&bytes).unwrap();
+
+ assert_eq!(len, 23);
+ assert_eq!(res, test_buffer_info);
+ }
+
+ #[test]
+ fn strings_serialize() {
+ let test_string = "This is a Test!1!!".to_string();
+ let test_string_list = vec!["test1".to_string(), "test 2".to_string()];
+
+ assert_eq!(
+ Variant::String(test_string.clone()).serialize().unwrap(),
+ [
+ 0, 0, 0, 10, 0, 0, 0, 0, 36, 0, 0x54, 0, 0x68, 0, 0x69, 0, 0x73, 0, 0x20, 0, 0x69,
+ 0, 0x73, 0, 0x20, 0, 0x61, 0, 0x20, 0, 0x54, 0, 0x65, 0, 0x73, 0, 0x74, 0, 0x21, 0,
+ 0x31, 0, 0x21, 0, 0x21
+ ]
+ );
+ assert_eq!(
+ Variant::ByteArray(test_string.clone()).serialize().unwrap(),
+ [
+ 0, 0, 0, 12, 0, 0, 0, 0, 18, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61,
+ 0x20, 0x54, 0x65, 0x73, 0x74, 0x21, 0x31, 0x21, 0x21
+ ]
+ );
+ assert_eq!(
+ Variant::StringList(test_string_list).serialize().unwrap(),
+ [
+ 0, 0, 0, 11, 0, 0, 0, 0, 2, 0, 0, 0, 10, 0, 0x74, 0, 0x65, 0, 0x73, 0, 0x74, 0,
+ 0x31, 0, 0, 0, 12, 0, 0x74, 0, 0x65, 0, 0x73, 0, 0x74, 0, 0x20, 0, 0x32
+ ]
+ );
+ }
+
+ #[test]
+ fn strings_deserialize() {
+ let test_string = "This is a Test!1!!".to_string();
+ let test_string_list = vec!["test1".to_string(), "test 2".to_string()];
+
+ let test_string_src = vec![
+ 0, 0, 0, 10, 0, 0, 0, 0, 36, 0, 0x54, 0, 0x68, 0, 0x69, 0, 0x73, 0, 0x20, 0, 0x69, 0,
+ 0x73, 0, 0x20, 0, 0x61, 0, 0x20, 0, 0x54, 0, 0x65, 0, 0x73, 0, 0x74, 0, 0x21, 0, 0x31,
+ 0, 0x21, 0, 0x21,
+ ];
+
+ let test_string_src_utf8 = vec![
+ 0, 0, 0, 12, 0, 0, 0, 0, 18, 0x54, 0x68, 0x69, 0x73, 0x20, 0x69, 0x73, 0x20, 0x61,
+ 0x20, 0x54, 0x65, 0x73, 0x74, 0x21, 0x31, 0x21, 0x21, 0,
+ ];
+
+ let test_string_list_src = vec![
+ 0, 0, 0, 11, 0, 0, 0, 0, 2, 0, 0, 0, 10, 0, 0x74, 0, 0x65, 0, 0x73, 0, 0x74, 0, 0x31,
+ 0, 0, 0, 12, 0, 0x74, 0, 0x65, 0, 0x73, 0, 0x74, 0, 0x20, 0, 0x32,
+ ];
+
+ assert_eq!(
+ (45, Variant::String(test_string.clone())),
+ Variant::parse(&test_string_src).unwrap()
+ );
+ assert_eq!(
+ (27, Variant::ByteArray(test_string.clone())),
+ Variant::parse(&test_string_src_utf8).unwrap()
+ );
+ assert_eq!(
+ (39, Variant::StringList(test_string_list)),
+ Variant::parse(&test_string_list_src).unwrap()
+ );
+ }
+
+ #[test]
+ fn datetime_serialize() {
+ let datetime =
+ Variant::DateTime(DateTime::parse("2020-02-19 13:00 +0200", "%Y-%m-%d %R %z").unwrap());
+ let date = Variant::Date(Date::parse("2020-02-19", "%Y-%m-%d").unwrap());
+ let time = Variant::Time(Time::parse("13:00", "%R").unwrap());
+
+ assert_eq!(
+ datetime.serialize().unwrap(),
+ [0, 0, 0, 0x10, 0, 0, 37, 133, 19, 2, 202, 28, 128, 3, 0, 0, 28, 32]
+ );
+
+ assert_eq!(
+ date.serialize().unwrap(),
+ [0, 0, 0, 0x0e, 0, 0, 37, 133, 19]
+ );
+
+ assert_eq!(
+ time.serialize().unwrap(),
+ [0, 0, 0, 0x0f, 0, 2, 202, 28, 128]
+ );
+ }
+
+ #[test]
+ fn datetime_deserialize() {
+ let datetime =
+ Variant::DateTime(DateTime::parse("2020-02-19 13:00 +0200", "%Y-%m-%d %R %z").unwrap());
+ let date = Variant::Date(Date::parse("2020-02-19", "%Y-%m-%d").unwrap());
+ let time = Variant::Time(Time::parse("13:00", "%R").unwrap());
+
+ assert_eq!(
+ (18, datetime),
+ Variant::parse(&[0, 0, 0, 0x10, 0, 0, 37, 133, 19, 2, 202, 28, 128, 3, 0, 0, 28, 32])
+ .unwrap()
+ );
+
+ assert_eq!(
+ (9, date),
+ Variant::parse(&[0, 0, 0, 0x0e, 0, 0, 37, 133, 19]).unwrap()
+ );
+
+ assert_eq!(
+ (9, time),
+ Variant::parse(&[0, 0, 0, 0x0f, 0, 2, 202, 28, 128]).unwrap()
+ );
+ }
+}
diff --git a/src/primitive/variantlist.rs b/src/primitive/variantlist.rs
index a802864..7e74122 100644
--- a/src/primitive/variantlist.rs
+++ b/src/primitive/variantlist.rs
@@ -7,8 +7,6 @@ use log::trace;
use crate::{Deserialize, Serialize};
-extern crate bytes;
-
use crate::primitive::Variant;
/// VariantLists are represented as a Vec of Variants.
diff --git a/src/primitive/variantmap.rs b/src/primitive/variantmap.rs
index 4f017f3..d43028c 100644
--- a/src/primitive/variantmap.rs
+++ b/src/primitive/variantmap.rs
@@ -11,8 +11,6 @@ use crate::Serialize;
use crate::primitive::Variant;
use crate::util;
-extern crate bytes;
-
/// VariantMaps are represented as a HashMap with String as key and Variant as value
///
/// They are serialized as the amount of keys as an i32 then for each entry a String and a Variant.
diff --git a/src/tests/base_types.rs b/src/tests/base_types.rs
deleted file mode 100644
index bbd2fc3..0000000
--- a/src/tests/base_types.rs
+++ /dev/null
@@ -1,84 +0,0 @@
-use crate::{Deserialize, DeserializeUTF8};
-use crate::{Serialize, SerializeUTF8};
-
-use crate::primitive::*;
-
-#[test]
-pub fn serialize_string() {
- let test_string: String = String::from("Configured");
-
- assert_eq!(
- test_string.serialize().unwrap(),
- [
- 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().unwrap(),
- [0, 0, 0, 11, 67, 111, 110, 102, 105, 103, 117, 114, 101, 100, 0]
- );
-}
-
-#[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).unwrap();
- 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).unwrap();
- assert_eq!(len, 14);
- assert_eq!(res, "Configured");
-}
-
-#[test]
-pub fn deserialize_string_utf8_null_terminated() {
- let test_bytes: &[u8] = &[
- 0, 0, 0, 11, 67, 111, 110, 102, 105, 103, 117, 114, 101, 100, 0, 0, 0, 0, 1,
- ];
- let (len, res) = String::parse_utf8(test_bytes).unwrap();
- assert_eq!(len, 15);
- 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().unwrap(),
- [
- 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, 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,
- ];
- let mut test_list = StringList::new();
- test_list.push("Configured".to_string());
- let (len, res) = StringList::parse(test_bytes).unwrap();
- assert_eq!(len, 28);
- assert_eq!(test_list, res);
-}
diff --git a/src/tests/datetime.rs b/src/tests/datetime.rs
deleted file mode 100644
index 85d84cb..0000000
--- a/src/tests/datetime.rs
+++ /dev/null
@@ -1,28 +0,0 @@
-use crate::Deserialize;
-use crate::Serialize;
-
-use crate::primitive::DateTime;
-
-#[test]
-pub fn serialize_datetime() {
- // Create datetime object
- let datetime = DateTime::parse("2020-02-19 13:00 +0200", "%Y-%m-%d %R %z").unwrap();
- println!("datetime: {:?}", datetime);
-
- let sers = datetime.serialize().unwrap();
- let bytes = vec![0, 37, 133, 19, 2, 202, 28, 128, 3, 0, 0, 28, 32];
-
- assert_eq!(sers, bytes)
-}
-
-#[test]
-pub fn deserialize_datetime() {
- // Create datetime object
- let datetime = DateTime::parse("2020-02-19 13:00 +0200", "%Y-%m-%d %R %z").unwrap();
- println!("datetime: {:?}", datetime);
-
- let bytes = vec![0, 37, 133, 19, 2, 202, 28, 128, 3, 0, 0, 28, 32];
- let (_, res): (usize, DateTime) = Deserialize::parse(&bytes).unwrap();
-
- assert_eq!(res, datetime)
-}
diff --git a/src/tests/frame.rs b/src/tests/frame.rs
deleted file mode 100644
index 878379f..0000000
--- a/src/tests/frame.rs
+++ /dev/null
@@ -1,240 +0,0 @@
-use tokio::io::{AsyncRead, AsyncWrite};
-use tokio_test::task;
-use tokio_test::{
- assert_err, assert_ok, assert_pending, assert_ready, assert_ready_err, assert_ready_ok,
-};
-use tokio_util::codec::*;
-
-use bytes::{BufMut, Bytes, BytesMut};
-use futures::{pin_mut, Sink, Stream};
-
-use std::collections::VecDeque;
-use std::io;
-use std::pin::Pin;
-use std::task::Poll::*;
-use std::task::{Context, Poll};
-
-use flate2::Compress;
-use flate2::Compression;
-use flate2::Decompress;
-use flate2::FlushCompress;
-use flate2::FlushDecompress;
-
-use crate::frame::QuasselCodec;
-
-macro_rules! mock {
- ($($x:expr,)*) => {{
- let mut v = VecDeque::new();
- v.extend(vec![$($x),*]);
- Mock { calls: v }
- }};
-}
-
-macro_rules! assert_next_eq {
- ($io:ident, $expect:expr) => {{
- task::spawn(()).enter(|cx, _| {
- let res = assert_ready!($io.as_mut().poll_next(cx));
- match res {
- Some(Ok(v)) => assert_eq!(v, $expect.as_ref()),
- Some(Err(e)) => panic!("error = {:?}", e),
- None => panic!("none"),
- }
- });
- }};
-}
-
-macro_rules! assert_next_pending {
- ($io:ident) => {{
- task::spawn(()).enter(|cx, _| match $io.as_mut().poll_next(cx) {
- Ready(Some(Ok(v))) => panic!("value = {:?}", v),
- Ready(Some(Err(e))) => panic!("error = {:?}", e),
- Ready(None) => panic!("done"),
- Pending => {}
- });
- }};
-}
-
-macro_rules! assert_next_err {
- ($io:ident) => {{
- task::spawn(()).enter(|cx, _| match $io.as_mut().poll_next(cx) {
- Ready(Some(Ok(v))) => panic!("value = {:?}", v),
- Ready(Some(Err(_))) => {}
- Ready(None) => panic!("done"),
- Pending => panic!("pending"),
- });
- }};
-}
-
-macro_rules! assert_done {
- ($io:ident) => {{
- task::spawn(()).enter(|cx, _| {
- let res = assert_ready!($io.as_mut().poll_next(cx));
- match res {
- Some(Ok(v)) => panic!("value = {:?}", v),
- Some(Err(e)) => panic!("error = {:?}", e),
- None => {}
- }
- });
- }};
-}
-
-// ======================
-// ===== Test =====
-// ======================
-
-#[test]
-pub fn read_single_frame() {
- let io = FramedRead::new(
- mock! {
- data(b"\x00\x00\x00\x09abcdefghi"),
- },
- QuasselCodec::new(),
- );
- pin_mut!(io);
-
- assert_next_eq!(io, b"abcdefghi");
- assert_done!(io);
-}
-
-#[test]
-pub fn read_multi_frame() {
- let mut d: Vec<u8> = vec![];
- d.extend_from_slice(b"\x00\x00\x00\x09abcdefghi");
- d.extend_from_slice(b"\x00\x00\x00\x03123");
- d.extend_from_slice(b"\x00\x00\x00\x0bhello world");
-
- let io = FramedRead::new(
- mock! {
- data(&d),
- },
- QuasselCodec::new(),
- );
- pin_mut!(io);
-
- assert_next_eq!(io, b"abcdefghi");
- assert_next_eq!(io, b"123");
- assert_next_eq!(io, b"hello world");
- assert_done!(io);
-}
-
-#[test]
-pub fn read_single_frame_compressed() {
- let io = FramedRead::new(
- mock! {
- data(b"\x78\x9c\x63\x60\x60\xe0\x4c\x4c\x4a\x4e\x49\x4d\x4b\xcf\xc8\x04\x00\x11\xec\x03\x97"),
- },
- QuasselCodec::builder().compression(true).new_codec(),
- );
- pin_mut!(io);
-
- assert_next_eq!(io, b"abcdefghi");
- assert_done!(io);
-}
-
-#[test]
-pub fn read_multi_frame_compressed() {
- let io = FramedRead::new(
- mock! {
- data(
- b"\x78\x9c\x63\x60\x60\xe0\x4c\x4c\x4a\x4e\x49\x4d\x4b\xcf\xc8\x04\x00\x11\xec\x03\x97\x78\x9c\x63\x60\x60\x60\x36\x34\x32\x06\x00\x01\x3d\x00\x9a\x78\x9c\x63\x60\x60\xe0\xce\x48\xcd\xc9\xc9\x57\x28\xcf\x2f\xca\x49\x01\x00\x1a\x93\x04\x68",
- ),
- },
- QuasselCodec::builder().compression(true).new_codec(),
- );
- pin_mut!(io);
-
- assert_next_eq!(io, b"abcdefghi");
- assert_next_eq!(io, b"123");
- assert_next_eq!(io, b"hello world");
- assert_done!(io);
-}
-
-// ======================
-// ===== Test utils =====
-// ======================
-
-struct Mock {
- calls: VecDeque<Poll<io::Result<Op>>>,
-}
-
-enum Op {
- Data(Vec<u8>),
- Flush,
-}
-
-use self::Op::*;
-
-impl AsyncRead for Mock {
- fn poll_read(
- mut self: Pin<&mut Self>,
- _cx: &mut Context<'_>,
- dst: &mut [u8],
- ) -> Poll<io::Result<usize>> {
- match self.calls.pop_front() {
- Some(Ready(Ok(Op::Data(data)))) => {
- debug_assert!(dst.len() >= data.len());
- dst[..data.len()].copy_from_slice(&data[..]);
- Ready(Ok(data.len()))
- }
- Some(Ready(Ok(_))) => panic!(),
- Some(Ready(Err(e))) => Ready(Err(e)),
- Some(Pending) => Pending,
- None => Ready(Ok(0)),
- }
- }
-}
-
-impl AsyncWrite for Mock {
- fn poll_write(
- mut self: Pin<&mut Self>,
- _cx: &mut Context<'_>,
- src: &[u8],
- ) -> Poll<Result<usize, io::Error>> {
- match self.calls.pop_front() {
- Some(Ready(Ok(Op::Data(data)))) => {
- let len = data.len();
- assert!(src.len() >= len, "expect={:?}; actual={:?}", data, src);
- assert_eq!(&data[..], &src[..len]);
- Ready(Ok(len))
- }
- Some(Ready(Ok(_))) => panic!(),
- Some(Ready(Err(e))) => Ready(Err(e)),
- Some(Pending) => Pending,
- None => Ready(Ok(0)),
- }
- }
-
- fn poll_flush(mut self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
- match self.calls.pop_front() {
- Some(Ready(Ok(Op::Flush))) => Ready(Ok(())),
- Some(Ready(Ok(_))) => panic!(),
- Some(Ready(Err(e))) => Ready(Err(e)),
- Some(Pending) => Pending,
- None => Ready(Ok(())),
- }
- }
-
- fn poll_shutdown(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Result<(), io::Error>> {
- Ready(Ok(()))
- }
-}
-
-impl<'a> From<&'a [u8]> for Op {
- fn from(src: &'a [u8]) -> Op {
- Op::Data(src.into())
- }
-}
-
-impl From<Vec<u8>> for Op {
- fn from(src: Vec<u8>) -> Op {
- Op::Data(src)
- }
-}
-
-fn data(bytes: &[u8]) -> Poll<io::Result<Op>> {
- Ready(Ok(bytes.into()))
-}
-
-fn flush() -> Poll<io::Result<Op>> {
- Ready(Ok(Flush))
-}
diff --git a/src/tests/handshake_types.rs b/src/tests/handshake_types.rs
deleted file mode 100644
index 1e789c1..0000000
--- a/src/tests/handshake_types.rs
+++ /dev/null
@@ -1,44 +0,0 @@
-use crate::primitive::{Variant, VariantMap};
-use crate::{HandshakeDeserialize, HandshakeSerialize};
-
-#[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, 2, 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().unwrap(), bytes);
-}
-
-#[test]
-pub fn deserialize_variantmap() {
- let test_bytes: &[u8] = &[
- 0, 0, 0, 2, 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).unwrap();
-
- assert_eq!(len, 39);
- assert_eq!(res, test_variantmap);
-}
-
-#[test]
-pub fn deserialize_variantmap_utf8() {
- let test_bytes: &[u8] = &[
- 0, 0, 0, 2, 0, 0, 0, 12, 0, 0, 0, 0, 10, 67, 111, 110, 102, 105, 103, 117, 114, 101, 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).unwrap();
-
- assert_eq!(len, 29);
- assert_eq!(res, test_variantmap);
-}
diff --git a/src/tests/mod.rs b/src/tests/mod.rs
deleted file mode 100644
index 1e99bfe..0000000
--- a/src/tests/mod.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-pub mod base_types;
-pub mod datetime;
-
-#[allow(unused_imports)]
-#[allow(unused_macros)]
-#[allow(dead_code)]
-#[cfg(feature = "framing")]
-pub mod frame;
-
-pub mod handshake_types;
-
-pub mod variant_types;
-
-extern crate futures;
-extern crate tokio;
-extern crate tokio_test;
-extern crate tokio_util;
diff --git a/src/tests/variant_types.rs b/src/tests/variant_types.rs
deleted file mode 100644
index 7ba4166..0000000
--- a/src/tests/variant_types.rs
+++ /dev/null
@@ -1,100 +0,0 @@
-use crate::Deserialize;
-use crate::Serialize;
-
-use crate::primitive::{BufferInfo, BufferType, Message, 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().unwrap(), [0, 0, 0, 1, 0, 1]);
- assert_eq!(test_variant_false.serialize().unwrap(), [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).unwrap();
- 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().unwrap(),
- [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).unwrap();
- 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().unwrap(), 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,
- ];
- let (len, res) = VariantMap::parse(test_bytes).unwrap();
- let mut test_variantmap = VariantMap::new();
- test_variantmap.insert("Configured".to_string(), Variant::bool(true));
- assert_eq!(len, 34);
- assert_eq!(res, test_variantmap);
-}
-
-#[test]
-pub fn serialize_buffer_info() {
- let test_buffer_info = BufferInfo {
- id: 0,
- network_id: 0,
- buffer_type: BufferType::Status,
- name: "test".to_string(),
- };
-
- let bytes = vec![
- 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5,
- 0x74, 0x65, 0x73, 0x74, 0x0,
- ];
- assert_eq!(test_buffer_info.serialize().unwrap(), bytes);
-}
-
-#[test]
-pub fn deserialize_buffer_info() {
- let test_buffer_info = BufferInfo {
- id: 0,
- network_id: 0,
- buffer_type: BufferType::Status,
- name: "test".to_string(),
- };
-
- let bytes = vec![
- 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x1, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x5,
- 0x74, 0x65, 0x73, 0x74, 0x0,
- ];
- let (len, res) = BufferInfo::parse(&bytes).unwrap();
-
- assert_eq!(len, 23);
- assert_eq!(res, test_buffer_info);
-}
diff --git a/src/util.rs b/src/util.rs
index eeeda4e..6051a96 100644
--- a/src/util.rs
+++ b/src/util.rs
@@ -38,3 +38,22 @@ pub fn insert_bytes(pos: usize, buf: &mut Vec<u8>, input: &mut [u8]) {
buf.insert(pos, *i)
}
}
+
+#[macro_export]
+macro_rules! map {
+ // map-like
+ ($($k:expr => $v:expr),* $(,)?) => {
+ std::iter::Iterator::collect(std::array::IntoIter::new([$(($k, $v),)*]))
+ };
+ // set-like
+ ($($v:expr),* $(,)?) => {
+ std::iter::Iterator::collect(std::array::IntoIter::new([$($v,)*]))
+ };
+}
+
+#[macro_export]
+macro_rules! s {
+ ($values:expr) => {
+ std::string::String::from($values)
+ };
+}