aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorMax Audron <audron@cocaine.farm>2025-02-27 01:03:29 +0100
committerMax Audron <audron@cocaine.farm>2025-02-27 01:03:29 +0100
commite4338a9d9d0a76029bca376c2bcb499962575e87 (patch)
treea0c14be508381e3f5091d1872210edd612f57dde /src
parentimplement NetworkId UserType (diff)
extend docs and reorganize files
Diffstat (limited to 'src')
-rw-r--r--src/error.rs (renamed from src/error/mod.rs)0
-rw-r--r--src/lib.rs93
-rw-r--r--src/message/signalproxy/mod.rs2
-rw-r--r--src/message/signalproxy/translation.rs122
-rw-r--r--src/message/signalproxy/translation/aos_soa.rs1134
-rw-r--r--src/message/signalproxy/translation/mod.rs112
-rw-r--r--src/primitive/variant.rs2
-rw-r--r--src/serialize.rs66
-rw-r--r--src/session.rs (renamed from src/session/mod.rs)14
-rw-r--r--src/util.rs13
10 files changed, 301 insertions, 1257 deletions
diff --git a/src/error/mod.rs b/src/error.rs
index 7414062..7414062 100644
--- a/src/error/mod.rs
+++ b/src/error.rs
diff --git a/src/lib.rs b/src/lib.rs
index 59581ae..d3d7d03 100644
--- a/src/lib.rs
+++ b/src/lib.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 ) => {