From 6f9c0d0f2906d05e27f9f11af6cefdf006c2cf4b Mon Sep 17 00:00:00 2001 From: Max Audron Date: Wed, 26 Feb 2025 17:53:08 +0100 Subject: refactor variant serialization code Factored out a lot of the serialization of variants into trait's that have auto impl so code duplication is much reduced --- src/serialize.rs | 88 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 src/serialize.rs (limited to 'src/serialize.rs') diff --git a/src/serialize.rs b/src/serialize.rs new file mode 100644 index 0000000..52fc2fe --- /dev/null +++ b/src/serialize.rs @@ -0,0 +1,88 @@ +use crate::{error::ProtocolError, primitive}; + +/// Serialization of types and structs to the quassel byteprotocol +pub trait Serialize { + fn serialize(&self) -> Result, ProtocolError>; +} + +/// Serialization of UTF-8 based Strings to the quassel byteprotocol +pub trait SerializeUTF8 { + fn serialize_utf8(&self) -> Result, ProtocolError>; +} + +/// Sets the usertype name to be used in serialization and deserialization of the types variants. +/// Automaticly implements the [SerializeVariant] trait. +/// +/// Example [Serialize] impl for a `struct NewType(T: Serialize)`: +/// ```rust +/// use libquassel::serialize::{Serialize, SerializeUTF8, UserType}; +/// +/// struct NewType(i64); +/// impl Serialize for NewType { +/// fn serialize(&self) -> Result, libquassel::ProtocolError> { +/// let mut res = Vec::new(); +/// +/// res.append(&mut Self::NAME.serialize_utf8()?); +/// res.extend(self.0.serialize()?); +/// +/// Ok(res) +/// } +/// } +/// +/// impl UserType for NewType { +/// const NAME: &str = "NewType"; +/// } +/// ``` +pub trait UserType { + const NAME: &str; +} + +/// Provides a easy default implementation for serializing a type to it's [Variant] given it's QT type id. +/// +/// If the type is a UserType implement only [UserType], SerializeVariant is implemented automaticly. +/// +/// ```rust ignore +/// impl SerializeVariant for VariantList { +/// const TYPE: u32 = primitive::QVARIANTLIST; +/// } +/// ``` +pub trait SerializeVariant { + /// QT Type as defined by the [Primitive Constants] + /// + /// [Primitive Constants]: primitive#constants + const TYPE: u32; + + /// 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, ProtocolError> + where + Self: SerializeVariantInner, + { + self.serialize_variant_inner(Self::TYPE) + } +} + +/// Implemented automaticly for all types that implement [Serialize] refer to [SerializeVariant] +pub trait SerializeVariantInner { + fn serialize_variant_inner(&self, t: u32) -> Result, ProtocolError>; +} + +impl SerializeVariantInner for T { + fn serialize_variant_inner(&self, t: u32) -> Result, ProtocolError> { + let mut res: Vec = Vec::new(); + + res.extend(t.to_be_bytes().iter()); + res.extend(0x00u8.to_be_bytes().iter()); + res.extend(self.serialize()?); + + Ok(res) + } +} + +impl SerializeVariant for T { + const TYPE: u32 = primitive::USERTYPE; +} -- cgit v1.2.3