diff options
| -rw-r--r-- | derive/src/network/list.rs | 64 | ||||
| -rw-r--r-- | derive/src/network/map.rs | 42 | ||||
| -rw-r--r-- | derive/src/network/maplist.rs | 64 | ||||
| -rw-r--r-- | src/message/handshake/sessioninit.rs | 8 | ||||
| -rw-r--r-- | src/message/signalproxy/objects/bufferviewconfig.rs | 4 | ||||
| -rw-r--r-- | src/message/signalproxy/objects/networkinfo.rs | 21 | ||||
| -rw-r--r-- | src/primitive/mod.rs | 2 | ||||
| -rw-r--r-- | src/primitive/networkid.rs | 63 | ||||
| -rw-r--r-- | src/primitive/variant.rs | 17 | ||||
| -rw-r--r-- | src/session/mod.rs | 19 |
10 files changed, 196 insertions, 108 deletions
diff --git a/derive/src/network/list.rs b/derive/src/network/list.rs index 973444e..1fc8f7e 100644 --- a/derive/src/network/list.rs +++ b/derive/src/network/list.rs @@ -43,19 +43,31 @@ pub(crate) fn from(fields: &Vec<NetworkField>) -> Vec<TokenStream> { .map(|field| { let field_name = field.ident.as_ref().unwrap(); - if field.default { + let field_rename = match &field.rename { + Some(name) => name.clone(), + None => format!("{}", field.ident.as_ref().unwrap()).into(), + }; + + let field_variant_type = get_field_variant_type(&field); + + let extract_inner = if field.default { quote! { - #field_name: Default::default(), + let mut i = input.iter(); + match i.position(|x| *x == libquassel::primitive::Variant::ByteArray(String::from(#field_rename))) { + Some(_) => { + match i.next().expect("failed to get next field") { + libquassel::primitive::Variant::#field_variant_type(var) => var + .clone() + .try_into() + .unwrap_or(Default::default()), + _ => Default::default(), + } + } + None => Default::default(), + } } } else { - let field_rename = match &field.rename { - Some(name) => name.clone(), - None => format!("{}", field.ident.as_ref().unwrap()).into(), - }; - - let field_variant_type = get_field_variant_type(&field); - - let extract_inner = quote! { + quote! { let mut i = input.iter(); i.position(|x| *x == libquassel::primitive::Variant::ByteArray(String::from(#field_rename))) .expect(format!("failed to get field {}", #field_rename).as_str()); @@ -64,25 +76,25 @@ pub(crate) fn from(fields: &Vec<NetworkField>) -> Vec<TokenStream> { libquassel::primitive::Variant::#field_variant_type(var) => var.clone().try_into().unwrap(), _ => panic!("network::list::from: wrong variant type"), } - }; + } + }; - match field.network { - super::NetworkRepr::List => quote! { - #field_name: libquassel::message::NetworkList::from_network_list(&mut { - #extract_inner - }), - }, - super::NetworkRepr::Map => quote! { - #field_name: libquassel::message::NetworkMap::from_network_map(&mut { - #extract_inner - }), - }, - super::NetworkRepr::None => quote! { - #field_name: { + match field.network { + super::NetworkRepr::List => quote! { + #field_name: libquassel::message::NetworkList::from_network_list(&mut { #extract_inner - }, + }), }, - } + super::NetworkRepr::Map => quote! { + #field_name: libquassel::message::NetworkMap::from_network_map(&mut { + #extract_inner + }), + }, + super::NetworkRepr::None => quote! { + #field_name: { + #extract_inner + }, + }, } }) .collect() diff --git a/derive/src/network/map.rs b/derive/src/network/map.rs index 0550ccb..4efc3bf 100644 --- a/derive/src/network/map.rs +++ b/derive/src/network/map.rs @@ -45,29 +45,29 @@ pub(crate) fn from(fields: &Vec<NetworkField>) -> Vec<TokenStream> { .map(|field| { let field_name = field.ident.as_ref().unwrap(); - if field.default { - quote! { - #field_name: Default::default(), - } + let unwrap = if field.default { + quote! { unwrap_or_default() } } else { - let field_rename = match &field.rename { - Some(name) => name.clone(), - None => format!("{}", field.ident.as_ref().unwrap()).into(), - }; + quote! { unwrap() } + }; - match field.network { - super::NetworkRepr::List => quote! { - #field_name: libquassel::message::NetworkList::from_network_list( - &mut std::convert::TryInto::try_into(input.remove(#field_rename).unwrap()).unwrap()), - }, - super::NetworkRepr::Map => quote! { - #field_name: libquassel::message::NetworkMap::from_network_map( - &mut std::convert::TryInto::try_into(input.remove(#field_rename).unwrap()).unwrap()), - }, - super::NetworkRepr::None => quote! { - #field_name: std::convert::TryInto::try_into(input.remove(#field_rename).unwrap()).unwrap(), - }, - } + let field_rename = match &field.rename { + Some(name) => name.clone(), + None => format!("{}", field.ident.as_ref().unwrap()).into(), + }; + + match field.network { + super::NetworkRepr::List => quote! { + #field_name: libquassel::message::NetworkList::from_network_list( + &mut std::convert::TryInto::try_into(input.remove(#field_rename).unwrap()).#unwrap), + }, + super::NetworkRepr::Map => quote! { + #field_name: libquassel::message::NetworkMap::from_network_map( + &mut std::convert::TryInto::try_into(input.remove(#field_rename).unwrap()).#unwrap), + }, + super::NetworkRepr::None => quote! { + #field_name: std::convert::TryInto::try_into(input.remove(#field_rename).unwrap()).#unwrap, + }, } }) .collect() diff --git a/derive/src/network/maplist.rs b/derive/src/network/maplist.rs index 8ce18c5..b5b4a86 100644 --- a/derive/src/network/maplist.rs +++ b/derive/src/network/maplist.rs @@ -137,42 +137,42 @@ pub(crate) fn from(fields: &Vec<NetworkField>) -> Vec<TokenStream> { .map(|field| { let field_name = field.ident.as_ref().unwrap(); - if field.default { + let unwrap = if field.default { + quote! { unwrap_or_default() } + } else { + quote! { unwrap() } + }; + + let field_rename = match &field.rename { + Some(name) => name.clone(), + None => format!("{}", field.ident.as_ref().unwrap()).into(), + }; + + let field_inner = match field.network { + super::NetworkRepr::List => quote! { + libquassel::message::NetworkList::from_network_list(&mut std::convert::TryInto::try_into(input.remove(0)).#unwrap) + }, + super::NetworkRepr::Map => quote! { + libquassel::message::NetworkMap::from_network_map(&mut std::convert::TryInto::try_into(input.remove(0)).#unwrap) + }, + super::NetworkRepr::None => quote! { + std::convert::TryInto::try_into(input.remove(0)).#unwrap + }, + }; + + if field.stringlist { quote! { - #field_name: Default::default(), + #field_name: match input.get_mut(#field_rename).unwrap() { + libquassel::primitive::Variant::StringList(input) => #field_inner, + _ => panic!("#field_name: wrong variant") + }, } } else { - let field_rename = match &field.rename { - Some(name) => name.clone(), - None => format!("{}", field.ident.as_ref().unwrap()).into(), - }; - - let field_inner = match field.network { - super::NetworkRepr::List => quote! { - libquassel::message::NetworkList::from_network_list(&mut std::convert::TryInto::try_into(input.remove(0)).unwrap()) - }, - super::NetworkRepr::Map => quote! { - libquassel::message::NetworkMap::from_network_map(&mut std::convert::TryInto::try_into(input.remove(0)).unwrap()) - }, - super::NetworkRepr::None => quote! { - std::convert::TryInto::try_into(input.remove(0)).unwrap() + quote! { + #field_name: match input.get_mut(#field_rename).unwrap() { + libquassel::primitive::Variant::VariantList(input) => #field_inner, + _ => panic!("#field_name: wrong variant") }, - }; - - if field.stringlist { - quote! { - #field_name: match input.get_mut(#field_rename).unwrap() { - libquassel::primitive::Variant::StringList(input) => #field_inner, - _ => panic!("#field_name: wrong variant") - }, - } - } else { - quote! { - #field_name: match input.get_mut(#field_rename).unwrap() { - libquassel::primitive::Variant::VariantList(input) => #field_inner, - _ => panic!("#field_name: wrong variant") - }, - } } } }) diff --git a/src/message/handshake/sessioninit.rs b/src/message/handshake/sessioninit.rs index 048324d..52e59ae 100644 --- a/src/message/handshake/sessioninit.rs +++ b/src/message/handshake/sessioninit.rs @@ -1,6 +1,6 @@ use crate::error::ProtocolError; use crate::message::objects::Identity; -use crate::primitive::{BufferInfo, Variant, VariantMap}; +use crate::primitive::{BufferInfo, NetworkId, Variant, VariantMap}; use crate::HandshakeSerialize; /// SessionInit is received along with ClientLoginAck to initialize that user Session @@ -12,7 +12,7 @@ pub struct SessionInit { /// List of all existing buffers pub buffers: Vec<BufferInfo>, /// Ids of all networks - pub network_ids: Vec<i32>, + pub network_ids: Vec<NetworkId>, } impl From<VariantMap> for SessionInit { @@ -36,7 +36,7 @@ impl From<VariantMap> for SessionInit { network_ids: match_variant!(state.get("NetworkIds").unwrap(), Variant::VariantList) .iter() .map(|network| match network { - Variant::i32(network) => network.clone(), + Variant::NetworkId(network) => network.clone(), _ => unimplemented!(), }) .collect(), @@ -71,7 +71,7 @@ impl HandshakeSerialize for SessionInit { Variant::VariantList( self.network_ids .iter() - .map(|id| Variant::i32(id.clone())) + .map(|id| Variant::NetworkId(id.clone())) .collect(), ), ); diff --git a/src/message/signalproxy/objects/bufferviewconfig.rs b/src/message/signalproxy/objects/bufferviewconfig.rs index a31ec92..8ca6b82 100644 --- a/src/message/signalproxy/objects/bufferviewconfig.rs +++ b/src/message/signalproxy/objects/bufferviewconfig.rs @@ -7,7 +7,7 @@ use crate::message::StatefulSyncableClient; use crate::message::StatefulSyncableServer; use crate::message::{Class, Syncable}; -use crate::primitive::{BufferId, VariantList}; +use crate::primitive::{BufferId, NetworkId, VariantList}; #[derive(Debug, Default, Clone, PartialEq, NetworkList, NetworkMap)] pub struct BufferViewConfig { @@ -27,7 +27,7 @@ pub struct BufferViewConfig { #[network(rename = "bufferViewName")] pub buffer_view_name: String, #[network(rename = "networkId")] - pub network_id: i32, + pub network_id: NetworkId, #[network(rename = "addNewBuffersAutomatically")] pub add_new_buffers_automatically: bool, #[network(rename = "sortAlphabetically")] diff --git a/src/message/signalproxy/objects/networkinfo.rs b/src/message/signalproxy/objects/networkinfo.rs index b3b2a4d..4cdf8d7 100644 --- a/src/message/signalproxy/objects/networkinfo.rs +++ b/src/message/signalproxy/objects/networkinfo.rs @@ -1,6 +1,6 @@ use crate::{ message::{Class, Syncable}, - primitive::{IdentityId, StringList}, + primitive::{IdentityId, NetworkId, StringList}, }; use libquassel_derive::{NetworkList, NetworkMap, Setters}; @@ -37,7 +37,8 @@ pub struct NetworkInfo { pub codec_for_decoding: String, // TODO add these type aliases or usertypes in variants - // pub network_id: NetworkId, + #[network(rename = "networkId", default)] + pub network_id: NetworkId, #[network(rename = "identityId")] pub identity_id: IdentityId, #[network(rename = "msgRateBurstSize")] @@ -119,6 +120,8 @@ mod tests { Variant::ByteArray(s!("")), Variant::ByteArray(s!("codecForDecoding")), Variant::ByteArray(s!("")), + Variant::ByteArray(s!("networkId")), + Variant::NetworkId(NetworkId(5)), Variant::ByteArray(s!("identityId")), Variant::IdentityId(IdentityId(0)), Variant::ByteArray(s!("msgRateBurstSize")), @@ -151,6 +154,7 @@ mod tests { fn get_runtime() -> NetworkInfo { NetworkInfo { identity_id: IdentityId(0), + network_id: NetworkId(5), network_name: s!("snoonet"), server_list: vec![], perform: vec![s!("")], @@ -179,11 +183,20 @@ mod tests { #[test] fn networkinfo_to_network() { - assert_eq!(get_runtime().to_network_list(), get_network()) + assert_eq!(get_runtime().to_network_list(), get_network()); + assert_eq!(get_runtime().to_network_list(), get_network()); } #[test] fn networkinfo_from_network() { - assert_eq!(NetworkInfo::from_network_list(&mut get_network()), get_runtime()) + assert_eq!(NetworkInfo::from_network_list(&mut get_network()), get_runtime()); + + // Test serialization without given network id + let mut network = get_network(); + network.remove(20); + network.remove(20); + + let left = NetworkInfo::from_network_list(&mut network); + assert_eq!(left.network_id, NetworkId(0)); } } diff --git a/src/primitive/mod.rs b/src/primitive/mod.rs index dbc82d0..79ff6c4 100644 --- a/src/primitive/mod.rs +++ b/src/primitive/mod.rs @@ -4,6 +4,7 @@ mod datetime; mod identityid; mod message; mod msgid; +mod networkid; mod peerptr; mod signedint; mod string; @@ -19,6 +20,7 @@ pub use datetime::*; pub use identityid::*; pub use message::*; pub use msgid::*; +pub use networkid::*; pub use peerptr::*; #[allow(unused_imports)] pub use signedint::*; diff --git a/src/primitive/networkid.rs b/src/primitive/networkid.rs new file mode 100644 index 0000000..1cfff61 --- /dev/null +++ b/src/primitive/networkid.rs @@ -0,0 +1,63 @@ +#[derive(Copy, Clone, Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash)] +#[repr(transparent)] +pub struct NetworkId(pub i32); + +use crate::{error::ProtocolError, serialize::*}; + +use crate::serialize::UserType; + +impl Serialize for NetworkId { + fn serialize(&self) -> Result<Vec<u8>, ProtocolError> { + let mut res = Vec::new(); + + res.append(&mut Self::NAME.serialize_utf8()?); + res.extend(self.0.serialize()?); + + Ok(res) + } +} + +impl Deserialize for NetworkId { + fn parse(b: &[u8]) -> Result<(usize, Self), ProtocolError> { + let (size, value) = i32::parse(b)?; + return Ok((size, NetworkId(value))); + } +} + +impl From<i32> for NetworkId { + fn from(value: i32) -> Self { + NetworkId(value) + } +} + +impl std::ops::Deref for NetworkId { + type Target = i32; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl UserType for NetworkId { + const NAME: &str = "NetworkId"; +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + pub fn networkid_parse_test() { + let test_bytes: &[u8] = &[0, 0, 0, 1]; + let (len, res) = NetworkId::parse(test_bytes).unwrap(); + assert_eq!(len, test_bytes.len()); + assert_eq!(res, NetworkId(1)); + } + + #[test] + pub fn networkid_serialize_test() { + let res = NetworkId(1).serialize().unwrap(); + let expected_bytes: &[u8] = &[0, 0, 0, 9, 78, 101, 116, 119, 111, 114, 107, 73, 100, 0, 0, 0, 1]; + assert_eq!(res, expected_bytes); + } +} diff --git a/src/primitive/variant.rs b/src/primitive/variant.rs index e8eea86..d39e0bf 100644 --- a/src/primitive/variant.rs +++ b/src/primitive/variant.rs @@ -1,10 +1,10 @@ use std::{collections::HashMap, vec::Vec}; use itertools::Itertools; -use log::{error, trace}; +use log::{debug, error, trace}; use crate::error::ProtocolError; -use crate::primitive::{self, PeerPtr}; +use crate::primitive::{self, NetworkId, PeerPtr}; use crate::primitive::{IdentityId, StringList}; use crate::serialize::*; @@ -31,6 +31,7 @@ pub enum Variant { IdentityId(IdentityId), Message(Message), MsgId(MsgId), + NetworkId(NetworkId), Time(Time), Date(Date), DateTime(DateTime), @@ -194,6 +195,7 @@ impl Serialize for Variant { Variant::IdentityId(v) => v.serialize_variant(), Variant::Message(v) => v.serialize_variant(), Variant::MsgId(v) => v.serialize_variant(), + Variant::NetworkId(v) => v.serialize_variant(), Variant::PeerPtr(v) => v.serialize_variant(), Variant::DateTime(v) => v.serialize_variant(), Variant::Time(v) => v.serialize_variant(), @@ -241,23 +243,16 @@ impl Deserialize for Variant { trace!(target: "primitive::Variant", "Parsing UserType: {:?}", user_type); - // TODO implement all these types // Match Possible User Types to basic structures match user_type.as_str() { BufferId::NAME => BufferId::parse_variant(b, len + user_type_len), // As VariantMap "IrcUser" | "IrcChannel" | "Identity" | "NetworkInfo" | "Network::Server" => { - trace!(target: "primitive::Variant", "UserType is VariantMap"); let (vlen, value) = VariantMap::parse(&b[(len + user_type_len)..])?; + debug!(target: "primitive::Variant", "UserType is VariantMap {:?}", value); return Ok((len + user_type_len + vlen, Variant::VariantMap(value))); } - // As i32 - "NetworkId" => { - trace!(target: "primitive::Variant", "UserType is i32"); - - let (vlen, value) = i32::parse(&b[(len + user_type_len)..])?; - return Ok((len + user_type_len + vlen, Variant::i32(value))); - } + NetworkId::NAME => NetworkId::parse_variant(b, len + user_type_len), IdentityId::NAME => IdentityId::parse_variant(b, len + user_type_len), PeerPtr::NAME => PeerPtr::parse_variant(b, len + user_type_len), BufferInfo::NAME => BufferInfo::parse_variant(b, len + user_type_len), diff --git a/src/session/mod.rs b/src/session/mod.rs index 392e6e1..31842b1 100644 --- a/src/session/mod.rs +++ b/src/session/mod.rs @@ -7,9 +7,12 @@ use crate::message::StatefulSyncableServer; use log::{debug, error, warn}; -use crate::message::{ - objects::{Types, *}, - Class, InitData, SessionInit, SyncMessage, Syncable, +use crate::{ + message::{ + objects::{Types, *}, + Class, InitData, SessionInit, SyncMessage, Syncable, + }, + primitive::NetworkId, }; // TODO implement nested types init and sync like BufferViewConfig in BufferViewManager @@ -25,7 +28,7 @@ pub struct Session { pub highlight_rule_manager: HighlightRuleManager, pub identities: Vec<Identity>, pub ignore_list_manager: IgnoreListManager, - pub networks: HashMap<i32, Network>, + pub networks: HashMap<NetworkId, Network>, pub network_config: NetworkConfig, } @@ -41,7 +44,7 @@ pub trait SessionManager { fn identities(&mut self) -> &mut Vec<Identity>; fn identity(&mut self, id: usize) -> Option<&mut Identity>; fn ignore_list_manager(&mut self) -> &mut IgnoreListManager; - fn networks(&mut self) -> &mut HashMap<i32, Network>; + fn networks(&mut self) -> &mut HashMap<NetworkId, Network>; fn network(&mut self, id: i32) -> Option<&mut Network>; fn network_config(&mut self) -> &mut NetworkConfig; @@ -166,7 +169,7 @@ pub trait SessionManager { Types::IgnoreListManager(data) => self.ignore_list_manager().init(data), Types::CertManager(data) => self.cert_manager().init(data), Types::Network(network) => { - let id: i32 = data.object_name.parse().unwrap(); + let id: NetworkId = NetworkId(data.object_name.parse().unwrap()); self.networks().insert(id, network); } Types::NetworkInfo(_) => (), @@ -225,12 +228,12 @@ impl SessionManager for Session { &mut self.ignore_list_manager } - fn networks(&mut self) -> &mut HashMap<i32, Network> { + fn networks(&mut self) -> &mut HashMap<NetworkId, Network> { &mut self.networks } fn network(&mut self, id: i32) -> Option<&mut Network> { - self.networks.get_mut(&id) + self.networks.get_mut(&NetworkId(id)) } fn network_config(&mut self) -> &mut NetworkConfig { |
