aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml4
-rw-r--r--derive/src/from/mod.rs90
-rw-r--r--derive/src/from_network_impl.rs127
-rw-r--r--derive/src/lib.rs210
-rw-r--r--derive/src/network/list.rs83
-rw-r--r--derive/src/network/map.rs78
-rw-r--r--derive/src/network/maplist.rs167
-rw-r--r--derive/src/network/mod.rs230
-rw-r--r--derive/src/to_network_impl.rs96
-rw-r--r--examples/quasselproxy/src/main.rs6
-rw-r--r--src/lib.rs58
-rw-r--r--src/message/handshake/connack.rs4
-rw-r--r--src/message/handshake/init.rs3
-rw-r--r--src/message/handshake/mod.rs4
-rw-r--r--src/message/handshake/protocol.rs3
-rw-r--r--src/message/handshake/sessioninit.rs33
-rw-r--r--src/message/handshake/types.rs5
-rw-r--r--src/message/signalproxy/heartbeat.rs2
-rw-r--r--src/message/signalproxy/initdata.rs18
-rw-r--r--src/message/signalproxy/initrequest.rs2
-rw-r--r--src/message/signalproxy/mod.rs6
-rw-r--r--src/message/signalproxy/objects/aliasmanager.rs131
-rw-r--r--src/message/signalproxy/objects/buffersyncer.rs263
-rw-r--r--src/message/signalproxy/objects/coreinfo.rs60
-rw-r--r--src/message/signalproxy/objects/highlightrulemanager.rs113
-rw-r--r--src/message/signalproxy/objects/identity.rs119
-rw-r--r--src/message/signalproxy/objects/ircchannel.rs245
-rw-r--r--src/message/signalproxy/objects/ircuser.rs53
-rw-r--r--src/message/signalproxy/objects/mod.rs59
-rw-r--r--src/message/signalproxy/objects/network.rs258
-rw-r--r--src/message/signalproxy/objects/networkinfo.rs18
-rw-r--r--src/message/signalproxy/rpccall.rs2
-rw-r--r--src/message/signalproxy/syncmessage.rs2
-rw-r--r--src/primitive/bufferinfo.rs3
-rw-r--r--src/primitive/datetime.rs3
-rw-r--r--src/primitive/message.rs8
-rw-r--r--src/primitive/signedint.rs2
-rw-r--r--src/primitive/string.rs10
-rw-r--r--src/primitive/stringlist.rs2
-rw-r--r--src/primitive/unsignedint.rs2
-rw-r--r--src/primitive/variant.rs30
-rw-r--r--src/primitive/variantlist.rs2
-rw-r--r--src/primitive/variantmap.rs7
43 files changed, 1621 insertions, 1000 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 0789077..41a88e6 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -8,6 +8,7 @@ homepage = "https://gitlab.com/cocainefarm/libquassel"
repository = "https://gitlab.com/cocainefarm/libquassel"
edition = "2018"
autobins = true
+include = ["src/**/*", "LICENSE", "README.md"]
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
@@ -20,8 +21,9 @@ time = "0.2"
num-traits = "0.2"
num-derive = "0.3"
-libquassel-derive = { path = "./derive" }
+itertools = "0.10"
+libquassel-derive = { path = "./derive" }
bytes = { version = "1.0", optional = true }
flate2 = { version = "1.0", features = ["tokio"], optional = true }
diff --git a/derive/src/from/mod.rs b/derive/src/from/mod.rs
new file mode 100644
index 0000000..2855d1a
--- /dev/null
+++ b/derive/src/from/mod.rs
@@ -0,0 +1,90 @@
+use quote::quote;
+use syn;
+use syn::parse_macro_input;
+
+use darling::{FromDeriveInput, FromVariant};
+
+#[derive(Debug, FromDeriveInput)]
+#[darling(attributes(from), supports(enum_any))]
+struct Enum {
+ ident: syn::Ident,
+ attrs: Vec<syn::Attribute>,
+}
+
+#[derive(Debug, FromVariant)]
+#[darling(attributes(from))]
+struct EnumField {
+ ident: syn::Ident,
+ fields: darling::ast::Fields<syn::Type>,
+
+ #[darling(default)]
+ ignore: bool,
+}
+
+pub fn from(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
+ let input = parse_macro_input!(input as syn::DeriveInput);
+ // println!("{:#?}", input);
+
+ let network = Enum::from_derive_input(&input).unwrap();
+ // println!("{:#?}", network);
+
+ let enum_name = network.ident;
+
+ let fields: Vec<EnumField> = match &input.data {
+ syn::Data::Enum(data) => data
+ .variants
+ .iter()
+ .map(|field| EnumField::from_variant(field).expect("Could not parse field"))
+ .collect(),
+ _ => panic!("from: not an enum"),
+ };
+
+ let derives = fields
+ .iter()
+ .filter(|field| field.fields.fields.len() > 0 && !field.ignore)
+ .map(|field| {
+ let variant = &field.ident;
+ let inner_type = &field.fields.fields[0];
+ let inner_type_str = format!("{}", quote! { #inner_type });
+
+ quote! {
+ impl From<#inner_type> for #enum_name {
+ fn from(input: #inner_type) -> Self {
+ Self::#variant(input)
+ }
+ }
+
+ impl std::convert::TryFrom<#enum_name> for #inner_type {
+ type Error = String;
+
+ fn try_from(input: #enum_name) -> Result<Self, Self::Error> {
+ match input {
+ #enum_name::#variant(input) => Ok(input),
+ v => Err(format!("variant::from: {} wrong variant expected: {:?}", #inner_type_str, v)),
+ }
+ }
+ }
+
+ impl std::convert::TryFrom<&#enum_name> for #inner_type {
+ type Error = String;
+
+ fn try_from(input: &#enum_name) -> Result<Self, Self::Error> {
+ match input {
+ #enum_name::#variant(input) => Ok(input.clone()),
+ v => Err(format!("variant::from: {} wrong variant expected: {:?}", #inner_type_str, v)),
+ }
+ }
+ }
+ }
+ });
+
+ // println!("{:#?}", fields);
+
+ let gen = quote! {
+ #(#derives)*
+ };
+
+ // println!("{}", gen);
+
+ gen.into()
+}
diff --git a/derive/src/from_network_impl.rs b/derive/src/from_network_impl.rs
deleted file mode 100644
index ff05f1c..0000000
--- a/derive/src/from_network_impl.rs
+++ /dev/null
@@ -1,127 +0,0 @@
-use proc_macro2::TokenStream;
-use quote::quote;
-
-use crate::{get_field_type, NetworkField};
-
-pub(crate) fn map(fields: &Vec<NetworkField>) -> Vec<TokenStream> {
- fields
- .iter()
- .map(|field| {
- let field_rename = match &field.rename {
- Some(name) => name.clone(),
- None => format!("{}", field.ident.as_ref().unwrap()).into(),
- };
-
- let field_name = field.ident.as_ref().unwrap();
-
- let field_type = get_field_type(&field);
-
- if field.from_map.is_some() {
- let field_map: syn::ExprClosure =
- syn::parse_str(&field.from_map.as_ref().unwrap()).unwrap();
-
- quote! {
- #field_name: match &input.get(#field_rename).unwrap() {
- crate::primitive::Variant::#field_type(input) => input.iter().map(#field_map).collect(),
- _ => unimplemented!()
- },
- }
- } else {
- quote! {
- #field_name: match &input.get(#field_rename).unwrap() {
- crate::primitive::Variant::#field_type(input) => input.clone(),
- _ => unimplemented!()
- },
- }
- }
- })
- .collect()
-}
-
-pub(crate) fn map_list(fields: &Vec<NetworkField>) -> Vec<TokenStream> {
- fields
- .iter()
- .map(|field| {
- let field_rename = match &field.rename {
- Some(name) => name.clone(),
- None => format!("{}", field.ident.as_ref().unwrap()).into(),
- };
-
- let field_name = field.ident.as_ref().unwrap();
-
- let field_type = get_field_type(&field);
-
- if field.from_map.is_some() {
- let field_map: syn::ExprClosure =
- syn::parse_str(&field.from_map.as_ref().unwrap()).unwrap();
-
- quote! {
- #field_name: match input.get_mut(#field_rename).unwrap() {
- crate::primitive::Variant::VariantList(input) => match &input.remove(0) {
- crate::primitive::Variant::#field_type(input) => input.iter().map(#field_map).collect(),
- _ => unimplemented!()
- },
- _ => unimplemented!()
- },
- }
- } else {
- quote! {
- #field_name: match input.get_mut(#field_rename).unwrap() {
- crate::primitive::Variant::VariantList(input) => match &input.remove(0) {
- crate::primitive::Variant::#field_type(input) => input.clone(),
- _ => unimplemented!()
- },
- _ => unimplemented!()
- },
- }
- }
- })
- .collect()
-}
-
-pub(crate) fn list(fields: &Vec<NetworkField>) -> Vec<TokenStream> {
- fields
- .iter()
- .map(|field| {
- let field_rename = match &field.rename {
- Some(name) => name.clone(),
- None => format!("{}", field.ident.as_ref().unwrap()).into(),
- };
-
- let field_name = field.ident.as_ref().unwrap();
-
- let field_type = get_field_type(&field);
-
- if field.from_map.is_some() {
- let field_map: syn::ExprClosure =
- syn::parse_str(&field.from_map.as_ref().unwrap()).unwrap();
-
- quote! {
- #field_name: match_variant!(
- input
- .iter()
- .nth(input
- .iter()
- .position(|x| *x == crate::primitive::Variant::ByteArray(#field_rename.to_string()))
- .unwrap())
- .unwrap(),
- crate::primitive::Variant::#field_type
- ).iter().map(#field_map).collect(),
- }
- } else {
- quote! {
- #field_name: match_variant!(
- input
- .iter()
- .nth(input
- .iter()
- .position(|x| *x == Variant::ByteArray(#field_rename.to_string()))
- .unwrap() + 1)
- .unwrap(),
- crate::primitive::Variant::#field_type
- ),
- }
- }
- })
- .collect()
-}
diff --git a/derive/src/lib.rs b/derive/src/lib.rs
index ddbb49a..831767a 100644
--- a/derive/src/lib.rs
+++ b/derive/src/lib.rs
@@ -1,216 +1,14 @@
-use quote::quote;
use syn;
-use syn::parse_macro_input;
-
-use darling::{FromDeriveInput, FromField, FromMeta, FromVariant};
-
-mod from_network_impl;
-mod to_network_impl;
-
-#[derive(Debug, FromDeriveInput)]
-#[darling(attributes(network), supports(struct_any))]
-struct Network {
- ident: syn::Ident,
- attrs: Vec<syn::Attribute>,
- repr: Repr,
-}
-
-#[derive(Debug, Clone, Copy, FromMeta)]
-#[darling(default)]
-enum Repr {
- Aos,
- List,
- Map,
- Maplist,
-}
-
-impl Default for Repr {
- fn default() -> Self {
- Repr::List
- }
-}
-
-#[derive(Debug, FromField)]
-#[darling(attributes(network))]
-struct NetworkField {
- ident: Option<syn::Ident>,
- ty: syn::Type,
-
- #[darling(default)]
- rename: Option<String>,
- #[darling(default)]
- override_type: Option<String>,
- #[darling(default)]
- to_map: Option<String>,
- #[darling(default)]
- from_map: Option<String>,
-}
+mod from;
+mod network;
#[proc_macro_derive(Network, attributes(network))]
pub fn network(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
- let input = parse_macro_input!(input as syn::DeriveInput);
- // println!("{:#?}", input);
-
- let network = Network::from_derive_input(&input).unwrap();
- // println!("{:#?}", network);
-
- let fields: Vec<NetworkField> = match &input.data {
- syn::Data::Struct(data) => match &data.fields {
- syn::Fields::Named(fields) => fields
- .named
- .iter()
- .map(|field| NetworkField::from_field(field).expect("Could not parse field"))
- .collect(),
- _ => unimplemented!(),
- },
- _ => unimplemented!(),
- };
-
- // println!("{:#?}", fields);
-
- let name = &input.ident;
-
- let to_network_impl_center = match network.repr {
- // Repr::Aos => {}
- Repr::Map => to_network_impl::map(&fields),
- Repr::Maplist => to_network_impl::map_list(&fields),
- Repr::List => to_network_impl::list(&fields),
- _ => unimplemented!(),
- };
-
- let from_network_impl_center = match network.repr {
- // Repr::Aos => {}
- Repr::Map => from_network_impl::map(&fields),
- Repr::Maplist => from_network_impl::map_list(&fields),
- Repr::List => from_network_impl::list(&fields),
- _ => unimplemented!(),
- };
-
- let network_impl_item = match network.repr {
- Repr::Aos => quote! {crate::primitive::VariantList;},
- Repr::Map => quote! {crate::primitive::VariantMap;},
- Repr::Maplist => quote! {crate::primitive::VariantMap;},
- Repr::List => quote! {crate::primitive::VariantList;},
- };
-
- // do things with `args`
- let gen = quote! {
- impl crate::message::signalproxy::Network for #name {
- type Item = #network_impl_item
-
- fn to_network(&self) -> Self::Item {
- let mut res = Self::Item::new();
-
- #(#to_network_impl_center)*
-
- return res;
- }
-
- fn from_network(input: &mut Self::Item) -> Self {
- Self {
- #(#from_network_impl_center)*
- }
- }
- }
- };
-
- println!("{}", gen);
-
- gen.into()
-}
-
-fn get_field_type(field: &NetworkField) -> syn::Type {
- match &field.override_type {
- Some(override_type) => syn::Type::from(syn::TypePath {
- qself: None,
- path: syn::Path {
- leading_colon: None,
- segments: {
- let mut res =
- syn::punctuated::Punctuated::<syn::PathSegment, syn::token::Colon2>::new();
-
- res.push(syn::PathSegment {
- ident: syn::Ident::new(override_type, proc_macro2::Span::call_site()),
- arguments: syn::PathArguments::None,
- });
-
- res
- },
- },
- }),
- None => field.ty.clone(),
- }
-}
-
-#[derive(Debug, FromDeriveInput)]
-#[darling(attributes(from), supports(enum_any))]
-struct Enum {
- ident: syn::Ident,
- attrs: Vec<syn::Attribute>,
-}
-
-#[derive(Debug, FromVariant)]
-#[darling(attributes(from))]
-struct EnumField {
- ident: syn::Ident,
- fields: darling::ast::Fields<syn::Type>,
-
- #[darling(default)]
- ignore: bool,
+ network::network(input)
}
#[proc_macro_derive(From, attributes(from))]
pub fn from(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
- let input = parse_macro_input!(input as syn::DeriveInput);
- // println!("{:#?}", input);
-
- let network = Enum::from_derive_input(&input).unwrap();
- // println!("{:#?}", network);
-
- let enum_name = network.ident;
-
- let fields: Vec<EnumField> = match &input.data {
- syn::Data::Enum(data) => data
- .variants
- .iter()
- .map(|field| EnumField::from_variant(field).expect("Could not parse field"))
- .collect(),
- _ => unimplemented!(),
- };
-
- let derives = fields
- .iter()
- .filter(|field| field.fields.fields.len() > 0 && !field.ignore)
- .map(|field| {
- let variant = &field.ident;
- let inner_type = &field.fields.fields[0];
-
- quote! {
- impl From<#inner_type> for #enum_name {
- fn from(input: #inner_type) -> Self {
- Self::#variant(input)
- }
- }
-
- impl Into<#inner_type> for #enum_name {
- fn into(self) -> #inner_type {
- match self {
- Self::#variant(input) => input,
- _ => unimplemented!(),
- }
- }
- }
- }
- });
-
- // println!("{:#?}", fields);
-
- let gen = quote! {
- #(#derives)*
- };
-
- // println!("{}", gen);
-
- gen.into()
+ from::from(input)
}
diff --git a/derive/src/network/list.rs b/derive/src/network/list.rs
new file mode 100644
index 0000000..75aecd0
--- /dev/null
+++ b/derive/src/network/list.rs
@@ -0,0 +1,83 @@
+use proc_macro2::TokenStream;
+use quote::quote;
+
+use super::{gen_type, get_field_type, get_field_type_colon, get_field_variant_type, NetworkField};
+
+pub(crate) fn to(fields: &Vec<NetworkField>) -> Vec<TokenStream> {
+ fields
+ .iter()
+ .map(|field| {
+ let field_rename = match &field.rename {
+ Some(name) => name.clone(),
+ None => format!("{}", field.ident.as_ref().unwrap()).into(),
+ };
+
+ let field_name = field.ident.as_ref().unwrap();
+ let field_type = get_field_type(&field);
+
+ let field_inner = if field.network {
+ quote! { self.#field_name.to_network() }
+ } else {
+ quote! { self.#field_name.clone() }
+ };
+
+ match &field.variant {
+ Some(variant_type) => {
+ let variant_type = gen_type(variant_type.as_str());
+ quote! {
+ res.push(crate::primitive::Variant::ByteArray(#field_rename.to_string()));
+ res.push(crate::primitive::Variant::#variant_type(#field_inner));
+ }
+ }
+ None => quote! {
+ res.push(crate::primitive::Variant::ByteArray(#field_rename.to_string()));
+ res.push(crate::primitive::Variant::#field_type(#field_inner));
+ },
+ }
+ })
+ .collect()
+}
+
+pub(crate) fn from(fields: &Vec<NetworkField>) -> Vec<TokenStream> {
+ fields
+ .iter()
+ .map(|field| {
+ let field_rename = match &field.rename {
+ Some(name) => name.clone(),
+ None => format!("{}", field.ident.as_ref().unwrap()).into(),
+ };
+
+ let field_name = field.ident.as_ref().unwrap();
+
+ let field_type = get_field_type(&field);
+ let field_variant_type = get_field_variant_type(&field);
+
+ let field_type_colon = get_field_type_colon(field_type.clone());
+
+ let extract_inner = quote! {
+ let mut i = input.iter();
+ i.position(|x| *x == crate::primitive::Variant::ByteArray(String::from(#field_rename)))
+ .unwrap();
+
+ match i.next().unwrap() {
+ crate::primitive::Variant::#field_variant_type(input) => input.clone(),
+ _ => panic!("network::list::from: wrong variant type"),
+ }
+ };
+
+ if field.network {
+ quote! {
+ #field_name: #field_type_colon::from_network(&mut {
+ #extract_inner
+ }),
+ }
+ } else {
+ quote! {
+ #field_name: {
+ #extract_inner
+ },
+ }
+ }
+ })
+ .collect()
+}
diff --git a/derive/src/network/map.rs b/derive/src/network/map.rs
new file mode 100644
index 0000000..60f96b5
--- /dev/null
+++ b/derive/src/network/map.rs
@@ -0,0 +1,78 @@
+use proc_macro2::{Ident, TokenStream};
+use quote::quote;
+
+use super::{get_field_type, get_field_type_colon, get_field_variant_type, NetworkField};
+
+pub(crate) fn to(fields: &Vec<NetworkField>) -> Vec<TokenStream> {
+ fields
+ .iter()
+ .map(|field| {
+ let field_rename = match &field.rename {
+ Some(name) => name.clone(),
+ None => format!("{}", field.ident.as_ref().unwrap()).into(),
+ };
+
+ let field_name = field.ident.as_ref().unwrap();
+ let _field_type = get_field_type(&field);
+ let field_variant_type = get_field_variant_type(&field);
+
+ let field_inner = if field.network {
+ quote! {
+ self.#field_name.to_network()
+ }
+ } else {
+ quote! {
+ self.#field_name.clone()
+ }
+ };
+
+ quote! {
+ res.insert(#field_rename.to_string(),
+ crate::primitive::Variant::#field_variant_type(#field_inner));
+ }
+ })
+ .collect()
+}
+
+pub(crate) fn from(fields: &Vec<NetworkField>) -> Vec<TokenStream> {
+ fields
+ .iter()
+ .map(|field| {
+ let field_rename = match &field.rename {
+ Some(name) => name.clone(),
+ None => format!("{}", field.ident.as_ref().unwrap()).into(),
+ };
+
+ let field_name = field.ident.as_ref().unwrap();
+ let field_type = get_field_type(&field);
+ let _field_variant_type = get_field_variant_type(&field);
+
+ let field_type_colon = get_field_type_colon(field_type.clone());
+
+ if field.network {
+ quote! {
+ #field_name: #field_type_colon::from_network(
+ &mut std::convert::TryInto::try_into(input.remove(#field_rename).unwrap()).unwrap()),
+ }
+ } else {
+ quote! {
+ #field_name: std::convert::TryInto::try_into(input.remove(#field_rename).unwrap()).unwrap(),
+ }
+ }
+ })
+ .collect()
+}
+
+pub(crate) fn to_vec(_type_name: &Ident, _fields: &Vec<NetworkField>) -> TokenStream {
+ quote! {
+ self.iter().map(|item| {
+ item.to_network().into()
+ }).collect()
+ }
+}
+
+pub(crate) fn from_vec(type_name: &Ident, _fields: &Vec<NetworkField>) -> TokenStream {
+ quote! {
+ input.iter().map(|item| #type_name::from_network(&mut std::convert::TryInto::try_into(item).unwrap())).collect()
+ }
+}
diff --git a/derive/src/network/maplist.rs b/derive/src/network/maplist.rs
new file mode 100644
index 0000000..c92b279
--- /dev/null
+++ b/derive/src/network/maplist.rs
@@ -0,0 +1,167 @@
+use proc_macro2::{Ident, TokenStream};
+use quote::quote;
+
+use super::{get_field_type, NetworkField};
+
+pub(crate) fn to(fields: &Vec<NetworkField>) -> Vec<TokenStream> {
+ fields
+ .iter()
+ .map(|field| {
+ let field_rename = match &field.rename {
+ Some(name) => name.clone(),
+ None => format!("{}", field.ident.as_ref().unwrap()).into(),
+ };
+
+ let field_name = field.ident.as_ref().unwrap();
+ let field_type = get_field_type(&field);
+
+ match &field.variant {
+ Some(variant_type) => match variant_type.as_str() {
+ "StringList" => quote! {
+ res.insert(#field_rename.to_string(),
+ crate::primitive::Variant::StringList(
+ std::vec::from_elem(self.#field_name.clone(), 1)));
+ },
+ _ => panic!("network::map::to: not one of the avaible variants")
+ }
+ None => quote! {
+ res.insert(#field_rename.to_string(),
+ crate::primitive::Variant::VariantList(
+ std::vec::from_elem(crate::primitive::Variant::#field_type(self.#field_name.clone()), 1)));
+ }
+ }
+ })
+ .collect()
+}
+
+pub(crate) fn to_vec(_type_name: &Ident, fields: &Vec<NetworkField>) -> TokenStream {
+ let (lists, for_each_inner, map_inserts): (
+ Vec<TokenStream>,
+ Vec<TokenStream>,
+ Vec<TokenStream>,
+ ) = fields.iter().fold(
+ (Vec::new(), Vec::new(), Vec::new()),
+ |(mut lists, mut for_each_inner, mut map_inserts), field| {
+ let field_rename = match &field.rename {
+ Some(name) => name.clone(),
+ None => format!("{}", field.ident.as_ref().unwrap()).into(),
+ };
+
+ let field_name = field.ident.as_ref().unwrap();
+ let field_type = get_field_type(&field);
+
+ match &field.variant {
+ None => {
+ lists.push(quote! {
+ let mut #field_name: crate::primitive::VariantList = Vec::with_capacity(self.len());
+ });
+
+ for_each_inner.push(quote! {
+ #field_name.push(crate::primitive::Variant::#field_type(item.#field_name.clone()));
+ });
+
+ map_inserts.push(quote! {
+ map.insert(String::from(#field_rename), crate::primitive::Variant::VariantList(#field_name));
+ });
+ }
+ Some(variant_type) => match variant_type.as_str() {
+ "StringList" => {
+ lists.push(quote! {
+ let mut #field_name: crate::primitive::StringList = Vec::with_capacity(self.len());
+ });
+
+ for_each_inner.push(quote! {
+ #field_name.push(item.#field_name.clone());
+ });
+
+ map_inserts.push(quote! {
+ map.insert(String::from(#field_rename), crate::primitive::Variant::StringList(#field_name));
+ });
+ }
+ _ => panic!("network::map::to: not one of the avaible variants")
+ }
+ }
+
+ return (lists, for_each_inner, map_inserts);
+ },
+ );
+
+ quote! {
+ #(#lists)*
+
+ let mut map = crate::primitive::VariantMap::new();
+
+ self.iter().for_each(|item| {
+ #(#for_each_inner)*
+ });
+
+ #(#map_inserts)*
+
+ return map;
+ }
+}
+
+pub(crate) fn from(fields: &Vec<NetworkField>) -> Vec<TokenStream> {
+ fields
+ .iter()
+ .map(|field| {
+ let field_rename = match &field.rename {
+ Some(name) => name.clone(),
+ None => format!("{}", field.ident.as_ref().unwrap()).into(),
+ };
+
+ let field_name = field.ident.as_ref().unwrap();
+
+ let _field_type = get_field_type(&field);
+
+ match &field.variant {
+ None => quote! {
+ #field_name: match input.get_mut(#field_rename).unwrap() {
+ crate::primitive::Variant::VariantList(input) => std::convert::TryInto::try_into(input.remove(0)).unwrap(),
+ _ => panic!("#field_name: wrong variant")
+ },
+ },
+ Some(variant_type) => match variant_type.as_str() {
+ "StringList" => quote! {
+ #field_name: match input.get_mut(#field_rename).unwrap() {
+ crate::primitive::Variant::StringList(input) => input.remove(0),
+ _ => panic!("#field_name: wrong variant")
+ },
+ },
+ _ => panic!("network::map::to: not one of the avaible variants"),
+ }
+ }
+ })
+ .collect()
+}
+
+pub(crate) fn from_vec(type_name: &Ident, fields: &Vec<NetworkField>) -> TokenStream {
+ let field = &fields[0];
+
+ let field_rename = match &field.rename {
+ Some(name) => name.clone(),
+ None => format!("{}", field.ident.as_ref().unwrap()).into(),
+ };
+
+ let _field_name = field.ident.as_ref().unwrap();
+
+ let field_variant = match &field.variant {
+ None => quote! {crate::primitive::VariantList},
+ Some(variant_type) => match variant_type.as_str() {
+ "StringList" => quote! {crate::primitive::StringList},
+ "VariantMap" => quote! {crate::primitive::VariantMap},
+ _ => panic!("network::map::from_vec: not one of the avaible variants"),
+ },
+ };
+
+ quote! {
+ let marker: #field_variant = std::convert::TryInto::try_into(input.get(#field_rename).unwrap()).unwrap();
+
+ let mut res = Vec::new();
+ for _ in 0..marker.len() {
+ res.push(#type_name::from_network(input));
+ }
+
+ return res;
+ }
+}
diff --git a/derive/src/network/mod.rs b/derive/src/network/mod.rs
new file mode 100644
index 0000000..f39bedd
--- /dev/null
+++ b/derive/src/network/mod.rs
@@ -0,0 +1,230 @@
+use quote::quote;
+use syn::{self, parse_macro_input};
+
+use darling::{FromDeriveInput, FromField, FromMeta};
+
+mod list;
+mod map;
+mod maplist;
+
+#[derive(Debug, FromDeriveInput)]
+#[darling(attributes(network), supports(struct_any))]
+/// Derive to and from network methods for quassel objects
+pub struct Network {
+ ident: syn::Ident,
+ attrs: Vec<syn::Attribute>,
+ /// Representation to choose for the network format
+ /// see Repr enum
+ repr: Repr,
+}
+
+#[derive(Debug, Clone, Copy, FromMeta)]
+#[darling(default)]
+pub enum Repr {
+ List,
+ Map,
+ Maplist,
+}
+
+impl Default for Repr {
+ fn default() -> Self {
+ Repr::List
+ }
+}
+
+// #[derive(Debug, Clone, Copy, FromMeta)]
+// #[darling(default)]
+// pub enum Variant {
+// Variantlist,
+// Stringlist,
+// Variantmap,
+// Default,
+// }
+
+// impl Default for Variant {
+// fn default() -> Self {
+// Self::Default
+// }
+// }
+
+#[derive(Debug, FromField)]
+#[darling(attributes(network))]
+pub struct NetworkField {
+ ident: Option<syn::Ident>,
+ ty: syn::Type,
+
+ #[darling(default)]
+ rename: Option<String>,
+ #[darling(default)]
+ override_type: Option<String>,
+ /// Variant to encapsulate this field
+ /// VariantList (default) or StringList
+ #[darling(default)]
+ variant: Option<String>,
+ /// field is a nested network repr so
+ /// use to_network and from_network on it
+ #[darling(default)]
+ network: bool,
+}
+
+pub fn network(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
+ let input = parse_macro_input!(input as syn::DeriveInput);
+ // println!("{:#?}", input);
+
+ let network = Network::from_derive_input(&input).unwrap();
+ // println!("{:#?}", network);
+
+ let fields: Vec<NetworkField> = match &input.data {
+ syn::Data::Struct(data) => match &data.fields {
+ syn::Fields::Named(fields) => fields
+ .named
+ .iter()
+ .map(|field| NetworkField::from_field(field).expect("Could not parse field"))
+ .collect(),
+ _ => panic!("network: not a named field"),
+ },
+ _ => panic!("network: not a Struct"),
+ };
+
+ // println!("{:#?}", fields);
+
+ let name = &input.ident;
+
+ let to_network_impl_center = match network.repr {
+ // Repr::Aos => {}
+ Repr::Map => map::to(&fields),
+ Repr::Maplist => maplist::to(&fields),
+ Repr::List => list::to(&fields),
+ };
+
+ let from_network_impl_center = match network.repr {
+ // Repr::Aos => {}
+ Repr::Map => map::from(&fields),
+ Repr::Maplist => maplist::from(&fields),
+ Repr::List => list::from(&fields),
+ };
+
+ let network_impl_item = match network.repr {
+ Repr::Map => quote! {crate::primitive::VariantMap;},
+ Repr::Maplist => quote! {crate::primitive::VariantMap;},
+ Repr::List => quote! {crate::primitive::VariantList;},
+ };
+
+ let mut gen = quote! {
+ impl crate::message::signalproxy::Network for #name {
+ type Item = #network_impl_item
+
+ fn to_network(&self) -> Self::Item {
+ let mut res = Self::Item::new();
+
+ #(#to_network_impl_center)*
+
+ return res;
+ }
+
+ fn from_network(input: &mut Self::Item) -> Self {
+ Self {
+ #(#from_network_impl_center)*
+ }
+ }
+ }
+ };
+
+ if let Repr::Maplist | Repr::Map = network.repr {
+ let network_impl_item_vec = match network.repr {
+ Repr::Map => quote! {crate::primitive::VariantList;},
+ Repr::Maplist => quote! {crate::primitive::VariantMap;},
+ Repr::List => quote! {crate::primitive::VariantList;},
+ };
+
+ let to_network_impl_vec_center = match network.repr {
+ Repr::Maplist => maplist::to_vec(name, &fields),
+ Repr::Map => map::to_vec(name, &fields),
+ _ => unimplemented!(),
+ };
+
+ let from_network_impl_vec_center = match network.repr {
+ Repr::Maplist => maplist::from_vec(name, &fields),
+ Repr::Map => map::from_vec(name, &fields),
+ _ => unimplemented!(),
+ };
+
+ let vec = quote! {
+ impl crate::message::signalproxy::Network for Vec<#name> {
+ type Item = #network_impl_item_vec
+
+ fn to_network(&self) -> Self::Item {
+ #to_network_impl_vec_center
+ }
+
+ fn from_network(input: &mut Self::Item) -> Self {
+ #from_network_impl_vec_center
+ }
+ }
+ };
+
+ gen.extend(vec);
+ }
+
+ // println!("{}", gen);
+
+ gen.into()
+}
+
+fn get_field_type(field: &NetworkField) -> syn::Type {
+ if let Some(override_type) = &field.override_type {
+ gen_type(override_type)
+ } else {
+ field.ty.clone()
+ }
+}
+
+fn get_field_variant_type(field: &NetworkField) -> syn::Type {
+ match &field.variant {
+ Some(ty) => gen_type(&ty),
+ None => {
+ if let Some(override_type) = &field.override_type {
+ gen_type(override_type)
+ } else {
+ field.ty.clone()
+ }
+ }
+ }
+}
+
+fn gen_type(typ: &str) -> syn::Type {
+ syn::Type::from(syn::TypePath {
+ qself: None,
+ path: syn::Path {
+ leading_colon: None,
+ segments: {
+ let mut res =
+ syn::punctuated::Punctuated::<syn::PathSegment, syn::token::Colon2>::new();
+
+ res.push(syn::PathSegment {
+ ident: syn::Ident::new(typ, proc_macro2::Span::call_site()),
+ arguments: syn::PathArguments::None,
+ });
+
+ res
+ },
+ },
+ })
+}
+
+fn get_field_type_colon(mut ty: syn::Type) -> syn::Type {
+ match &mut ty {
+ syn::Type::Path(path) => {
+ let first_seg = path.path.segments.first_mut().unwrap();
+ match &mut first_seg.arguments {
+ syn::PathArguments::AngleBracketed(bracket) => {
+ bracket.colon2_token = Some(syn::parse_str("::").unwrap());
+ }
+ _ => (),
+ }
+ }
+ _ => (),
+ };
+
+ return ty;
+}
diff --git a/derive/src/to_network_impl.rs b/derive/src/to_network_impl.rs
deleted file mode 100644
index 4a8501d..0000000
--- a/derive/src/to_network_impl.rs
+++ /dev/null
@@ -1,96 +0,0 @@
-use proc_macro2::TokenStream;
-use quote::quote;
-
-use crate::{get_field_type, NetworkField};
-
-pub(crate) fn map(fields: &Vec<NetworkField>) -> Vec<TokenStream> {
- fields
- .iter()
- .map(|field| {
- let field_rename = match &field.rename {
- Some(name) => name.clone(),
- None => format!("{}", field.ident.as_ref().unwrap()).into(),
- };
-
- let field_name = field.ident.as_ref().unwrap();
- let field_type = get_field_type(&field);
-
- if field.to_map.is_some() {
- let field_map: syn::ExprClosure =
- syn::parse_str(&field.to_map.as_ref().unwrap()).unwrap();
-
- quote! {
- res.insert(#field_rename.to_string(),
- crate::primitive::Variant::#field_type(self.#field_name.iter().map(#field_map).collect()));
- }
- } else {
- quote! {
- res.insert(#field_rename.to_string(),
- crate::primitive::Variant::#field_type(self.#field_name.clone()));
- }
- }
- })
- .collect()
-}
-
-pub(crate) fn map_list(fields: &Vec<NetworkField>) -> Vec<TokenStream> {
- fields
- .iter()
- .map(|field| {
- let field_rename = match &field.rename {
- Some(name) => name.clone(),
- None => format!("{}", field.ident.as_ref().unwrap()).into(),
- };
-
- let field_name = field.ident.as_ref().unwrap();
- let field_type = get_field_type(&field);
-
- if field.to_map.is_some() {
- let field_map: syn::ExprClosure =
- syn::parse_str(&field.to_map.as_ref().unwrap()).unwrap();
-
- quote! {
- res.insert(#field_rename.to_string(),
- crate::primitive::Variant::VariantList(
- std::vec::from_elem(crate::primitive::Variant::#field_type(self.#field_name.iter().map(#field_map).collect()), 1)));
- }
- } else {
- quote! {
- res.insert(#field_rename.to_string(),
- crate::primitive::Variant::VariantList(
- std::vec::from_elem(crate::primitive::Variant::#field_type(self.#field_name.clone()), 1)));
- }
- }
- })
- .collect()
-}
-
-pub(crate) fn list(fields: &Vec<NetworkField>) -> Vec<TokenStream> {
- fields
- .iter()
- .map(|field| {
- let field_rename = match &field.rename {
- Some(name) => name.clone(),
- None => format!("{}", field.ident.as_ref().unwrap()).into(),
- };
-
- let field_name = field.ident.as_ref().unwrap();
- let field_type = get_field_type(&field);
-
- if field.to_map.is_some() {
- let field_map: syn::ExprClosure =
- syn::parse_str(&field.to_map.as_ref().unwrap()).unwrap();
-
- quote! {
- res.push(crate::primitive::Variant::ByteArray(#field_rename.to_string()));
- res.push(crate::primitive::Variant::#field_type(self.#field_name.iter().map(#field_map).collect()));
- }
- } else {
- quote! {
- res.push(crate::primitive::Variant::ByteArray(#field_rename.to_string()));
- res.push(crate::primitive::Variant::#field_type(self.#field_name.clone()));
- }
- }
- })
- .collect()
-}
diff --git a/examples/quasselproxy/src/main.rs b/examples/quasselproxy/src/main.rs
index 16c0fa9..227240a 100644
--- a/examples/quasselproxy/src/main.rs
+++ b/examples/quasselproxy/src/main.rs
@@ -148,7 +148,7 @@ impl Server {
tls: bool,
compression: bool,
) -> Result<ConnAck, Error> {
- use libquassel::Deserialize;
+ use libquassel::deserialize::*;
// Buffer for our initialization
let mut init: Vec<u8> = vec![];
@@ -217,7 +217,7 @@ impl Server {
) -> Result<(), Error> {
use libquassel::HandshakeDeserialize;
- trace!(target: "message", "Received bytes: {:x?}", buf);
+ trace!(target: "handshakemessage", "Received bytes: {:x?}", buf);
match HandshakeMessage::parse(buf) {
Ok((_size, res)) => {
info!("{}: {:#?}", direction, res);
@@ -236,8 +236,8 @@ impl Server {
#[tracing::instrument]
async fn handle_message(buf: &[u8], direction: &str) -> Result<(), Error> {
+ use libquassel::deserialize::*;
use libquassel::message::Message;
- use libquassel::Deserialize;
trace!(target: "message", "Received bytes: {:x?}", buf);
diff --git a/src/lib.rs b/src/lib.rs
index a2a3a25..e2f57c9 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1,3 +1,4 @@
+#![feature(test)]
#![feature(external_doc)]
#![feature(doc_cfg)]
#![doc(include = "../README.md")]
@@ -26,32 +27,51 @@ pub mod error;
/// Framing impl to be used with [`tokio_util::codec::Framed`]
pub mod frame;
-use failure::Error;
+/// Traits for Serialization of objects
+pub mod serialize {
+ use failure::Error;
-/// Serialization of types and structs to the quassel byteprotocol
-pub trait Serialize {
- fn serialize(&self) -> Result<Vec<u8>, Error>;
-}
+ /// Serialization of types and structs to the quassel byteprotocol
+ pub trait Serialize {
+ fn serialize(&self) -> Result<Vec<u8>, Error>;
+ }
-/// Serialization of UTF-8 based Strings to the quassel byteprotocol
-pub trait SerializeUTF8 {
- fn serialize_utf8(&self) -> Result<Vec<u8>, Error>;
-}
+ /// Serialization of UTF-8 based Strings to the quassel byteprotocol
+ pub trait SerializeUTF8 {
+ fn serialize_utf8(&self) -> Result<Vec<u8>, Error>;
+ }
-/// Deserialization of types and structs to the quassel byteprotocol
-pub trait Deserialize {
- fn parse(b: &[u8]) -> Result<(usize, Self), Error>
- where
- Self: std::marker::Sized;
+ pub trait SerializeVariant {
+ fn serialize_variant(&self) -> Result<Vec<u8>, Error>;
+ }
}
-/// Deserialization of UTF-8 based Strings to the quassel byteprotocol
-pub trait DeserializeUTF8 {
- fn parse_utf8(b: &[u8]) -> Result<(usize, Self), Error>
- where
- Self: std::marker::Sized;
+/// Traits for parsing objects
+pub mod deserialize {
+ use failure::Error;
+
+ /// Deserialization of types and structs to the quassel byteprotocol
+ pub trait Deserialize {
+ fn parse(b: &[u8]) -> Result<(usize, Self), Error>
+ where
+ Self: std::marker::Sized;
+ }
+
+ /// Deserialization of UTF-8 based Strings to the quassel byteprotocol
+ pub trait DeserializeUTF8 {
+ fn parse_utf8(b: &[u8]) -> Result<(usize, Self), Error>
+ where
+ Self: std::marker::Sized;
+ }
+
+ pub trait DeserializeVariant {
+ fn parse_variant(b: &[u8]) -> Result<(usize, Self), Error>
+ where
+ Self: std::marker::Sized;
+ }
}
+use failure::Error;
/// HandshakeSerialize implements the serialization needed during the handhake phase.
///
/// The protocol has some minor differences during this phase compared to the regular parsing.
diff --git a/src/message/handshake/connack.rs b/src/message/handshake/connack.rs
index 222c08c..a246679 100644
--- a/src/message/handshake/connack.rs
+++ b/src/message/handshake/connack.rs
@@ -29,7 +29,7 @@ impl Default for ConnAck {
}
}
-impl crate::Serialize for ConnAck {
+impl crate::serialize::Serialize for ConnAck {
fn serialize(&self) -> Result<Vec<std::primitive::u8>, Error> {
let mut bytes: Vec<u8> = Vec::new();
@@ -41,7 +41,7 @@ impl crate::Serialize for ConnAck {
}
}
-impl crate::Deserialize for ConnAck {
+impl crate::deserialize::Deserialize for ConnAck {
fn parse(b: &[u8]) -> Result<(usize, Self), Error> {
let (flen, flags) = u8::parse(b)?;
let (elen, extra) = i16::parse(&b[flen..])?;
diff --git a/src/message/handshake/init.rs b/src/message/handshake/init.rs
index b4604b6..df1b29e 100644
--- a/src/message/handshake/init.rs
+++ b/src/message/handshake/init.rs
@@ -1,5 +1,4 @@
-use crate::Deserialize;
-use crate::Serialize;
+use crate::{deserialize::Deserialize, serialize::Serialize};
/// The first few bytes sent to the core to initialize the connection and setup if we want to use tls and compression
#[derive(Clone, Debug)]
diff --git a/src/message/handshake/mod.rs b/src/message/handshake/mod.rs
index c180c5e..029eb86 100644
--- a/src/message/handshake/mod.rs
+++ b/src/message/handshake/mod.rs
@@ -24,7 +24,7 @@ pub use protocol::*;
pub use sessioninit::*;
pub use types::*;
-use crate::primitive::{Variant, VariantMap};
+use crate::primitive::VariantMap;
use crate::{HandshakeDeserialize, HandshakeSerialize};
#[derive(Debug, Clone)]
@@ -56,7 +56,7 @@ impl HandshakeDeserialize for HandshakeMessage {
fn parse(b: &[u8]) -> Result<(usize, Self), failure::Error> {
let (size, res) = VariantMap::parse(b)?;
- let msgtype = match_variant!(&res["MsgType"], Variant::String);
+ let msgtype: String = (&res["MsgType"]).into();
match msgtype.as_str() {
"ClientInit" => Ok((size, HandshakeMessage::ClientInit(res.into()))),
"ClientInitAck" => Ok((size, HandshakeMessage::ClientInitAck(res.into()))),
diff --git a/src/message/handshake/protocol.rs b/src/message/handshake/protocol.rs
index d020f33..c12da05 100644
--- a/src/message/handshake/protocol.rs
+++ b/src/message/handshake/protocol.rs
@@ -1,5 +1,4 @@
-use crate::Deserialize;
-use crate::Serialize;
+use crate::{deserialize::Deserialize, serialize::Serialize};
pub enum Protocol {
Legacy = 0x00000001,
diff --git a/src/message/handshake/sessioninit.rs b/src/message/handshake/sessioninit.rs
index d1b4b90..a663cce 100644
--- a/src/message/handshake/sessioninit.rs
+++ b/src/message/handshake/sessioninit.rs
@@ -1,3 +1,5 @@
+use std::convert::TryInto;
+
use crate::message::objects::Identity;
use crate::primitive::{BufferInfo, Variant, VariantMap};
use crate::HandshakeSerialize;
@@ -18,12 +20,15 @@ pub struct SessionInit {
impl From<VariantMap> for SessionInit {
fn from(input: VariantMap) -> Self {
- let state = match_variant!(input.get("SessionState").unwrap(), Variant::VariantMap);
+ use crate::message::signalproxy::Network;
+ let state: VariantMap = input.get("SessionState").unwrap().try_into().unwrap();
+
+ log::trace!("sessionstate: {:#?}", state);
+
SessionInit {
- identities: match_variant!(state.get("Identities").unwrap(), Variant::VariantList)
- .iter()
- .map(|ident| Identity::from(match_variant!(ident, Variant::VariantMap)))
- .collect(),
+ identities: Vec::<Identity>::from_network(
+ &mut state.get("Identities").unwrap().try_into().unwrap(),
+ ),
buffers: match_variant!(state.get("BufferInfos").unwrap(), Variant::VariantList)
.iter()
.map(|buffer| match buffer {
@@ -49,15 +54,15 @@ impl HandshakeSerialize for SessionInit {
"MsgType".to_string(),
Variant::String("SessionInit".to_string()),
);
- values.insert(
- "Identities".to_string(),
- Variant::VariantList(
- self.identities
- .iter()
- .map(|ident| Variant::VariantMap(ident.clone().into()))
- .collect(),
- ),
- );
+ // values.insert(
+ // "Identities".to_string(),
+ // Variant::VariantList(
+ // self.identities
+ // .iter()
+ // .map(|ident| Variant::VariantMap(ident.clone().into()))
+ // .collect(),
+ // ),
+ // );
values.insert(
"BufferInfos".to_string(),
Variant::VariantList(
diff --git a/src/message/handshake/types.rs b/src/message/handshake/types.rs
index 24d847b..e9e6469 100644
--- a/src/message/handshake/types.rs
+++ b/src/message/handshake/types.rs
@@ -7,11 +7,10 @@ use failure::Error;
use crate::error::ProtocolError;
use crate::primitive::Variant;
use crate::util;
-use crate::Deserialize;
-use crate::Serialize;
+use crate::{deserialize::Deserialize, serialize::Serialize};
+use crate::message::handshake::{HandshakeDeserialize, HandshakeSerialize};
use crate::primitive::VariantMap;
-use crate::{HandshakeDeserialize, HandshakeSerialize};
impl HandshakeSerialize for VariantMap {
fn serialize<'a>(&'a self) -> Result<Vec<u8>, Error> {
diff --git a/src/message/signalproxy/heartbeat.rs b/src/message/signalproxy/heartbeat.rs
index 46bfd51..58dc430 100644
--- a/src/message/signalproxy/heartbeat.rs
+++ b/src/message/signalproxy/heartbeat.rs
@@ -1,6 +1,6 @@
use crate::message::MessageType;
use crate::primitive::{DateTime, Variant, VariantList};
-use crate::{Deserialize, Serialize};
+use crate::{deserialize::Deserialize, serialize::Serialize};
#[derive(Clone, Debug, std::cmp::PartialEq)]
pub struct HeartBeat {
diff --git a/src/message/signalproxy/initdata.rs b/src/message/signalproxy/initdata.rs
index abeacad..7c3e443 100644
--- a/src/message/signalproxy/initdata.rs
+++ b/src/message/signalproxy/initdata.rs
@@ -1,12 +1,14 @@
use crate::message::MessageType;
use crate::primitive::{Variant, VariantList};
-use crate::{Deserialize, Serialize};
+use crate::{deserialize::Deserialize, serialize::Serialize};
+
+use super::objects::Types;
#[derive(Clone, Debug, std::cmp::PartialEq)]
pub struct InitData {
class_name: String,
object_name: String,
- init_data: VariantList,
+ init_data: Types,
}
impl Serialize for InitData {
@@ -17,24 +19,26 @@ impl Serialize for InitData {
res.push(Variant::ByteArray(self.class_name.clone()));
res.push(Variant::ByteArray(self.object_name.clone()));
- res.append(&mut self.init_data.clone());
+ res.append(&mut self.init_data.to_network());
res.serialize()
}
}
impl Deserialize for InitData {
- fn parse(b: &[std::primitive::u8]) -> Result<(std::primitive::usize, Self), failure::Error> {
+ fn parse(b: &[u8]) -> Result<(usize, Self), failure::Error> {
let (size, mut res) = VariantList::parse(&b)?;
res.remove(0);
+ let class_name: String = res.remove(0).into();
+
Ok((
size,
Self {
- class_name: match_variant!(res.remove(0), Variant::ByteArray),
- object_name: match_variant!(res.remove(0), Variant::ByteArray),
- init_data: res,
+ class_name: class_name.clone(),
+ object_name: res.remove(0).into(),
+ init_data: Types::from_network(class_name.as_str(), &mut res),
},
))
}
diff --git a/src/message/signalproxy/initrequest.rs b/src/message/signalproxy/initrequest.rs
index 5190e0a..1beef5c 100644
--- a/src/message/signalproxy/initrequest.rs
+++ b/src/message/signalproxy/initrequest.rs
@@ -1,6 +1,6 @@
use crate::message::MessageType;
use crate::primitive::{Variant, VariantList};
-use crate::{Deserialize, Serialize};
+use crate::{deserialize::Deserialize, serialize::Serialize};
#[derive(Clone, Debug, std::cmp::PartialEq)]
pub struct InitRequest {
diff --git a/src/message/signalproxy/mod.rs b/src/message/signalproxy/mod.rs
index 9887af7..2887407 100644
--- a/src/message/signalproxy/mod.rs
+++ b/src/message/signalproxy/mod.rs
@@ -1,4 +1,6 @@
-use crate::{Deserialize, Serialize};
+use crate::{deserialize::Deserialize, serialize::Serialize};
+
+use num_derive::{FromPrimitive, ToPrimitive};
mod heartbeat;
mod initdata;
@@ -98,7 +100,7 @@ impl Deserialize for Message {
/// Type of an SignalProxy Message
/// The first element in the VariantList that is received
#[repr(i32)]
-#[derive(Copy, Clone, Debug, std::cmp::PartialEq)]
+#[derive(Debug, Copy, Clone, PartialEq, FromPrimitive, ToPrimitive)]
pub enum MessageType {
/// Bidirectional
SyncMessage = 0x00000001,
diff --git a/src/message/signalproxy/objects/aliasmanager.rs b/src/message/signalproxy/objects/aliasmanager.rs
index 093163b..b536cde 100644
--- a/src/message/signalproxy/objects/aliasmanager.rs
+++ b/src/message/signalproxy/objects/aliasmanager.rs
@@ -1,93 +1,27 @@
-use crate::primitive::{StringList, Variant, VariantMap};
+use libquassel_derive::Network;
-use crate::message::signalproxy::Network;
-
-#[derive(Clone, Debug, std::cmp::PartialEq)]
+#[derive(Clone, Debug, std::cmp::PartialEq, Network)]
+#[network(repr = "list")]
pub struct AliasManager {
+ #[network(rename = "Aliases", variant = "VariantMap", network)]
pub aliases: Vec<Alias>,
}
-#[derive(Clone, Debug, std::cmp::PartialEq)]
+#[derive(Clone, Debug, std::cmp::PartialEq, Network)]
+#[network(repr = "maplist")]
pub struct Alias {
+ #[network(rename = "names", variant = "StringList")]
name: String,
+ #[network(rename = "expansions", variant = "StringList")]
expansion: String,
}
-impl Alias {
- fn from_network_internal(input: &VariantMap) -> Vec<Self> {
- let names = match_variant!(input.get("names").unwrap(), Variant::StringList);
- let expansions = match_variant!(input.get("expansions").unwrap(), Variant::StringList);
-
- return names
- .iter()
- .zip(expansions)
- .map(|(name, expansion)| Alias {
- name: name.clone(),
- expansion,
- })
- .collect();
- }
-}
-
-impl Network for Alias {
- type Item = VariantMap;
-
- fn to_network(&self) -> Self::Item {
- let mut map = VariantMap::new();
- map.insert(s!("names"), Variant::StringList(vec![self.name.clone()]));
- map.insert(
- s!("expansions"),
- Variant::StringList(vec![self.expansion.clone()]),
- );
-
- return map;
- }
-
- fn from_network(input: &mut Self::Item) -> Self {
- Alias::from_network_internal(&input)[0].clone()
- }
-}
-
-impl Network for AliasManager {
- type Item = VariantMap;
-
- fn to_network(&self) -> Self::Item {
- let (names, expansions) = self.aliases.iter().fold(
- (StringList::new(), StringList::new()),
- |(mut names, mut expansions), alias| {
- names.push(alias.name.clone());
- expansions.push(alias.expansion.clone());
- return (names, expansions);
- },
- );
-
- let mut map = VariantMap::new();
- map.insert(s!("names"), Variant::StringList(names));
- map.insert(s!("expansions"), Variant::StringList(expansions));
-
- return map;
- }
-
- fn from_network(input: &mut Self::Item) -> Self {
- let names = match_variant!(input.get("names").unwrap(), Variant::StringList);
- let expansions = match_variant!(input.get("expansions").unwrap(), Variant::StringList);
-
- AliasManager {
- aliases: names
- .iter()
- .zip(expansions)
- .map(|(name, expansion)| Alias {
- name: name.clone(),
- expansion,
- })
- .collect(),
- }
- }
-}
-
#[cfg(test)]
mod tests {
use super::*;
+ use crate::message::signalproxy::translation::Network;
+
+ use crate::primitive::{Variant, VariantList};
fn get_src() -> AliasManager {
AliasManager {
@@ -104,23 +38,36 @@ mod tests {
}
}
- fn get_dest() -> VariantMap {
- map! {
- s!("names") => Variant::StringList(
- vec![
- s!("j"),
- s!("ns"),
- ],
- ),
- s!("expansions") => Variant::StringList(
- vec![
- s!("/join $0"),
- s!("/msg nickserv $0"),
- ],
- ),
- }
+ fn get_dest() -> VariantList {
+ vec![
+ Variant::ByteArray(s!("Aliases")),
+ Variant::VariantMap(map! {
+ s!("names") => Variant::StringList(
+ vec![
+ s!("j"),
+ s!("ns"),
+ ],
+ ),
+ s!("expansions") => Variant::StringList(
+ vec![
+ s!("/join $0"),
+ s!("/msg nickserv $0"),
+ ],
+ ),
+ }),
+ ]
}
+ // #[bench]
+ // fn alias_to_network(b: &mut test::Bencher) {
+ // b.iter(|| test::black_box(get_src()).to_network())
+ // }
+
+ // #[bench]
+ // fn alias_from_network(b: &mut test::Bencher) {
+ // b.iter(|| AliasManager::from_network(&mut test::black_box(get_dest())))
+ // }
+
#[test]
fn aliasmanager_to_network() {
assert_eq!(get_src().to_network(), get_dest())
diff --git a/src/message/signalproxy/objects/buffersyncer.rs b/src/message/signalproxy/objects/buffersyncer.rs
index 7ee4ca5..cc26310 100644
--- a/src/message/signalproxy/objects/buffersyncer.rs
+++ b/src/message/signalproxy/objects/buffersyncer.rs
@@ -1,13 +1,148 @@
-use crate::message::signalproxy::MessageType;
-use std::collections::HashMap;
+use std::{collections::HashMap, convert::TryInto};
-// use default_macro::default;
-// #[default(crate::message::signalproxy::objects::BufferSyncerClient)]
+use num_traits::{FromPrimitive, ToPrimitive};
+
+use itertools::Itertools;
+
+use crate::{
+ message::signalproxy::Network,
+ primitive::{MessageType, Variant, VariantList},
+};
+
+#[derive(Debug, Clone, PartialEq)]
pub struct BufferSyncer {
- pub activities: HashMap<u32, MessageType>,
- pub highlight_counts: HashMap<u32, u32>,
- pub last_seen_msg: HashMap<u32, u32>,
- pub marker_line: HashMap<u32, u32>,
+ pub activities: HashMap<i32, MessageType>,
+ pub highlight_counts: HashMap<i32, i32>,
+ pub last_seen_msg: HashMap<i32, i64>,
+ pub marker_line: HashMap<i32, i64>,
+}
+
+impl Network for BufferSyncer {
+ type Item = VariantList;
+
+ fn to_network(&self) -> Self::Item {
+ let mut res = Self::Item::new();
+
+ res.push(Variant::ByteArray(s!("Activities")));
+ res.push(Variant::VariantList({
+ let mut res = VariantList::new();
+
+ self.activities.iter().for_each(|(k, v)| {
+ res.push(Variant::i32(*k));
+ res.push(Variant::i32(v.to_i32().unwrap()));
+ });
+
+ res
+ }));
+
+ res.push(Variant::ByteArray(s!("HighlightCounts")));
+ res.push(Variant::VariantList({
+ let mut res = VariantList::new();
+
+ self.highlight_counts.iter().for_each(|(k, v)| {
+ res.push(Variant::i32(*k));
+ res.push(Variant::i32(*v));
+ });
+
+ res
+ }));
+
+ res.push(Variant::ByteArray(s!("LastSeenMsg")));
+ res.push(Variant::VariantList({
+ let mut res = VariantList::new();
+
+ self.last_seen_msg.iter().for_each(|(k, v)| {
+ res.push(Variant::i32(*k));
+ res.push(Variant::i64(*v));
+ });
+
+ res
+ }));
+
+ res.push(Variant::ByteArray(s!("MarkerLines")));
+ res.push(Variant::VariantList({
+ let mut res = VariantList::new();
+
+ self.marker_line.iter().for_each(|(k, v)| {
+ res.push(Variant::i32(*k));
+ res.push(Variant::i64(*v));
+ });
+
+ res
+ }));
+
+ res
+ }
+
+ fn from_network(input: &mut Self::Item) -> Self {
+ let mut i = input.iter().cycle();
+
+ i.position(|x| *x == crate::primitive::Variant::ByteArray(s!("Activities")))
+ .unwrap();
+ let activities: VariantList = i.next().unwrap().try_into().unwrap();
+ let activities = activities
+ .iter()
+ .batching(|it| match it.next() {
+ None => None,
+ Some(x) => match it.next() {
+ None => None,
+ Some(y) => Some((
+ x.try_into().unwrap(),
+ MessageType::from_i32(y.try_into().unwrap()).unwrap(),
+ )),
+ },
+ })
+ .collect();
+
+ i.position(|x| *x == crate::primitive::Variant::ByteArray(s!("HighlightCounts")))
+ .unwrap();
+ let highlight_counts: VariantList = i.next().unwrap().try_into().unwrap();
+ let highlight_counts = highlight_counts
+ .iter()
+ .batching(|it| match it.next() {
+ None => None,
+ Some(x) => match it.next() {
+ None => None,
+ Some(y) => Some((x.try_into().unwrap(), y.try_into().unwrap())),
+ },
+ })
+ .collect();
+
+ i.position(|x| *x == crate::primitive::Variant::ByteArray(s!("LastSeenMsg")))
+ .unwrap();
+ let last_seen_msg: VariantList = i.next().unwrap().try_into().unwrap();
+ let last_seen_msg = last_seen_msg
+ .iter()
+ .batching(|it| match it.next() {
+ None => None,
+ Some(x) => match it.next() {
+ None => None,
+ Some(y) => Some((x.try_into().unwrap(), y.try_into().unwrap())),
+ },
+ })
+ .collect();
+
+ i.position(|x| *x == crate::primitive::Variant::ByteArray(s!("MarkerLines")))
+ .unwrap();
+ let marker_line: VariantList = i.next().unwrap().try_into().unwrap();
+ let marker_line = marker_line
+ .iter()
+ .batching(|it| match it.next() {
+ None => None,
+ Some(x) => match it.next() {
+ None => None,
+ Some(y) => Some((x.try_into().unwrap(), y.try_into().unwrap())),
+ },
+ })
+ .collect();
+
+ Self {
+ activities,
+ highlight_counts,
+ last_seen_msg,
+ marker_line,
+ }
+ }
}
pub trait BufferSyncerServer {
@@ -72,3 +207,115 @@ pub trait BufferSyncerClient {
self.marker_line_mut().insert(buffer, msgid);
}
}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::message::signalproxy::translation::Network;
+ use crate::primitive::{Variant, VariantList};
+ use pretty_assertions::assert_eq;
+
+ fn get_network() -> VariantList {
+ vec![
+ Variant::ByteArray(s!("Activities")),
+ Variant::VariantList(vec![
+ Variant::i32(1),
+ Variant::i32(0),
+ Variant::i32(2),
+ Variant::i32(0),
+ Variant::i32(3),
+ Variant::i32(0),
+ Variant::i32(4),
+ Variant::i32(0),
+ Variant::i32(5),
+ Variant::i32(0),
+ ]),
+ Variant::ByteArray(s!("HighlightCounts")),
+ Variant::VariantList(vec![
+ Variant::i32(1),
+ Variant::i32(0),
+ Variant::i32(2),
+ Variant::i32(0),
+ Variant::i32(3),
+ Variant::i32(0),
+ Variant::i32(4),
+ Variant::i32(0),
+ Variant::i32(5),
+ Variant::i32(0),
+ ]),
+ Variant::ByteArray(s!("LastSeenMsg")),
+ Variant::VariantList(vec![
+ Variant::i32(1),
+ Variant::i64(2185),
+ Variant::i32(2),
+ Variant::i64(2188),
+ Variant::i32(3),
+ Variant::i64(860),
+ Variant::i32(4),
+ Variant::i64(2183),
+ Variant::i32(5),
+ Variant::i64(2180),
+ ]),
+ Variant::ByteArray(s!("MarkerLines")),
+ Variant::VariantList(vec![
+ Variant::i32(1),
+ Variant::i64(2185),
+ Variant::i32(2),
+ Variant::i64(2188),
+ Variant::i32(3),
+ Variant::i64(860),
+ Variant::i32(4),
+ Variant::i64(1527),
+ Variant::i32(5),
+ Variant::i64(2180),
+ ]),
+ ]
+ }
+
+ fn get_runtime() -> BufferSyncer {
+ BufferSyncer {
+ activities: map! {
+ 1 => MessageType::None,
+ 2 => MessageType::None,
+ 3 => MessageType::None,
+ 4 => MessageType::None,
+ 5 => MessageType::None,
+ },
+ highlight_counts: map! {
+ 1 => 0,
+ 2 => 0,
+ 3 => 0,
+ 4 => 0,
+ 5 => 0,
+ },
+ last_seen_msg: map! {
+ 1 => 2185,
+ 2 => 2188,
+ 3 => 860,
+ 4 => 2183,
+ 5 => 2180,
+ },
+ marker_line: map! {
+ 1 => 2185,
+ 2 => 2188,
+ 3 => 860,
+ 4 => 1527,
+ 5 => 2180,
+ },
+ }
+ }
+
+ // Disabled cus not sorted
+ // #[test]
+ // fn buffersyncer_to_network() {
+ // assert_eq!(get_runtime().to_network(), get_network())
+ // }
+
+ #[test]
+ fn buffersyncer_from_network() {
+ assert_eq!(
+ BufferSyncer::from_network(&mut get_network()),
+ get_runtime()
+ )
+ }
+}
diff --git a/src/message/signalproxy/objects/coreinfo.rs b/src/message/signalproxy/objects/coreinfo.rs
new file mode 100644
index 0000000..a717366
--- /dev/null
+++ b/src/message/signalproxy/objects/coreinfo.rs
@@ -0,0 +1,60 @@
+use libquassel_derive::Network;
+
+use crate::primitive::{DateTime, StringList};
+
+#[derive(Debug, Clone, PartialEq, Network)]
+#[network(repr = "map")]
+pub struct CoreInfo {
+ #[network(rename = "coreData", network, variant = "VariantMap")]
+ core_data: CoreData,
+}
+
+// // S->C calls
+// setCoreData(coreData: QVariantMap)
+// /**
+// * Replaces all properties of the object with the content of the
+// * "properties" parameter. This parameter is in network representation.
+// */
+// update(properties: QVariantMap)
+
+#[derive(Debug, Clone, PartialEq, Network)]
+#[network(repr = "map")]
+pub struct CoreData {
+ #[network(rename = "quasselVersion")]
+ quassel_version: String,
+ #[network(rename = "quasselBuildDate")]
+ quassel_build_date: String,
+ #[network(rename = "startTime")]
+ start_time: DateTime,
+ #[network(rename = "sessionConnectedClients")]
+ session_connected_clients: i32,
+ #[network(
+ rename = "sessionConnectedClientData",
+ variant = "VariantList",
+ network
+ )]
+ session_connected_client_data: Vec<ConnectedClient>,
+}
+
+#[derive(Debug, Clone, PartialEq, Network)]
+#[network(repr = "map")]
+pub struct ConnectedClient {
+ #[network(rename = "id")]
+ id: i32,
+ #[network(rename = "remoteAddress")]
+ remote_address: String,
+ #[network(rename = "location")]
+ location: String,
+ #[network(rename = "clientVersion")]
+ client_version: String,
+ #[network(rename = "clientVersionDate")]
+ client_version_date: String,
+ #[network(rename = "connectedSince")]
+ connected_since: DateTime,
+ #[network(rename = "secure")]
+ secure: bool,
+ #[network(rename = "features")]
+ features: i32,
+ #[network(rename = "featureList")]
+ feature_list: StringList,
+}
diff --git a/src/message/signalproxy/objects/highlightrulemanager.rs b/src/message/signalproxy/objects/highlightrulemanager.rs
new file mode 100644
index 0000000..d579254
--- /dev/null
+++ b/src/message/signalproxy/objects/highlightrulemanager.rs
@@ -0,0 +1,113 @@
+use libquassel_derive::Network;
+
+use num_derive::{FromPrimitive, ToPrimitive};
+use num_traits::{FromPrimitive, ToPrimitive};
+
+#[derive(Debug, Clone, PartialEq, Network)]
+#[network(repr = "list")]
+pub struct HighlightRuleManager {
+ #[network(rename = "highlightRuleList", network, variant = "VariantMap")]
+ highlight_rule_list: Vec<HighlightRule>,
+ #[network(rename = "highlightNick", network, variant = "i32")]
+ highlight_nick: HighlightNickType,
+ #[network(rename = "nicksCaseSensitive")]
+ nicks_case_sensitive: bool,
+}
+
+#[derive(Debug, Clone, PartialEq, Network)]
+#[network(repr = "maplist")]
+pub struct HighlightRule {
+ id: i32,
+ #[network(variant = "StringList")]
+ name: String,
+ #[network(rename = "isRegEx")]
+ is_regex: bool,
+ #[network(rename = "isCaseSensitive")]
+ is_case_sensitive: bool,
+ #[network(rename = "isEnabled")]
+ is_enabled: bool,
+ #[network(rename = "isInverse")]
+ is_inverse: bool,
+ #[network(variant = "StringList")]
+ sender: String,
+ #[network(variant = "StringList")]
+ channel: String,
+}
+
+#[derive(Debug, Clone, PartialEq, FromPrimitive, ToPrimitive)]
+pub enum HighlightNickType {
+ NoNick = 0x00,
+ CurrentNick = 0x01,
+ AllNicks = 0x02,
+}
+
+impl crate::message::signalproxy::Network for HighlightNickType {
+ type Item = i32;
+
+ fn to_network(&self) -> Self::Item {
+ self.to_i32().unwrap()
+ }
+
+ fn from_network(input: &mut Self::Item) -> Self {
+ Self::from_i32(*input).unwrap()
+ }
+}
+
+#[cfg(test)]
+mod tests {
+ use super::*;
+ use crate::message::signalproxy::translation::Network;
+ use crate::primitive::{Variant, VariantList};
+
+ use pretty_assertions::assert_eq;
+
+ fn get_network() -> VariantList {
+ vec![
+ Variant::ByteArray(s!("highlightRuleList")),
+ Variant::VariantMap(map! {
+ s!("isInverse") => Variant::VariantList(vec![Variant::bool(false)]),
+ s!("isEnabled") => Variant::VariantList(vec![Variant::bool(true)]),
+ s!("channel") => Variant::StringList(vec![s!("#test")]),
+ s!("sender") => Variant::StringList(vec![s!("testuser")]),
+ s!("isCaseSensitive") => Variant::VariantList(vec![Variant::bool(false)]),
+ s!("isRegEx") => Variant::VariantList(vec![Variant::bool(false)]),
+ s!("name") => Variant::StringList(vec![s!("testrule")]),
+ s!("id") => Variant::VariantList(vec![Variant::i32(1)]),
+ }),
+ Variant::ByteArray(s!("highlightNick")),
+ Variant::i32(1),
+ Variant::ByteArray(s!("nicksCaseSensitive")),
+ Variant::bool(false),
+ ]
+ }
+
+ fn get_runtime() -> HighlightRuleManager {
+ HighlightRuleManager {
+ highlight_rule_list: vec![HighlightRule {
+ id: 1,
+ name: s!("testrule"),
+ is_regex: false,
+ is_case_sensitive: false,
+ is_enabled: true,
+ is_inverse: false,
+ sender: s!("testuser"),
+ channel: s!("#test"),
+ }],
+ highlight_nick: HighlightNickType::CurrentNick,
+ nicks_case_sensitive: false,
+ }
+ }
+
+ #[test]
+ fn highlightrulemanager_to_network() {
+ assert_eq!(get_runtime().to_network(), get_network())
+ }
+
+ #[test]
+ fn highlightrulemanager_from_network() {
+ assert_eq!(
+ HighlightRuleManager::from_network(&mut get_network()),
+ get_runtime()
+ )
+ }
+}
diff --git a/src/message/signalproxy/objects/identity.rs b/src/message/signalproxy/objects/identity.rs
index a710e5d..744e777 100644
--- a/src/message/signalproxy/objects/identity.rs
+++ b/src/message/signalproxy/objects/identity.rs
@@ -1,119 +1,44 @@
-use crate::primitive::{Variant, VariantMap};
+use libquassel_derive::Network;
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, PartialEq, Network)]
+#[network(repr = "map")]
pub struct Identity {
+ #[network(rename = "identityId")]
identity_id: i32,
+ #[network(rename = "identityName")]
identity_name: String,
+ #[network(rename = "realName")]
real_name: String,
+ #[network(rename = "nicks", override_type = "StringList")]
nicks: Vec<String>,
+ #[network(rename = "awayNick")]
away_nick: String,
+ #[network(rename = "awayNickEnabled")]
away_nick_enabled: bool,
+ #[network(rename = "awayReason")]
away_reason: String,
+ #[network(rename = "awayReasonEnabled")]
away_reason_enabled: bool,
+ #[network(rename = "autoAwayEnabled")]
auto_away_enabled: bool,
+ #[network(rename = "autoAwayTime")]
auto_away_time: i32,
+ #[network(rename = "autoAwayReason")]
auto_away_reason: String,
+ #[network(rename = "autoAwayReasonEnabled")]
auto_away_reason_enabled: bool,
+ #[network(rename = "detachAwayEnabled")]
detach_away_enabled: bool,
+ #[network(rename = "detachAwayReason")]
detach_away_reason: String,
+ #[network(rename = "detachAwayReasonEnabled")]
detach_away_reason_enabled: bool,
+ #[network(rename = "ident")]
ident: String,
+ #[network(rename = "kickReason")]
kick_reason: String,
+ #[network(rename = "partReason")]
part_reason: String,
+ #[network(rename = "quitReason")]
quit_reason: String,
}
-
-impl From<VariantMap> for Identity {
- fn from(input: VariantMap) -> Self {
- Identity {
- identity_id: match_variant!(input.get("identityId").unwrap(), Variant::i32),
- identity_name: match_variant!(input.get("identityName").unwrap(), Variant::String),
- real_name: match_variant!(input.get("realName").unwrap(), Variant::String),
- nicks: match_variant!(input.get("nicks").unwrap(), Variant::StringList),
- away_nick: match_variant!(input.get("awayNick").unwrap(), Variant::String),
- away_nick_enabled: match_variant!(input.get("awayNickEnabled").unwrap(), Variant::bool),
- away_reason: match_variant!(input.get("awayReason").unwrap(), Variant::String),
- away_reason_enabled: match_variant!(
- input.get("awayReasonEnabled").unwrap(),
- Variant::bool
- ),
- auto_away_enabled: match_variant!(input.get("autoAwayEnabled").unwrap(), Variant::bool),
- auto_away_time: match_variant!(input.get("autoAwayTime").unwrap(), Variant::i32),
- auto_away_reason: match_variant!(input.get("autoAwayReason").unwrap(), Variant::String),
- auto_away_reason_enabled: match_variant!(
- input.get("autoAwayReasonEnabled").unwrap(),
- Variant::bool
- ),
- detach_away_enabled: match_variant!(
- input.get("detachAwayEnabled").unwrap(),
- Variant::bool
- ),
- detach_away_reason: match_variant!(
- input.get("detachAwayReason").unwrap(),
- Variant::String
- ),
- detach_away_reason_enabled: match_variant!(
- input.get("detachAwayReasonEnabled").unwrap(),
- Variant::bool
- ),
- ident: match_variant!(input.get("ident").unwrap(), Variant::String),
- kick_reason: match_variant!(input.get("kickReason").unwrap(), Variant::String),
- part_reason: match_variant!(input.get("partReason").unwrap(), Variant::String),
- quit_reason: match_variant!(input.get("quitReason").unwrap(), Variant::String),
- }
- }
-}
-
-impl Into<std::collections::HashMap<String, Variant>> for Identity {
- fn into(self) -> VariantMap {
- let mut res = VariantMap::with_capacity(19);
-
- res.insert("identityId".to_string(), Variant::i32(self.identity_id));
- res.insert(
- "identityName".to_string(),
- Variant::String(self.identity_name),
- );
- res.insert("realName".to_string(), Variant::String(self.real_name));
- res.insert("nicks".to_string(), Variant::StringList(self.nicks));
- res.insert("awayNick".to_string(), Variant::String(self.away_nick));
- res.insert(
- "awayNickEnabled".to_string(),
- Variant::bool(self.away_nick_enabled),
- );
- res.insert("awayReason".to_string(), Variant::String(self.away_reason));
- res.insert(
- "awayReasonEnabled".to_string(),
- Variant::bool(self.away_reason_enabled),
- );
- res.insert(
- "autoAwayEnabled".to_string(),
- Variant::bool(self.auto_away_enabled),
- );
- res.insert(
- "autoAwayTime".to_string(),
- Variant::i32(self.auto_away_time),
- );
- res.insert(
- "autoAwayReason".to_string(),
- Variant::String(self.auto_away_reason),
- );
- res.insert(
- "detachAwayEnabled".to_string(),
- Variant::bool(self.detach_away_enabled),
- );
- res.insert(
- "detachAwayReason".to_string(),
- Variant::String(self.detach_away_reason),
- );
- res.insert(
- "detachAwayReasonEnabled".to_string(),
- Variant::bool(self.detach_away_reason_enabled),
- );
- res.insert("ident".to_string(), Variant::String(self.ident));
- res.insert("kickReason".to_string(), Variant::String(self.kick_reason));
- res.insert("partReason".to_string(), Variant::String(self.part_reason));
- res.insert("quitReason".to_string(), Variant::String(self.quit_reason));
-
- res
- }
-}
diff --git a/src/message/signalproxy/objects/ircchannel.rs b/src/message/signalproxy/objects/ircchannel.rs
index b15d789..ee23f07 100644
--- a/src/message/signalproxy/objects/ircchannel.rs
+++ b/src/message/signalproxy/objects/ircchannel.rs
@@ -1,22 +1,119 @@
use std::collections::HashMap;
+use std::convert::TryFrom;
+use std::convert::TryInto;
-use crate::primitive::{StringList, Variant, VariantMap};
+use crate::primitive::{StringList, Variant, VariantList, VariantMap};
-#[allow(unused_imports)]
use crate::message::signalproxy::Network;
#[allow(dead_code)]
#[derive(Debug, Clone, PartialEq)]
pub struct IrcChannel {
- channel_modes_a: HashMap<char, StringList>,
- channel_modes_b: HashMap<char, String>,
- channel_modes_c: HashMap<char, String>,
- channel_modes_d: String,
- user_modes: HashMap<String, String>,
- name: String,
- topic: String,
- password: String,
- encrypted: bool,
+ pub channel_modes_a: HashMap<char, StringList>,
+ pub channel_modes_b: HashMap<char, String>,
+ pub channel_modes_c: HashMap<char, String>,
+ pub channel_modes_d: String,
+ // pub channel_modes: HashMap<char, ChannelMode>,
+ pub user_modes: HashMap<String, String>,
+ pub name: String,
+ pub topic: String,
+ pub password: String,
+ pub encrypted: bool,
+}
+
+// #[derive(Debug, Clone, PartialEq)]
+// pub enum ChannelMode {
+// A(char, StringList),
+// B(char, String),
+// C(char, String),
+// D(char),
+// }
+
+impl Network for Vec<IrcChannel> {
+ type Item = VariantMap;
+
+ fn to_network(&self) -> Self::Item {
+ let mut channelmodes: VariantList = Vec::with_capacity(self.len());
+ let mut usermodes: VariantList = Vec::with_capacity(self.len());
+ let mut name: VariantList = Vec::with_capacity(self.len());
+ let mut topic: VariantList = Vec::with_capacity(self.len());
+ let mut password: VariantList = Vec::with_capacity(self.len());
+ let mut encrypted: VariantList = Vec::with_capacity(self.len());
+
+ let mut map = VariantMap::new();
+
+ self.iter().for_each(|item| {
+ channelmodes.push(Variant::VariantMap({
+ let mut map = VariantMap::new();
+
+ map.insert(
+ s!("A"),
+ Variant::VariantMap(
+ item.channel_modes_a
+ .iter()
+ .map(|(k, v)| (k.to_string(), Variant::StringList(v.clone())))
+ .collect(),
+ ),
+ );
+ map.insert(
+ s!("B"),
+ Variant::VariantMap(
+ item.channel_modes_b
+ .iter()
+ .map(|(k, v)| (k.to_string(), Variant::String(v.clone())))
+ .collect(),
+ ),
+ );
+ map.insert(
+ s!("C"),
+ Variant::VariantMap(
+ item.channel_modes_c
+ .iter()
+ .map(|(k, v)| (k.to_string(), Variant::String(v.clone())))
+ .collect(),
+ ),
+ );
+ map.insert(s!("D"), Variant::String(item.channel_modes_d.clone()));
+
+ map
+ }));
+
+ usermodes.push(Variant::VariantMap(
+ item.user_modes
+ .iter()
+ .map(|(k, v)| (k.clone(), Variant::String(v.clone())))
+ .collect(),
+ ));
+ name.push(Variant::String(item.name.clone()));
+ topic.push(Variant::String(item.topic.clone()));
+ password.push(Variant::String(item.password.clone()));
+ encrypted.push(Variant::bool(item.encrypted));
+ });
+
+ map.insert(
+ String::from("ChanModes"),
+ Variant::VariantList(channelmodes),
+ );
+ map.insert(String::from("UserModes"), Variant::VariantList(usermodes));
+ map.insert(String::from("name"), Variant::VariantList(name));
+ map.insert(String::from("topic"), Variant::VariantList(topic));
+ map.insert(String::from("password"), Variant::VariantList(password));
+ map.insert(String::from("encrypted"), Variant::VariantList(encrypted));
+
+ map
+ }
+
+ fn from_network(input: &mut Self::Item) -> Self {
+ let marker: VariantList =
+ std::convert::TryInto::try_into(input.get("name").unwrap()).unwrap();
+
+ let mut res = Vec::new();
+ for _ in 0..marker.len() {
+ res.push(IrcChannel::from_network(input));
+ }
+
+ return res;
+ }
}
impl Network for IrcChannel {
@@ -92,90 +189,48 @@ impl Network for IrcChannel {
res
}
fn from_network(input: &mut Self::Item) -> Self {
+ let mut chanmodes: VariantMap = match_variant!(
+ match_variant!(input.get_mut("ChanModes").unwrap(), Variant::VariantList).remove(0),
+ Variant::VariantMap
+ );
+
Self {
- channel_modes_a: match_variant!(
- match_variant!(
- match_variant!(input.get("ChanModes").unwrap(), Variant::VariantList)[0],
- Variant::VariantMap
- )
- .get("B")
- .unwrap(),
- Variant::VariantMap
+ channel_modes_a: match_variant!(chanmodes.remove("A").unwrap(), Variant::VariantMap)
+ .into_iter()
+ .map(|(mut k, v)| (k.remove(0), match_variant!(v, Variant::StringList)))
+ .collect(),
+ channel_modes_b: match_variant!(chanmodes.remove("B").unwrap(), Variant::VariantMap)
+ .into_iter()
+ .map(|(mut k, v)| (k.remove(0), match_variant!(v, Variant::String)))
+ .collect(),
+ channel_modes_c: match_variant!(chanmodes.remove("C").unwrap(), Variant::VariantMap)
+ .into_iter()
+ .map(|(mut k, v)| (k.remove(0), match_variant!(v, Variant::String)))
+ .collect(),
+ channel_modes_d: match_variant!(chanmodes.remove("D").unwrap(), Variant::String),
+ user_modes: VariantMap::try_from(
+ match_variant!(input.get_mut("UserModes").unwrap(), Variant::VariantList).remove(0),
)
- .iter()
- .map(|(k, v)| {
- (
- k.chars().nth(0).unwrap(),
- match_variant!(v, Variant::StringList),
- )
- })
+ .unwrap()
+ .into_iter()
+ .map(|(k, v)| (k, v.try_into().unwrap()))
.collect(),
- channel_modes_b: match_variant!(
- match_variant!(
- match_variant!(input.get("ChanModes").unwrap(), Variant::VariantList)[0],
- Variant::VariantMap
- )
- .get("B")
+ name: match_variant!(input.get_mut("name").unwrap(), Variant::VariantList)
+ .remove(0)
+ .try_into()
.unwrap(),
- Variant::VariantMap
- )
- .iter()
- .map(|(k, v)| {
- (
- k.chars().nth(0).unwrap(),
- match_variant!(v, Variant::String),
- )
- })
- .collect(),
- channel_modes_c: match_variant!(
- match_variant!(
- match_variant!(input.get("ChanModes").unwrap(), Variant::VariantList)[0],
- Variant::VariantMap
- )
- .get("C")
+ topic: match_variant!(input.get_mut("topic").unwrap(), Variant::VariantList)
+ .remove(0)
+ .try_into()
.unwrap(),
- Variant::VariantMap
- )
- .iter()
- .map(|(k, v)| {
- (
- k.chars().nth(0).unwrap(),
- match_variant!(v, Variant::String),
- )
- })
- .collect(),
- channel_modes_d: match_variant!(
- match_variant!(
- match_variant!(input.get("ChanModes").unwrap(), Variant::VariantList)[0],
- Variant::VariantMap
- )
- .get("D")
+ password: match_variant!(input.get_mut("password").unwrap(), Variant::VariantList)
+ .remove(0)
+ .try_into()
+ .unwrap(),
+ encrypted: match_variant!(input.get_mut("encrypted").unwrap(), Variant::VariantList)
+ .remove(0)
+ .try_into()
.unwrap(),
- Variant::String
- ),
- user_modes: match_variant!(
- match_variant!(input.get("UserModes").unwrap(), Variant::VariantList)[0],
- Variant::VariantMap
- )
- .iter()
- .map(|(k, v)| (k.clone(), match_variant!(v, Variant::String)))
- .collect(),
- name: match_variant!(
- match_variant!(input.get("name").unwrap(), Variant::VariantList)[0],
- Variant::String
- ),
- topic: match_variant!(
- match_variant!(input.get("topic").unwrap(), Variant::VariantList)[0],
- Variant::String
- ),
- password: match_variant!(
- match_variant!(input.get("password").unwrap(), Variant::VariantList)[0],
- Variant::String
- ),
- encrypted: match_variant!(
- match_variant!(input.get("encrypted").unwrap(), Variant::VariantList)[0],
- Variant::bool
- ),
}
}
}
@@ -185,7 +240,7 @@ mod tests {
use super::*;
fn get_network() -> VariantMap {
- VariantMap::from(map! {
+ map! {
s!("encrypted") => Variant::VariantList(
vec![
Variant::bool(
@@ -233,9 +288,9 @@ mod tests {
),
},
),
- s!("A") => Variant::VariantMap(map!
- {},
- ),
+ s!("A") => Variant::VariantMap(map! {
+ s!("b") => Variant::StringList(vec![s!("*!*@test"), s!("*!*@test2")]),
+ }),
},
),
],
@@ -261,11 +316,11 @@ mod tests {
),
],
)
- })
+ }
}
fn get_runtime() -> IrcChannel {
IrcChannel {
- channel_modes_a: map! {},
+ channel_modes_a: map! { 'b' => vec![s!("*!*@test"), s!("*!*@test2")] },
channel_modes_b: map! {},
channel_modes_c: map! { 'j' => s!("5:1"), 'x' => s!("10:5"), 'f' => s!("30:5"), 'F' => s!("5:60") },
channel_modes_d: s!("tCnT"),
diff --git a/src/message/signalproxy/objects/ircuser.rs b/src/message/signalproxy/objects/ircuser.rs
index 1064965..85fea81 100644
--- a/src/message/signalproxy/objects/ircuser.rs
+++ b/src/message/signalproxy/objects/ircuser.rs
@@ -1,56 +1,39 @@
-use std::collections::HashMap;
-
-use crate::primitive::{DateTime, StringList, Variant, VariantMap};
+use crate::primitive::{DateTime, StringList};
#[allow(unused_imports)]
use crate::message::signalproxy::Network;
use libquassel_derive::Network;
-impl Network for Vec<IrcUser> {
- type Item = VariantMap;
-
- fn to_network(&self) -> Self::Item {
- Variant::VariantMap(self.iter().fold(HashMap::new(), |mut res, v| {
- res.extend(v.to_network());
-
- res
- }))
- }
- fn from_network(input: &mut Self::Item) -> Self {
- todo!()
- }
-}
-
#[allow(dead_code)]
#[derive(Debug, Clone, PartialEq, Network)]
#[network(repr = "maplist")]
pub struct IrcUser {
- user: String,
- host: String,
- nick: String,
+ pub user: String,
+ pub host: String,
+ pub nick: String,
#[network(rename = "realName")]
- real_name: String,
- account: String,
- away: bool,
+ pub real_name: String,
+ pub account: String,
+ pub away: bool,
#[network(rename = "awayMessage")]
- away_message: String,
+ pub away_message: String,
#[network(rename = "idleTime")]
- idle_time: DateTime,
+ pub idle_time: DateTime,
#[network(rename = "loginTime")]
- login_time: DateTime,
- server: String,
+ pub login_time: DateTime,
+ pub server: String,
#[network(rename = "ircOperator")]
- irc_operator: String,
+ pub irc_operator: String,
#[network(rename = "lastAwayMessageTime")]
- last_away_message_time: DateTime,
+ pub last_away_message_time: DateTime,
#[network(rename = "whoisServiceReply")]
- whois_service_reply: String,
+ pub whois_service_reply: String,
#[network(rename = "suserHost")]
- suser_host: String,
- encrypted: bool,
- channels: StringList,
+ pub suser_host: String,
+ pub encrypted: bool,
+ pub channels: StringList,
#[network(rename = "userModes")]
- user_modes: String,
+ pub user_modes: String,
}
#[cfg(test)]
diff --git a/src/message/signalproxy/objects/mod.rs b/src/message/signalproxy/objects/mod.rs
index 84f2f5a..2fc4745 100644
--- a/src/message/signalproxy/objects/mod.rs
+++ b/src/message/signalproxy/objects/mod.rs
@@ -1,15 +1,62 @@
mod aliasmanager;
mod buffersyncer;
+mod coreinfo;
+mod highlightrulemanager;
mod identity;
-// mod ircchannel;
-// mod ircuser;
-// mod network;
-// mod networkinfo;
+mod ircchannel;
+mod ircuser;
+mod network;
+mod networkinfo;
+
+use std::convert::TryInto;
pub use aliasmanager::*;
pub use buffersyncer::*;
+pub use coreinfo::*;
+pub use highlightrulemanager::*;
pub use identity::*;
+pub use ircchannel::*;
+pub use ircuser::*;
+pub use network::*;
+pub use networkinfo::*;
+
+use libquassel_derive::From;
+
+use super::Network;
+use crate::primitive::VariantList;
+
+#[derive(Debug, Clone, PartialEq, From)]
+pub enum Types {
+ AliasManager(AliasManager),
+ Network(network::Network),
+ NetworkInfo(NetworkInfo),
+ NetworkConfig(NetworkConfig),
+ CoreData(CoreData),
+ Unknown(VariantList),
+}
+
+impl Types {
+ pub fn to_network(&self) -> VariantList {
+ match self {
+ Types::AliasManager(val) => val.to_network(),
+ Types::Network(val) => val.to_network(),
+ Types::NetworkInfo(val) => val.to_network(),
+ Types::NetworkConfig(val) => val.to_network(),
+ Types::CoreData(val) => vec![val.to_network().into()],
+ Types::Unknown(val) => val.clone(),
+ }
+ }
-pub trait Act {
- fn act(self: Self);
+ pub fn from_network(class_name: &str, input: &mut VariantList) -> Self {
+ match class_name {
+ "Network" => Types::Network(Network::from_network(input)),
+ "NetworkInfo" => Types::NetworkInfo(NetworkInfo::from_network(input)),
+ "NetworkConfig" => Types::NetworkConfig(NetworkConfig::from_network(input)),
+ "AliasManager" => Types::AliasManager(AliasManager::from_network(input)),
+ "CoreData" => Types::CoreData(CoreData::from_network(
+ &mut input.remove(0).try_into().unwrap(),
+ )),
+ _ => Types::Unknown(input.to_owned()),
+ }
+ }
}
diff --git a/src/message/signalproxy/objects/network.rs b/src/message/signalproxy/objects/network.rs
index 4075499..6bf9265 100644
--- a/src/message/signalproxy/objects/network.rs
+++ b/src/message/signalproxy/objects/network.rs
@@ -1,16 +1,17 @@
-use crate::primitive::{StringList, Variant, VariantList, VariantMap};
+use std::convert::TryInto;
+
+use crate::primitive::{Variant, VariantList, VariantMap};
-#[allow(unused_imports)]
use libquassel_derive::Network;
use std::collections::HashMap;
use num_derive::{FromPrimitive, ToPrimitive};
-use num_traits::{FromPrimitive, ToPrimitive};
+use num_traits::FromPrimitive;
use super::{ircchannel::IrcChannel, ircuser::IrcUser, networkinfo::NetworkInfo};
-#[derive(Debug, Clone)]
+#[derive(Debug, Clone, PartialEq)]
pub struct Network {
my_nick: String,
latency: i32,
@@ -105,146 +106,104 @@ impl crate::message::signalproxy::Network for Network {
}
fn from_network(input: &mut Self::Item) -> Self {
- let users_and_channels = match_variant!(
- input
- .iter()
- .nth(
- input
- .iter()
- .position(|x| *x == Variant::ByteArray(s!("IrcUsersAndChannels")))
- .unwrap()
- )
- .unwrap(),
- Variant::VariantMap
- );
-
- let res = Self {
- my_nick: match_variant!(
- input
- .iter()
- .nth(
- input
- .iter()
- .position(|x| *x == Variant::ByteArray(s!("myNick")))
- .unwrap()
- )
- .unwrap(),
- Variant::String
- ),
- latency: match_variant!(
- input
- .iter()
- .nth(
- input
- .iter()
- .position(|x| *x == Variant::ByteArray(s!("latency")))
- .unwrap()
- )
- .unwrap(),
- Variant::i32
- ),
- current_server: match_variant!(
- input
- .iter()
- .nth(
- input
- .iter()
- .position(|x| *x == Variant::ByteArray(s!("currentServer")))
- .unwrap()
- )
- .unwrap(),
- Variant::String
- ),
- is_connected: match_variant!(
- input
- .iter()
- .nth(
- input
- .iter()
- .position(|x| *x == Variant::ByteArray(s!("isConnected")))
- .unwrap()
- )
- .unwrap(),
- Variant::bool
- ),
- connection_state: ConnectionState::from_i32(match_variant!(
- input
- .iter()
- .nth(
- input
- .iter()
- .position(|x| *x == Variant::ByteArray(s!("connectionState")))
- .unwrap()
- )
- .unwrap(),
- Variant::i32
- ))
- .unwrap(),
- irc_users: match_variant!(
- users_and_channels.get("Users").unwrap(),
- Variant::VariantMap
- )
- .iter()
- .map(|(k, v)| (k, IrcUser::from_network(v))),
- irc_channels: match_variant!(
- users_and_channels.get("Channels").unwrap(),
- Variant::VariantMap
- )
- .iter()
- .map(|(k, v)| (k, match_variant!(v, Variant::VariantList))),
- supports: match_variant!(
- input
- .iter()
- .nth(
- input
- .iter()
- .position(|x| *x == Variant::ByteArray(s!("Supports")))
- .unwrap()
- )
- .unwrap(),
- Variant::VariantMap
- )
- .iter()
- .map(|(k, v)| (k.clone(), match_variant!(v, Variant::String)))
- .collect(),
- caps: match_variant!(
- input
- .iter()
- .nth(
- input
- .iter()
- .position(|x| *x == Variant::ByteArray(s!("Caps")))
- .unwrap()
- )
- .unwrap(),
- Variant::VariantMap
- )
- .iter()
- .map(|(k, v)| (k.clone(), match_variant!(v, Variant::String)))
- .collect(),
- caps_enabled: match_variant!(
- input
- .iter()
- .nth(
- input
- .iter()
- .position(|x| *x == Variant::ByteArray(s!("CapsEnabled")))
- .unwrap()
- )
- .unwrap(),
- Variant::VariantList
- )
- .iter()
- .map(|v| match_variant!(v, Variant::String))
- .collect(),
- network_info: NetworkInfo::from_network(input),
+ let mut i = input.iter().cycle();
+
+ let users_and_channels: VariantMap = {
+ i.position(|x| *x == Variant::ByteArray(String::from("IrcUsersAndChannels")))
+ .unwrap();
+
+ i.next().unwrap().try_into().unwrap()
};
- todo!()
+ log::trace!("users and channels: {:#?}", users_and_channels);
+
+ Self {
+ my_nick: {
+ i.position(|x| *x == Variant::ByteArray(String::from("myNick")))
+ .unwrap();
+
+ i.next().unwrap().try_into().unwrap()
+ },
+ latency: {
+ i.position(|x| *x == Variant::ByteArray(String::from("latency")))
+ .unwrap();
+
+ i.next().unwrap().try_into().unwrap()
+ },
+ current_server: {
+ i.position(|x| *x == Variant::ByteArray(String::from("currentServer")))
+ .unwrap();
+
+ i.next().unwrap().try_into().unwrap()
+ },
+ is_connected: {
+ i.position(|x| *x == Variant::ByteArray(String::from("isConnected")))
+ .unwrap();
+
+ i.next().unwrap().try_into().unwrap()
+ },
+ connection_state: ConnectionState::from_i32({
+ i.position(|x| *x == Variant::ByteArray(String::from("connectionState")))
+ .unwrap();
+
+ i.next().unwrap().try_into().unwrap()
+ })
+ .unwrap(),
+ irc_users: {
+ let users: Vec<IrcUser> = Vec::<IrcUser>::from_network(
+ &mut users_and_channels.get("Users").unwrap().try_into().unwrap(),
+ );
+ users
+ .into_iter()
+ .map(|user| (user.nick.clone(), user))
+ .collect()
+ },
+ irc_channels: {
+ let channels: Vec<IrcChannel> = Vec::<IrcChannel>::from_network(
+ &mut users_and_channels
+ .get("Channels")
+ .unwrap()
+ .try_into()
+ .unwrap(),
+ );
+ channels
+ .into_iter()
+ .map(|channel| (channel.name.clone(), channel))
+ .collect()
+ },
+ supports: {
+ i.position(|x| *x == Variant::ByteArray(String::from("Supports")))
+ .unwrap();
+
+ let var: VariantMap = i.next().unwrap().try_into().unwrap();
+
+ var.into_iter()
+ .map(|(k, v)| (k, v.try_into().unwrap()))
+ .collect()
+ },
+ caps: {
+ i.position(|x| *x == Variant::ByteArray(String::from("Caps")))
+ .unwrap();
+
+ let var: VariantMap = i.next().unwrap().try_into().unwrap();
+
+ var.into_iter()
+ .map(|(k, v)| (k, v.try_into().unwrap()))
+ .collect()
+ },
+ caps_enabled: {
+ i.position(|x| *x == Variant::ByteArray(String::from("CapsEnabled")))
+ .unwrap();
+
+ let var: VariantList = i.next().unwrap().try_into().unwrap();
+
+ var.into_iter().map(|v| v.try_into().unwrap()).collect()
+ },
+ network_info: NetworkInfo::from_network(input),
+ }
}
}
-#[allow(dead_code)]
#[derive(Debug, Clone, PartialEq, Network)]
#[network(repr = "map")]
pub struct NetworkServer {
@@ -274,6 +233,27 @@ pub struct NetworkServer {
pub proxy_pass: String,
}
+#[derive(Debug, Clone, PartialEq, Network)]
+#[network(repr = "list")]
+pub struct NetworkConfig {
+ #[network(rename = "pingTimeoutEnabled")]
+ ping_timeout_enabled: bool,
+ #[network(rename = "pingInterval")]
+ ping_interval: i32,
+ #[network(rename = "maxPingCount")]
+ max_ping_count: i32,
+ #[network(rename = "autoWhoEnabled")]
+ auto_who_enabled: bool,
+ #[network(rename = "autoWhoInterval")]
+ auto_who_interval: i32,
+ #[network(rename = "autoWhoNickLimit")]
+ auto_who_nick_limit: i32,
+ #[network(rename = "autoWhoDelay")]
+ auto_who_delay: i32,
+ #[network(rename = "standardCtcp")]
+ standard_ctcp: bool,
+}
+
#[cfg(test)]
mod tests {
use super::*;
diff --git a/src/message/signalproxy/objects/networkinfo.rs b/src/message/signalproxy/objects/networkinfo.rs
index e36297d..e5aa6ea 100644
--- a/src/message/signalproxy/objects/networkinfo.rs
+++ b/src/message/signalproxy/objects/networkinfo.rs
@@ -1,23 +1,16 @@
-use crate::primitive::{StringList, Variant};
+use crate::primitive::StringList;
-#[allow(unused_imports)]
use libquassel_derive::Network;
use crate::message::objects::network::NetworkServer;
-#[allow(dead_code)]
#[derive(Debug, Clone, PartialEq, Network)]
#[network(repr = "list")]
pub struct NetworkInfo {
#[network(rename = "networkName")]
pub network_name: String,
- #[network(
- rename = "ServerList",
- override_type = "VariantList",
- to_map = "|server| Variant::VariantMap(server.to_network())",
- from_map = "|server| NetworkServer::from_network(&mut match_variant!(server, Variant::VariantMap))"
- )]
+ #[network(rename = "ServerList", network, variant = "VariantList")]
pub server_list: Vec<NetworkServer>,
#[network(rename = "perform")]
pub perform: StringList,
@@ -75,15 +68,12 @@ pub struct NetworkInfo {
#[cfg(test)]
mod tests {
- use crate::{
- message::objects::network::NetworkServer,
- primitive::{Variant, VariantList},
- };
+ use crate::primitive::{Variant, VariantList};
use super::*;
use crate::message::signalproxy::translation::Network;
- use pretty_assertions::{assert_eq, assert_ne};
+ use pretty_assertions::assert_eq;
fn get_network() -> VariantList {
vec![
diff --git a/src/message/signalproxy/rpccall.rs b/src/message/signalproxy/rpccall.rs
index 2755ea1..0b5c598 100644
--- a/src/message/signalproxy/rpccall.rs
+++ b/src/message/signalproxy/rpccall.rs
@@ -1,7 +1,7 @@
use crate::message::MessageType;
use crate::primitive::Message;
use crate::primitive::{Variant, VariantList};
-use crate::{Deserialize, Serialize};
+use crate::{deserialize::Deserialize, serialize::Serialize};
#[derive(Clone, Debug, std::cmp::PartialEq)]
pub enum RpcCall {
diff --git a/src/message/signalproxy/syncmessage.rs b/src/message/signalproxy/syncmessage.rs
index b58659a..9c1716b 100644
--- a/src/message/signalproxy/syncmessage.rs
+++ b/src/message/signalproxy/syncmessage.rs
@@ -1,6 +1,6 @@
use crate::message::MessageType;
use crate::primitive::{Variant, VariantList};
-use crate::{Deserialize, Serialize};
+use crate::{deserialize::Deserialize, serialize::Serialize};
#[derive(Clone, Debug, std::cmp::PartialEq)]
pub struct SyncMessage {
diff --git a/src/primitive/bufferinfo.rs b/src/primitive/bufferinfo.rs
index 24080cb..97d9408 100644
--- a/src/primitive/bufferinfo.rs
+++ b/src/primitive/bufferinfo.rs
@@ -2,8 +2,7 @@ use std::vec::Vec;
use failure::Error;
-use crate::{Deserialize, DeserializeUTF8};
-use crate::{Serialize, SerializeUTF8};
+use crate::{deserialize::*, serialize::*};
/// The BufferInfo struct represents a BufferInfo as received in IRC
///
diff --git a/src/primitive/datetime.rs b/src/primitive/datetime.rs
index e4c4c83..8d78b32 100644
--- a/src/primitive/datetime.rs
+++ b/src/primitive/datetime.rs
@@ -1,5 +1,4 @@
-use crate::Deserialize;
-use crate::Serialize;
+use crate::{deserialize::*, serialize::*};
use time::{OffsetDateTime, PrimitiveDateTime, UtcOffset};
diff --git a/src/primitive/message.rs b/src/primitive/message.rs
index 04c427e..36a55c5 100644
--- a/src/primitive/message.rs
+++ b/src/primitive/message.rs
@@ -1,9 +1,10 @@
use std::vec::Vec;
+use num_derive::{FromPrimitive, ToPrimitive};
+
use failure::Error;
-use crate::{Deserialize, DeserializeUTF8};
-use crate::{Serialize, SerializeUTF8};
+use crate::{deserialize::*, serialize::*};
use crate::primitive::BufferInfo;
@@ -171,8 +172,9 @@ impl Deserialize for Message {
}
#[repr(i32)]
-#[derive(Copy, Clone, Debug, std::cmp::PartialEq)]
+#[derive(Copy, Clone, Debug, std::cmp::PartialEq, FromPrimitive, ToPrimitive)]
pub enum MessageType {
+ None = 0x00000000,
Plain = 0x00000001,
Notice = 0x00000002,
Action = 0x00000004,
diff --git a/src/primitive/signedint.rs b/src/primitive/signedint.rs
index a1254fb..2d2029d 100644
--- a/src/primitive/signedint.rs
+++ b/src/primitive/signedint.rs
@@ -6,7 +6,7 @@ use std::vec::Vec;
use failure::Error;
-use crate::{Deserialize, Serialize};
+use crate::{deserialize::*, serialize::*};
impl Serialize for i64 {
fn serialize(&self) -> Result<Vec<u8>, Error> {
diff --git a/src/primitive/string.rs b/src/primitive/string.rs
index 7ea838d..478bc0a 100644
--- a/src/primitive/string.rs
+++ b/src/primitive/string.rs
@@ -8,9 +8,7 @@ use failure::Error;
use log::trace;
use crate::util;
-use crate::{Deserialize, DeserializeUTF8, Serialize, SerializeUTF8};
-
-pub type ByteArray = String;
+use crate::{deserialize::*, serialize::*};
/// We Shadow the String type here as we can only use impl on types in our own scope.
///
@@ -21,10 +19,8 @@ impl Serialize for String {
fn serialize(&self) -> Result<Vec<u8>, Error> {
let mut res: Vec<u8> = Vec::new();
- let utf16: Vec<u16> = self.encode_utf16().collect();
- for i in utf16 {
- res.extend(i.to_be_bytes().iter());
- }
+ self.encode_utf16()
+ .for_each(|i| res.extend(i.to_be_bytes().iter()));
util::prepend_byte_len(&mut res);
return Ok(res);
diff --git a/src/primitive/stringlist.rs b/src/primitive/stringlist.rs
index df6d281..ceea63e 100644
--- a/src/primitive/stringlist.rs
+++ b/src/primitive/stringlist.rs
@@ -8,7 +8,7 @@ use failure::Error;
use log::trace;
-use crate::{Deserialize, Serialize};
+use crate::{deserialize::*, serialize::*};
/// StringList are represented as a Vec of Strings
///
diff --git a/src/primitive/unsignedint.rs b/src/primitive/unsignedint.rs
index 6e91e2a..90ec696 100644
--- a/src/primitive/unsignedint.rs
+++ b/src/primitive/unsignedint.rs
@@ -8,7 +8,7 @@ use std::vec::Vec;
use failure::Error;
use crate::error::ProtocolError;
-use crate::{Deserialize, Serialize};
+use crate::{deserialize::*, serialize::*};
impl Serialize for bool {
fn serialize(&self) -> Result<Vec<u8>, Error> {
diff --git a/src/primitive/variant.rs b/src/primitive/variant.rs
index 8a98d59..efe69b8 100644
--- a/src/primitive/variant.rs
+++ b/src/primitive/variant.rs
@@ -7,8 +7,7 @@ use log::{error, trace};
use crate::error::ProtocolError;
use crate::primitive;
use crate::primitive::StringList;
-use crate::{Deserialize, DeserializeUTF8};
-use crate::{Serialize, SerializeUTF8};
+use crate::{deserialize::*, serialize::*};
use crate::primitive::{BufferInfo, Date, DateTime, Message, Time, VariantList, VariantMap};
@@ -35,6 +34,7 @@ pub enum Variant {
DateTime(DateTime),
VariantMap(VariantMap),
VariantList(VariantList),
+ #[from(ignore)]
String(String),
#[from(ignore)]
ByteArray(String),
@@ -50,6 +50,32 @@ pub enum Variant {
i8(i8),
}
+impl From<Variant> for String {
+ fn from(input: Variant) -> Self {
+ match input {
+ Variant::String(value) => value,
+ Variant::ByteArray(value) => value,
+ _ => panic!("unknown variant expected string or bytearray"),
+ }
+ }
+}
+
+impl From<&Variant> for String {
+ fn from(input: &Variant) -> Self {
+ match input {
+ Variant::String(value) => value.clone(),
+ Variant::ByteArray(value) => value.clone(),
+ _ => panic!("unknown variant expected string or bytearray"),
+ }
+ }
+}
+
+impl From<String> for Variant {
+ fn from(input: String) -> Self {
+ Self::String(input)
+ }
+}
+
impl Serialize for Variant {
fn serialize(&self) -> Result<Vec<u8>, Error> {
let unknown: u8 = 0x00;
diff --git a/src/primitive/variantlist.rs b/src/primitive/variantlist.rs
index 7e74122..2d20ae2 100644
--- a/src/primitive/variantlist.rs
+++ b/src/primitive/variantlist.rs
@@ -5,7 +5,7 @@ use failure::Error;
use log::trace;
-use crate::{Deserialize, Serialize};
+use crate::{deserialize::*, serialize::*};
use crate::primitive::Variant;
diff --git a/src/primitive/variantmap.rs b/src/primitive/variantmap.rs
index d43028c..8c1032d 100644
--- a/src/primitive/variantmap.rs
+++ b/src/primitive/variantmap.rs
@@ -5,8 +5,7 @@ use failure::Error;
use log::trace;
-use crate::Deserialize;
-use crate::Serialize;
+use crate::{deserialize::*, serialize::*};
use crate::primitive::Variant;
use crate::util;
@@ -40,11 +39,11 @@ impl Deserialize for VariantMap {
let mut pos: usize = 4;
let mut map = VariantMap::new();
for _ in 0..len {
- trace!(target: "primitive::VariantMap", "Parsing entry name");
+ trace!(target: "primitive::VariantMap", "Parsing entry name {:x?}", &b[pos..]);
let (nlen, name) = String::parse(&b[pos..])?;
pos += nlen;
- trace!(target: "primitive::VariantMap", "Parsing entry: {:?} with len {:?}", name, &b[(pos)..(pos + 4)]);
+ trace!(target: "primitive::VariantMap", "Parsing entry: {:?} with type {:x?}", name, &b[(pos)..(pos + 4)]);
let (vlen, value) = Variant::parse(&b[(pos)..])?;
pos += vlen;