aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Audron <audron@cocaine.farm>2025-02-26 22:52:16 +0100
committerMax Audron <audron@cocaine.farm>2025-02-26 22:58:03 +0100
commita130eee7a71996f9ae50502c477a2c6494b78a83 (patch)
tree39d5e659ad1d537728757aa542968cb49b06bd35
parentimplement IdentityId (diff)
implement NetworkId UserType
-rw-r--r--derive/src/network/list.rs64
-rw-r--r--derive/src/network/map.rs42
-rw-r--r--derive/src/network/maplist.rs64
-rw-r--r--src/message/handshake/sessioninit.rs8
-rw-r--r--src/message/signalproxy/objects/bufferviewconfig.rs4
-rw-r--r--src/message/signalproxy/objects/networkinfo.rs21
-rw-r--r--src/primitive/mod.rs2
-rw-r--r--src/primitive/networkid.rs63
-rw-r--r--src/primitive/variant.rs17
-rw-r--r--src/session/mod.rs19
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 {