diff options
| author | Max Audron <audron@cocaine.farm> | 2025-02-27 01:03:29 +0100 |
|---|---|---|
| committer | Max Audron <audron@cocaine.farm> | 2025-02-27 01:03:29 +0100 |
| commit | e4338a9d9d0a76029bca376c2bcb499962575e87 (patch) | |
| tree | a0c14be508381e3f5091d1872210edd612f57dde | |
| parent | implement NetworkId UserType (diff) | |
extend docs and reorganize files
Diffstat (limited to '')
| -rw-r--r-- | README.md | 36 | ||||
| -rw-r--r-- | derive/src/lib.rs | 8 | ||||
| -rw-r--r-- | src/error.rs (renamed from src/error/mod.rs) | 0 | ||||
| -rw-r--r-- | src/lib.rs | 93 | ||||
| -rw-r--r-- | src/message/signalproxy/mod.rs | 2 | ||||
| -rw-r--r-- | src/message/signalproxy/translation.rs | 122 | ||||
| -rw-r--r-- | src/message/signalproxy/translation/aos_soa.rs | 1134 | ||||
| -rw-r--r-- | src/message/signalproxy/translation/mod.rs | 112 | ||||
| -rw-r--r-- | src/primitive/variant.rs | 2 | ||||
| -rw-r--r-- | src/serialize.rs | 66 | ||||
| -rw-r--r-- | src/session.rs (renamed from src/session/mod.rs) | 14 | ||||
| -rw-r--r-- | src/util.rs | 13 |
12 files changed, 321 insertions, 1281 deletions
@@ -17,20 +17,22 @@ Native rust implementation of the Quassel protocol and library functions # TODOs -- [TODO] Implementation of Syncable Objects {#implementation-of-syncable-objects} - - [DONE] AliasManager - - [TODO] BacklogManager - - [DONE] BufferSyncer - - [DONE] BufferViewConfig - - [DONE] BufferViewManager - - [DONE] CertManager - - [DONE] CoreInfo - - [DONE] HighlightRuleManager - - [DONE] Identity - - [DONE] IgnoreListManager - - [DONE] IrcChannel - - [TODO] IrcListHelper - - [TODO] IrcUser - - [TODO] Network - - [TODO] NetworkInfo - - [TODO] NetworkConfig +- [ ] Implementation of Syncable Objects + - [X] AliasManager + - [ ] BacklogManager + - [X] BufferSyncer + - [X] BufferViewConfig + - [X] BufferViewManager + - [X] CertManager + - [X] CoreInfo + - [X] HighlightRuleManager + - [X] Identity + - [X] IgnoreListManager + - [X] IrcChannel + - [ ] IrcListHelper + - [X] IrcUser + - [X] Network + - [X] NetworkInfo + - [X] NetworkConfig +- [ ] Rework Error handling to actually handle errors +- [ ] Rewrite the parsers using nom diff --git a/derive/src/lib.rs b/derive/src/lib.rs index 71feae7..47e8ad8 100644 --- a/derive/src/lib.rs +++ b/derive/src/lib.rs @@ -2,8 +2,8 @@ use syn; mod from; mod network; -mod sync; mod setters; +mod sync; #[proc_macro_derive(NetworkList, attributes(network))] pub fn network_list(input: proc_macro::TokenStream) -> proc_macro::TokenStream { @@ -25,12 +25,6 @@ pub fn setters(input: proc_macro::TokenStream) -> proc_macro::TokenStream { setters::setters(input) } -/// Sugar to make sending sync messages nicer -/// -/// Example: -/// ``` -/// sync!("requestCreateBufferView", [properties.to_network_map()]) -/// ``` #[proc_macro] pub fn sync(input: proc_macro::TokenStream) -> proc_macro::TokenStream { sync::sync(input) diff --git a/src/error/mod.rs b/src/error.rs index 7414062..7414062 100644 --- a/src/error/mod.rs +++ b/src/error.rs @@ -1,8 +1,9 @@ +#![doc = include_str!("../README.md")] #![cfg_attr(all(test, feature = "bench"), feature(test))] + #[cfg(all(test, feature = "bench"))] extern crate test; -#[doc = include_str!("../README.md")] #[cfg_attr(docsrs, feature(doc_cfg))] extern crate self as libquassel; @@ -50,3 +51,93 @@ pub trait HandshakeDeserialize { where Self: std::marker::Sized; } + +/// Derive the [message::NetworkList] and [message::NetworkMap] traits. +/// +/// This provides easy and boilerplate free implementations for the network translations from and to the raw +/// Variants. For details on the different kinds of mappings see [message::translation] +/// +/// ```rust ignore +/// use libquassel::{NetworkList, NetworkMap}; +/// +/// #[derive(NetworkMap, NetworkList)] +/// #[network(repr = "map")] +/// pub struct Example { +/// #[network(rename = "Name", default)] +/// pub name: String, +/// #[network(rename = "Nested", network = "map", variant = "VariantMap")] +/// pub nested: Nested, +/// } +/// +/// type Value = i32; +/// +/// #[derive(NetworkMap, NetworkList)] +/// #[network(repr = "maplist")] +/// pub struct Nested { +/// #[network(rename = "Name", type = "i32")] +/// pub field: Value +/// } +/// ``` +/// +/// ## Attributes +/// ### Object Attributes +/// - `#[network(repr = "...")]` +/// +/// Sets the network representation used for this object. Only applies to [NetworkMap] +/// +/// Either [`maplist`] or [`map`] +/// +/// ### Field Attributes +/// - `#[network(rename = "name")]` +/// +/// Renames the field to change case or spelling etc. +/// +/// - `#[network(skip)]` +/// +/// Ignore this field completly in both to and from conversions. +/// - `#[network(default)]` +/// +/// If the field is not set in the network representation, fall back on [`Default::default()`]. +/// +/// May be used if the network representation does not always contain a field. +/// +/// - `#[network(network = "...")]` +/// +/// Use either NetworkMap or NetworkList translation trait to convert this field depending +/// on if `map` or `list` is set respectivly. +/// +/// - `#[network(variant = "...")]` +/// +/// Override the variant used to convert the field, instead of the fields type itself. +/// +/// E.g if the field is of type `String` but the network representation wants `ByteArray` then +/// set this here. +/// +/// - `#[network(type = "...")]` +/// +/// Override the type of the field that is used e.g. when you are using a type alias. +/// +/// This differs from setting the `variant` as it will also influence the inner type instead +/// of just the wrapping Variant +/// +/// - `#[network(stringlist)]` +/// +/// Special case handling for if the field type is `Vec<String>`. +/// +/// This would by default be converted to a `Variant::VariantList(Vec<Variant::String>)` but for +/// strings the [StringList] representation is used: `Variant::StringList(Vec<String>)` +/// +/// [`maplist`]: libquassel::message::translation#structure-of-arrays +/// [`map`]: libquassel::message::translation#variantmap +/// [StringList]: libquassel::primitive::StringList +pub use libquassel_derive::{NetworkList, NetworkMap}; + +/// send a syncmessage using [`Syncable::send_sync`] and casts it's arguments to the correct Variants +/// +/// Example: +/// ```rust ignore +/// sync!("requestCreateBufferView", [properties.to_network_map()]) +/// ``` +/// +/// [`Syncable::send_sync`]: libquassel::message::Syncable::send_sync +pub use libquassel_derive::sync; diff --git a/src/message/signalproxy/mod.rs b/src/message/signalproxy/mod.rs index 6cd887b..062b400 100644 --- a/src/message/signalproxy/mod.rs +++ b/src/message/signalproxy/mod.rs @@ -15,7 +15,7 @@ pub mod objects; mod rpccall; mod syncmessage; -mod translation; +pub mod translation; pub use translation::*; pub use heartbeat::*; diff --git a/src/message/signalproxy/translation.rs b/src/message/signalproxy/translation.rs new file mode 100644 index 0000000..b175e44 --- /dev/null +++ b/src/message/signalproxy/translation.rs @@ -0,0 +1,122 @@ +//! Traits for Network Representation translation +//! +//! The traits found here usually do not need to implemented manually and can be derived using the [`libquassel::NetworkList`] and [`libquassel::NetworkMap`] macros. +//! +//! Quassel has 3 main ways to represent an object over the Network: +//! +//! ### VariantList +//! The struct is serialized to a Vector of Variants. This is mostly used in the InitData messages. +//! First the field name as a ByteArray (UTF-8 String), followed by the field value in it's own Type's va!iant. +//! The order in which the fields are transmitted cannot be assumed. +//! +//! Example: +//! ```ignore +//! NetworkConfig { +//! ping_timeout_enabled: true, +//! ping_interval: 0, +//! } +//! ``` +//! to +//! ```ignore +//! VariantList([ +//! ByteArray( +//! "pingTimeoutEnabled", +//! ), +//! bool( +//! true, +//! ), +//! ByteArray( +//! "pingInterval", +//! ), +//! i32( +//! 30, +//! ), +//! ]) +//! ``` +//! +//! +//! ### VariantMap +//! The struct is represented as a `VariantMap`. The keys and values of +//! the struct are serialized to a corresponding `HashMap<String, Variant>`. +//! +//! Using the [libquassel::NetworkMap] macro this is selected with `#[network(repr = "map")]` on the object. +//! +//! Example: +//! ```ignore +//! NetworkConfig { +//! ping_timeout_enabled: false, +//! ping_interval: 0, +//! } +//! ``` +//! to +//! ```ignore +//! VariantMap({ +//! "pingTimeoutEnabled": bool(false) +//! "pingInterval": i32(0) +//! }) +//! ``` +//! +//! ### Structure of Arrays +//! +//! For Objects that are transmitted as multiple at once the VariantMap +//! representation is augemented and instead of transmitting multiple `VariantMaps`, +//! each field is a `VariantList` of Items. +//! +//! Using the [libquassel::NetworkMap] macro this is selected with `#[network(repr = "maplist")]` on the +//! object. +//! +//! Example: +//! ```ignore +//! vec![ +//! NetworkConfig { +//! ping_timeout_enabled: false, +//! ping_interval: 0, +//! }, +//! NetworkConfig { +//! ping_timeout_enabled: true, +//! ping_interval: 1, +//! }, +//! ] +//! ``` +//! to +//! ```ignore +//! VariantMap({ +//! "pingTimeoutEnabled": VariantList([ +//! bool(false), +//! bool(true), +//! ]), +//! "pingInterval": VariantList([ +//! i32(0), +//! i32(1), +//! ]) +//! }) +//! ``` +use crate::primitive::{Variant, VariantList}; + +#[deprecated( + since = "0.1.0", + note = "please use NetworkMap and NetworkList implementations" +)] +pub trait Network { + type Item; + + fn to_network(&self) -> Self::Item; + fn from_network(input: &mut Self::Item) -> Self; +} + +pub trait NetworkMap +where + // TODO correct this error type + Self::Item: TryFrom<Variant, Error = String>, + Self::Item: Into<Variant>, +{ + type Item; + + fn to_network_map(&self) -> Self::Item; + fn from_network_map(input: &mut Self::Item) -> Self; +} + +pub trait NetworkList { + fn to_network_list(&self) -> VariantList; + fn from_network_list(input: &mut VariantList) -> Self; +} diff --git a/src/message/signalproxy/translation/aos_soa.rs b/src/message/signalproxy/translation/aos_soa.rs deleted file mode 100644 index c070aea..0000000 --- a/src/message/signalproxy/translation/aos_soa.rs +++ /dev/null @@ -1,1134 +0,0 @@ -// InitData { -// class_name: "AliasManager", -// object_name: "", -// init_data: [ -// Variant::ByteArray( -// "Aliases", -// ), -// Variant::VariantMap( -// { -// "names": Variant::StringList( -// [ -// "j", -// "ns", -// "nickserv", -// "cs", -// "chanserv", -// "hs", -// "hostserv", -// "wii", -// "back", -// "inxi", -// "sysinfo", -// ], -// ), -// "expansions": Variant::StringList( -// [ -// "/join $0", -// "/msg nickserv $0", -// "/msg nickserv $0", -// "/msg chanserv $0", -// "/msg chanserv $0", -// "/msg hostserv $0", -// "/msg hostserv $0", -// "/whois $0 $0", -// "/quote away", -// "/exec inxi $0", -// "/exec inxi -d", -// ], -// ), -// }, -// ), -// ], -// }, - -// InitData { -// class_name: "Network", -// object_name: "2", -// init_data: [ -// ByteArray( -// "Caps", -// ), -// VariantMap( -// { -// "message-tags": String( -// "", -// ), -// "multi-prefix": String( -// "", -// ), -// "echo-message": String( -// "", -// ), -// "away-notify": String( -// "", -// ), -// "inspircd.org/standard-replies": String( -// "", -// ), -// "sasl": String( -// "", -// ), -// "labeled-response": String( -// "", -// ), -// "inspircd.org/poison": String( -// "", -// ), -// "account-tag": String( -// "", -// ), -// "userhost-in-names": String( -// "", -// ), -// "account-notify": String( -// "", -// ), -// "extended-join": String( -// "", -// ), -// "server-time": String( -// "", -// ), -// "chghost": String( -// "", -// ), -// "setname": String( -// "", -// ), -// "cap-notify": String( -// "", -// ), -// "batch": String( -// "", -// ), -// "sts": String( -// "duration=15552000,preload", -// ), -// "invite-notify": String( -// "", -// ), -// }, -// ), -// ByteArray( -// "CapsEnabled", -// ), -// VariantList( -// [ -// String( -// "account-notify", -// ), -// String( -// "away-notify", -// ), -// String( -// "cap-notify", -// ), -// String( -// "chghost", -// ), -// String( -// "extended-join", -// ), -// String( -// "multi-prefix", -// ), -// String( -// "userhost-in-names", -// ), -// ], -// ), -// ByteArray( -// "IrcUsersAndChannels", -// ), -// VariantMap( -// { -// "Users": VariantMap( -// { -// "suserHost": VariantList( -// [ -// String( -// "", -// ), -// String( -// "", -// ), -// String( -// "", -// ), -// String( -// "", -// ), -// String( -// "", -// ), -// ], -// ), -// "lastAwayMessageTime": VariantList( -// [ -// DateTime( -// OffsetDateTime { -// utc_datetime: PrimitiveDateTime { -// date: Date { -// year: 1970, -// ordinal: 1, -// }, -// time: Time { -// hour: 0, -// minute: 0, -// second: 0, -// nanosecond: 0, -// }, -// }, -// offset: UtcOffset { -// seconds: 0, -// }, -// }, -// ), -// DateTime( -// OffsetDateTime { -// utc_datetime: PrimitiveDateTime { -// date: Date { -// year: 1970, -// ordinal: 1, -// }, -// time: Time { -// hour: 0, -// minute: 0, -// second: 0, -// nanosecond: 0, -// }, -// }, -// offset: UtcOffset { -// seconds: 0, -// }, -// }, -// ), -// DateTime( -// OffsetDateTime { -// utc_datetime: PrimitiveDateTime { -// date: Date { -// year: 1970, -// ordinal: 1, -// }, -// time: Time { -// hour: 0, -// minute: 0, -// second: 0, -// nanosecond: 0, -// }, -// }, -// offset: UtcOffset { -// seconds: 0, -// }, -// }, -// ), -// DateTime( -// OffsetDateTime { -// utc_datetime: PrimitiveDateTime { -// date: Date { -// year: 1970, -// ordinal: 1, -// }, -// time: Time { -// hour: 0, -// minute: 0, -// second: 0, -// nanosecond: 0, -// }, -// }, -// offset: UtcOffset { -// seconds: 0, -// }, -// }, -// ), -// DateTime( -// OffsetDateTime { -// utc_datetime: PrimitiveDateTime { -// date: Date { -// year: 1970, -// ordinal: 1, -// }, -// time: Time { -// hour: 0, -// minute: 0, -// second: 0, -// nanosecond: 0, -// }, -// }, -// offset: UtcOffset { -// seconds: 0, -// }, -// }, -// ), -// ], -// ), -// "away": VariantList( -// [ -// bool( -// false, -// ), -// bool( -// false, -// ), -// bool( -// false, -// ), -// bool( -// false, -// ), -// bool( -// false, -// ), -// ], -// ), -// "ircOperator": VariantList( -// [ -// String( -// "", -// ), -// String( -// "", -// ), -// String( -// "", -// ), -// String( -// "", -// ), -// String( -// "", -// ), -// ], -// ), -// "account": VariantList( -// [ -// String( -// "", -// ), -// String( -// "*", -// ), -// String( -// "", -// ), -// String( -// "", -// ), -// String( -// "audron", -// ), -// ], -// ), -// "loginTime": VariantList( -// [ -// DateTime( -// OffsetDateTime { -// utc_datetime: PrimitiveDateTime { -// date: Date { -// year: 1970, -// ordinal: 1, -// }, -// time: Time { -// hour: 0, -// minute: 0, -// second: 0, -// nanosecond: 0, -// }, -// }, -// offset: UtcOffset { -// seconds: 0, -// }, -// }, -// ), -// DateTime( -// OffsetDateTime { -// utc_datetime: PrimitiveDateTime { -// date: Date { -// year: 1970, -// ordinal: 1, -// }, -// time: Time { -// hour: 0, -// minute: 0, -// second: 0, -// nanosecond: 0, -// }, -// }, -// offset: UtcOffset { -// seconds: 0, -// }, -// }, -// ), -// DateTime( -// OffsetDateTime { -// utc_datetime: PrimitiveDateTime { -// date: Date { -// year: 1970, -// ordinal: 1, -// }, -// time: Time { -// hour: 0, -// minute: 0, -// second: 0, -// nanosecond: 0, -// }, -// }, -// offset: UtcOffset { -// seconds: 0, -// }, -// }, -// ), -// DateTime( -// OffsetDateTime { -// utc_datetime: PrimitiveDateTime { -// date: Date { -// year: 1970, -// ordinal: 1, -// }, -// time: Time { -// hour: 0, -// minute: 0, -// second: 0, -// nanosecond: 0, -// }, -// }, -// offset: UtcOffset { -// seconds: 0, -// }, -// }, -// ), -// DateTime( -// OffsetDateTime { -// utc_datetime: PrimitiveDateTime { -// date: Date { -// year: 1970, -// ordinal: 1, -// }, -// time: Time { -// hour: 0, -// minute: 0, -// second: 0, -// nanosecond: 0, -// }, -// }, -// offset: UtcOffset { -// seconds: 0, -// }, -// }, -// ), -// ], -// ), -// "userModes": VariantList( -// [ -// String( -// "", -// ), -// String( -// "Iwxi", -// ), -// String( -// "", -// ), -// String( -// "", -// ), -// String( -// "", -// ), -// ], -// ), -// "host": VariantList( -// [ -// String( -// "services", -// ), -// String( -// "irc-tar.hr0.2d7ge7.IP", -// ), -// String( -// "services", -// ), -// String( -// "", -// ), -// String( -// "user/audron", -// ), -// ], -// ), -// "whoisServiceReply": VariantList( -// [ -// String( -// "", -// ), -// String( -// "", -// ), -// String( -// "", -// ), -// String( -// "", -// ), -// String( -// "", -// ), -// ], -// ), -// "channels": VariantList( -// [ -// StringList( -// [], -// ), -// StringList( -// [ -// "#audron-test", -// ], -// ), -// StringList( -// [], -// ), -// StringList( -// [], -// ), -// StringList( -// [ -// "#audron-test", -// ], -// ), -// ], -// ), -// "realName": VariantList( -// [ -// String( -// "", -// ), -// String( -// "Quassel IRC User", -// ), -// String( -// "", -// ), -// String( -// "", -// ), -// String( -// "Max Audron <audron@cocaine.farm>", -// ), -// ], -// ), -// "nick": VariantList( -// [ -// String( -// "NickServ", -// ), -// String( -// "audron_", -// ), -// String( -// "Global", -// ), -// String( -// "irc.snoonet.org", -// ), -// String( -// "audron", -// ), -// ], -// ), -// "idleTime": VariantList( -// [ -// DateTime( -// OffsetDateTime { -// utc_datetime: PrimitiveDateTime { -// date: Date { -// year: 1970, -// ordinal: 1, -// }, -// time: Time { -// hour: 0, -// minute: 0, -// second: 0, -// nanosecond: 0, -// }, -// }, -// offset: UtcOffset { -// seconds: 0, -// }, -// }, -// ), -// DateTime( -// OffsetDateTime { -// utc_datetime: PrimitiveDateTime { -// date: Date { -// year: 1970, -// ordinal: 1, -// }, -// time: Time { -// hour: 0, -// minute: 0, -// second: 0, -// nanosecond: 0, -// }, -// }, -// offset: UtcOffset { -// seconds: 0, -// }, -// }, -// ), -// DateTime( -// OffsetDateTime { -// utc_datetime: PrimitiveDateTime { -// date: Date { -// year: 1970, -// ordinal: 1, -// }, -// time: Time { -// hour: 0, -// minute: 0, -// second: 0, -// nanosecond: 0, -// }, -// }, -// offset: UtcOffset { -// seconds: 0, -// }, -// }, -// ), -// DateTime( -// OffsetDateTime { -// utc_datetime: PrimitiveDateTime { -// date: Date { -// year: 1970, -// ordinal: 1, -// }, -// time: Time { -// hour: 0, -// minute: 0, -// second: 0, -// nanosecond: 0, -// }, -// }, -// offset: UtcOffset { -// seconds: 0, -// }, -// }, -// ), -// DateTime( -// OffsetDateTime { -// utc_datetime: PrimitiveDateTime { -// date: Date { -// year: 1970, -// ordinal: 1, -// }, -// time: Time { -// hour: 0, -// minute: 0, -// second: 0, -// nanosecond: 0, -// }, -// }, -// offset: UtcOffset { -// seconds: 0, -// }, -// }, -// ), -// ], -// ), -// "encrypted": VariantList( -// [ -// bool( -// false, -// ), -// bool( -// false, -// ), -// bool( -// false, -// ), -// bool( -// false, -// ), -// bool( -// false, -// ), -// ], -// ), -// "awayMessage": VariantList( -// [ -// String( -// "", -// ), -// String( -// "", -// ), -// String( -// "", -// ), -// String( -// "", -// ), -// String( -// "", -// ), -// ], -// ), -// "user": VariantList( -// [ -// String( -// "NickServ", -// ), -// String( -// "quassel", -// ), -// String( -// "Global", -// ), -// String( -// "", -// ), -// String( -// "audron", -// ), -// ], -// ), -// "server": VariantList( -// [ -// String( -// "", -// ), -// String( -// "irc.snoonet.org", -// ), -// String( -// "", -// ), -// String( -// "", -// ), -// String( -// "irc.snoonet.org", -// ), -// ], -// ), -// }, -// ), -// "Channels": VariantMap( -// { -// "encrypted": VariantList( -// [ -// bool( -// false, -// ), -// ], -// ), -// "topic": VariantList( -// [ -// String( -// "", -// ), -// ], -// ), -// "password": VariantList( -// [ -// String( -// "", -// ), -// ], -// ), -// "ChanModes": VariantList( -// [ -// VariantMap( -// { -// "B": VariantMap( -// {}, -// ), -// "D": String( -// "tCnT", -// ), -// "C": VariantMap( -// { -// "j": String( -// "5:1", -// ), -// "x": String( -// "10:5", -// ), -// "f": String( -// "30:5", -// ), -// "F": String( -// "5:60", -// ), -// }, -// ), -// "A": VariantMap( -// {}, -// ), -// }, -// ), -// ], -// ), -// "UserModes": VariantList( -// [ -// VariantMap( -// { -// "audron": String( -// "o", -// ), -// "audron_": String( -// "", -// ), -// }, -// ), -// ], -// ), -// "name": VariantList( -// [ -// String( -// "#audron-test", -// ), -// ], -// ), -// }, -// ), -// }, -// ), -// ByteArray( -// "ServerList", -// ), -// VariantList( -// [ -// VariantMap( -// { -// "ProxyHost": String( -// "localhost", -// ), -// "sslVerify": bool( -// true, -// ), -// "UseSSL": bool( -// true, -// ), -// "Port": u32( -// 6697, -// ), -// "Password": String( -// "", -// ), -// "ProxyType": i32( -// 1, -// ), -// "sslVersion": i32( -// 0, -// ), -// "ProxyUser": String( -// "", -// ), -// "ProxyPass": String( -// "", -// ), -// "Host": String( -// "irc.snoonet.org", -// ), -// "ProxyPort": u32( -// 8080, -// ), -// "UseProxy": bool( -// false, -// ), -// }, -// ), -// ], -// ), -// ByteArray( -// "Supports", -// ), -// VariantMap( -// { -// "NAMESX": String( -// "", -// ), -// "MAXTARGETS": String( -// "20", -// ), -// "NICKLEN": String( -// "27", -// ), -// "SILENCE": String( -// "32", -// ), -// "PREFIX": String( -// "(Yohv)!@%+", -// ), -// "TOPICLEN": String( -// "307", -// ), -// "UHNAMES": String( -// "", -// ), -// "STATUSMSG": String( -// "!@%+", -// ), -// "SECURELIST": String( -// "60", -// ), -// "ACCEPT": String( -// "16", -// ), -// "CHANNELLEN": String( -// "64", -// ), -// "KEYLEN": String( -// "32", -// ), -// "EXTBAN": String( -// ",ABCNOQRSTUacjmprsz", -// ), -// "CHANMODES": String( -// "IXZbegw,k,FHJLWdfjlx,ABCDKMNOPQRSTcimnprstuz", -// ), -// "KICKLEN": String( -// "255", -// ), -// "ESILENCE": String( -// "CcdiNnPpTtx", -// ), -// "HOSTLEN": String( -// "64", -// ), -// "CHANLIMIT": String( -// "#:200", -// ), -// "USERMODES": String( -// ",,s,BHILRSTWcdghikorwx", -// ), -// "CLIENTTAGDENY": String( -// "*", -// ), -// "CHANTYPES": String( -// "#", -// ), -// "NETWORK": String( -// "Snoonet", -// ), -// "INVEX": String( -// "I", -// ), -// "ELIST": String( -// "CMNTU", -// ), -// "CALLERID": String( -// "g", -// ), -// "BOT": String( -// "B", -// ), -// "NAMELEN": String( -// "128", -// ), -// "USERIP": String( -// "", -// ), -// "MODES": String( -// "50", -// ), -// "WATCH": String( -// "30", -// ), -// "MAXLIST": String( -// "I:1024,X:1024,b:1024,e:1024,g:1024,w:1024", -// ), -// "USERLEN": String( -// "11", -// ), -// "CASEMAPPING": String( -// "rfc1459", -// ), -// "REMOVE": String( -// "", -// ), -// "LINELEN": String( -// "512", -// ), -// "AWAYLEN": String( -// "200", -// ), -// "EXCEPTS": String( -// "e", -// ), -// "WHOX": String( -// "", -// ), -// "SAFELIST": String( -// "", -// ), -// }, -// ), -// ByteArray( -// "autoIdentifyPassword", -// ), -// String( -// "", -// ), -// ByteArray( -// "autoIdentifyService", -// ), -// String( -// "NickServ", -// ), -// ByteArray( -// "autoReconnectInterval", -// ), -// u32( -// 60, -// ), -// ByteArray( -// "autoReconnectRetries", -// ), -// u16( -// 20, -// ), -// ByteArray( -// "codecForDecoding", -// ), -// ByteArray( -// "", -// ), -// ByteArray( -// "codecForEncoding", -// ), -// ByteArray( -// "", -// ), -// ByteArray( -// "codecForServer", -// ), -// ByteArray( -// "", -// ), -// ByteArray( -// "connectionState", -// ), -// i32( -// 3, -// ), -// ByteArray( -// "currentServer", -// ), -// String( -// "travincal.snoonet.org", -// ), -// ByteArray( -// "identityId", -// ), -// i32( -// 1, -// ), -// ByteArray( -// "isConnected", -// ), -// bool( -// true, -// ), -// ByteArray( -// "latency", -// ), -// i32( -// 13, -// ), -// ByteArray( -// "msgRateBurstSize", -// ), -// u32( -// 5, -// ), -// ByteArray( -// "msgRateMessageDelay", -// ), -// u32( -// 2200, -// ), -// ByteArray( -// "myNick", -// ), -// String( -// "audron_", -// ), -// ByteArray( -// "networkName", -// ), -// String( -// "snoonet", -// ), -// ByteArray( -// "perform", -// ), -// StringList( -// [ -// "", -// ], -// ), -// ByteArray( -// "rejoinChannels", -// ), -// bool( -// true, -// ), -// ByteArray( -// "saslAccount", -// ), -// String( -// "", -// ), -// ByteArray( -// "saslPassword", -// ), -// String( -// "", -// ), -// ByteArray( -// "unlimitedMessageRate", -// ), -// bool( -// false, -// ), -// ByteArray( -// "unlimitedReconnectRetries", -// ), -// bool( -// false, -// ), -// ByteArray( -// "useAutoIdentify", -// ), -// bool( -// false, -// ), -// ByteArray( -// "useAutoReconnect", -// ), -// bool( -// true, -// ), -// ByteArray( -// "useCustomMessageRate", -// ), -// bool( -// false, -// ), -// ByteArray( -// "useRandomServer", -// ), -// bool( -// false, -// ), -// ByteArray( -// "useSasl", -// ), -// bool( -// false, -// ), -// ], -// }, diff --git a/src/message/signalproxy/translation/mod.rs b/src/message/signalproxy/translation/mod.rs deleted file mode 100644 index a55d6f3..0000000 --- a/src/message/signalproxy/translation/mod.rs +++ /dev/null @@ -1,112 +0,0 @@ -/** -Quassel has 3 main ways to represent an object over the Network: - -# VariantList -The struct is serialized to a Vector of Variants. This is mostly used in the InitData messages. -First the field name as a ByteArray (UTF-8 String), followed by the field value in it's own Type's variant. -The order in which the fields are transmitted cannot be assumed. - -Example: -```ignore -NetworkConfig { - ping_timeout_enabled: true, - ping_interval: 0, -} -``` -to -```ignore -VariantList([ - ByteArray( - "pingTimeoutEnabled", - ), - bool( - true, - ), - ByteArray( - "pingInterval", - ), - i32( - 30, - ), -]) -``` - - -# VariantMap -The struct is represented as a `VariantMap`. The keys and values of -the struct are serialized to a corresponding `HashMap<String, Variant>`. - -Example: -```ignore -NetworkConfig { - ping_timeout_enabled: false, - ping_interval: 0, -} -``` -to -```ignore -VariantMap({ - "pingTimeoutEnabled": bool(false) - "pingInterval": i32(0) -}) -``` - -## Structure of Arrays - -For Objects that are transmitted as multiple at once the VariantMap -representation is augemented and instead of transmitting multiple `VariantMaps`, -each field is a `VariantList` of Items. - -Example: -```ignore -vec![ - NetworkConfig { - ping_timeout_enabled: false, - ping_interval: 0, - }, - NetworkConfig { - ping_timeout_enabled: true, - ping_interval: 1, - }, -] -``` -to -```ignore -VariantMap({ - "pingTimeoutEnabled": VariantList([ - bool(false), - bool(true), - ]), - "pingInterval": VariantList([ - i32(0), - i32(1), - ]) -}) -``` -**/ -use crate::primitive::{Variant, VariantList}; - -#[deprecated(since="0.1.0", note="please use NetworkMap and NetworkList implementations")] -pub trait Network { - type Item; - - fn to_network(&self) -> Self::Item; - fn from_network(input: &mut Self::Item) -> Self; -} - -pub trait NetworkMap -where - // TODO correct this error type - Self::Item: TryFrom<Variant, Error = String>, - Self::Item: Into<Variant>, -{ - type Item; - - fn to_network_map(&self) -> Self::Item; - fn from_network_map(input: &mut Self::Item) -> Self; -} - -pub trait NetworkList { - fn to_network_list(&self) -> VariantList; - fn from_network_list(input: &mut VariantList) -> Self; -} diff --git a/src/primitive/variant.rs b/src/primitive/variant.rs index d39e0bf..903f77c 100644 --- a/src/primitive/variant.rs +++ b/src/primitive/variant.rs @@ -88,7 +88,7 @@ impl From<&str> for Variant { } /// Implements the Network trait genericly for everything that -/// can be a VariantList / Vec<T> +/// can be a [VariantList] impl<T, S> crate::message::NetworkList for HashMap<T, S> where T: std::convert::TryFrom<Variant> + Into<Variant> + Clone + std::hash::Hash + std::cmp::Eq, diff --git a/src/serialize.rs b/src/serialize.rs index 925b668..dffd0c3 100644 --- a/src/serialize.rs +++ b/src/serialize.rs @@ -1,3 +1,51 @@ +//! Traits for Serializing and Deserializing types to their byte representations +//! +//! example for a simple type would look like this with the `TYPE` usually fetched from [libquassel::primitive#constants] +//! +//! ```rust +//! use libquassel::{ProtocolError, serialize::*}; +//! +//! pub struct Example; +//! +//! impl Serialize for Example { +//! fn serialize(&self) -> Result<Vec<u8>, ProtocolError> { +//! // Serialize here +//! # todo!() +//! } +//! } +//! +//! impl Deserialize for Example { +//! fn parse(b: &[u8]) -> Result<(usize, Self), ProtocolError> { +//! // Deserialize here +//! # todo!() +//! } +//! } +//! +//! impl VariantType for Example { +//! // The QT Type identifier +//! const TYPE: u32 = 0x18; +//! } +//! ``` +//! +//! Some types are not serialized directly but are a [UserType]: +//! ```rust +//! use libquassel::{ProtocolError, serialize::*}; +//! +//! pub struct Example; +//! +//! impl Serialize for Example { +//! fn serialize(&self) -> Result<Vec<u8>, ProtocolError> { +//! // Serialize here +//! # todo!() +//! } +//! } +//! +//! impl UserType for Example { +//! const NAME: &str = "Example"; +//! } +//! ``` +//! [UserType]: libquassel::serialize::UserType + use crate::{ error::ProtocolError, primitive::{self, Variant}, @@ -64,13 +112,11 @@ pub trait VariantType { const TYPE: u32; } +/// Serialize a Type directly to it's Variant. +/// +/// Has a default implementation and is automaticly implemented for all types that +/// have a [VariantType] set and [Serialize] implemented. pub trait SerializeVariant: VariantType + Serialize { - /// Default implementation that passes the serialization through to [SerializeVariantInner]. - /// [SerializeVariantInner] is automaticly implemented for all types that implement [Serialize] - /// - /// ```rust ignore - /// self.serialize_variant_inner(Self::TYPE) - /// ``` fn serialize_variant(&self) -> Result<Vec<u8>, ProtocolError> { let mut res: Vec<u8> = Vec::new(); @@ -102,6 +148,14 @@ pub trait DeserializeUTF8 { Self: std::marker::Sized; } +/// Deserialize a Type for use in the Variant parsing. In opposite to [SerializeVariant] this does not deal +/// with the variant type itself as we have to match onto it genericly before passing it on to per Type +/// functions. +/// +/// Still using this gives us automatic implementations and more code reuse +/// +/// Has a default implementation and is automaticly implemented for all types that +/// have a [VariantType] set and [Deserialize] implemented. pub trait DeserializeVariant: VariantType + Deserialize where Variant: From<Self>, diff --git a/src/session/mod.rs b/src/session.rs index 31842b1..d4a788b 100644 --- a/src/session/mod.rs +++ b/src/session.rs @@ -1,3 +1,8 @@ +//! Generic Session handling implementation +//! +//! This module provides a relativly generic example implementation for handling the whole quassel session in +//! an application. This won't be usable in all cases but e.g. imediate mode GUIs can use it directly. + use std::collections::HashMap; #[cfg(feature = "client")] @@ -15,8 +20,7 @@ use crate::{ primitive::NetworkId, }; -// TODO implement nested types init and sync like BufferViewConfig in BufferViewManager - +/// Central struct that hold all our state #[derive(Default, Debug)] pub struct Session { pub alias_manager: AliasManager, @@ -33,6 +37,9 @@ pub struct Session { } /// The Session Trait is the main point of entry and implements the basic logic +/// +/// Default implementations to handle sync and init of data structures is provided and you only have to +/// provide the getter functions. pub trait SessionManager { fn alias_manager(&mut self) -> &mut AliasManager; fn buffer_syncer(&mut self) -> &mut BufferSyncer; @@ -48,6 +55,7 @@ pub trait SessionManager { fn network(&mut self, id: i32) -> Option<&mut Network>; fn network_config(&mut self) -> &mut NetworkConfig; + /// Handles an incoming [SyncMessage] and passes it on to the correct destination Object. fn sync(&mut self, msg: SyncMessage) where Self: Sized, @@ -158,6 +166,8 @@ pub trait SessionManager { *self.identities() = data.identities; } + /// Handles an [InitData] messages and initializes the SessionManagers Objects. + /// TODO handle automatic sending of InitRequest for whatever objects will need that. fn init(&mut self, data: InitData) { match data.init_data { Types::AliasManager(data) => self.alias_manager().init(data), diff --git a/src/util.rs b/src/util.rs index 98e3521..eb5a595 100644 --- a/src/util.rs +++ b/src/util.rs @@ -38,6 +38,17 @@ pub fn insert_bytes(pos: usize, buf: &mut Vec<u8>, input: &mut [u8]) { } } +/// Easily create HashMaps for tests +/// +/// ```rust +/// use libquassel::{map, s}; +/// use libquassel::primitive::{Variant, VariantMap}; +/// +/// let example: VariantMap = map! { +/// s!("id") => Variant::VariantList(vec![Variant::i32(1)]), +/// s!("name") => Variant::StringList(vec![s!("testrule")]), +///}; +/// ``` #[macro_export] macro_rules! map { // map-like @@ -50,6 +61,7 @@ macro_rules! map { }; } +/// Shorthand to make an owned string: `s!("example text")` #[macro_export] macro_rules! s { ($values:expr) => { @@ -57,6 +69,7 @@ macro_rules! s { }; } +/// Remove the first entry in a SyncMessage #[macro_export] macro_rules! get_param { ( $msg:expr ) => { |
