From 6afb148068790d7416b9b2af32ff3d2d57564d24 Mon Sep 17 00:00:00 2001 From: Avril Date: Tue, 3 Aug 2021 19:45:24 +0100 Subject: [PATCH] Added `UntypedSerializedMessage`: A `SerializedMessage` whos original value type has been erased. A `SerializedMessage` can be converted into this with `.into_untyped()`, and can be converted back with the `unsafe` function `into_typed()`. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Untyped serialized mmessages cannot be deserialized, they must first be given a type with `into_typed()`. This operation is unsafe as it may cause a potential type confusion if the message"s original `V` is different from the newly specified `V`. Fortune for rsh's current commit: Half curse − 半凶 --- src/message.rs | 29 +++++++++++++++++++---------- src/message/value.rs | 37 +++++++++++++++++++++++++++++++++++-- 2 files changed, 54 insertions(+), 12 deletions(-) diff --git a/src/message.rs b/src/message.rs index 3be60c2..80a281e 100644 --- a/src/message.rs +++ b/src/message.rs @@ -27,6 +27,9 @@ pub use builder::*; pub mod value; pub use value::MessageValue; +/// A `SerializedMessage` whos type has been erased. +pub type UntypedSerializedMessage = SerializedMessage; + /// Size of encrypted AES key pub const RSA_BLOCK_SIZE: usize = 512; @@ -59,7 +62,7 @@ impl Message macro_rules! accessor { ($name:ident, $fn_name:ident, $type:ty $(; $comment:literal)?) => { $(#[doc = $comment])? - #[inline] pub fn $fn_name(&self) -> &$type + #[inline] pub fn $fn_name(&self) -> &$type { &self.0.$name } @@ -86,6 +89,8 @@ struct SerHeader timestamp: u64, /// `id` of message this one is responding to, if needed. responds_to: Option, + //TODO: Add `flags` bitflags + //TODO: Add `kind` enum } /// A reference to a message's header. @@ -104,7 +109,7 @@ impl AsRef for Message /// /// Messages of this type are not yet validated, and may be invalid/corrupt. The validation happens when converting back to a `Message` (of the same `V`.) #[derive(Debug, Clone, PartialEq, Eq)] -pub struct SerializedMessage +pub struct SerializedMessage { header: SerHeader, /// cbor serialised `V`. @@ -231,7 +236,7 @@ impl Message } } -impl SerializedMessage +impl SerializedMessage { /// Get the message header #[inline(always)] pub fn header(&self) -> MessageHeader<'_, V> @@ -315,6 +320,16 @@ impl SerializedMessage Ok(w) } + /// Consume into `Vec`. + pub fn into_bytes(self) -> Vec + { + let mut v = Vec::with_capacity(self.data.len()<<1); + self.into_writer(&mut v).expect("Failed to write to in-memory buffer"); + v + } +} +impl SerializedMessage +{ /// Create from a reader. /// /// The message may be in an invalid state. It is only possible to extract the value after validating it into a `Message`. @@ -397,13 +412,7 @@ impl SerializedMessage _phantom: PhantomData, }) } - /// Consume into `Vec`. - pub fn into_bytes(self) -> Vec - { - let mut v = Vec::with_capacity(self.data.len()<<1); - self.into_writer(&mut v).expect("Failed to write to in-memory buffer"); - v - } + /// Create from bytes #[inline] pub fn from_bytes(bytes: impl AsRef<[u8]>) -> eyre::Result { diff --git a/src/message/value.rs b/src/message/value.rs index 33d3632..5a5b4cb 100644 --- a/src/message/value.rs +++ b/src/message/value.rs @@ -1,5 +1,6 @@ //! Message values use super::*; +use std::mem; use serde::{Serialize, Deserialize}; /// A value that can be used for messages. @@ -26,8 +27,40 @@ pub struct MessageValueAny(Box); //where T: Serialize + for<'de> Deserialize<'de> + Any{} */ -/// A type-unsafe `MessageValue` that can be used to transmute `SerializedMessage` instances. +/// A type-unsafe value that can be used to transmute `SerializedMessage` instances. /// /// This operation is unsafe and can result in deserializing the `SerializedMessage` failing, or even worse, a type confusion. -#[derive(Debug, Serialize, Deserialize)] +/// +/// This type does not implement `MessageValue`, as serialized messages of this value cannot be created (from `Message::serialize()`), nor deserialized. They must first be converted into a typed `SerializedMessage` with `UntypedSerializedMessage::into_typed()`. +/// +/// This is an empty (!) type. +#[derive(Debug)] pub enum UntypedMessageValue{} + +impl SerializedMessage +{ + /// Transmute into a specifically typed `SerializedMessage` + /// + /// # Safety + /// If `V` is not the original type of this message (before being untyped), then deserialisation will likely fail, or, much worse, cause a *type consufion* bug, where the object of type `V` is successfully deserialized with an invalid value from an unknown type. + /// Take special care when using this. + pub const unsafe fn into_typed(self) -> SerializedMessage + { + mem::transmute(self) + } +} + +impl SerializedMessage +{ + /// Consume this value into an untyped `SerializedMessage`. + /// + /// # Safety + /// This operation is safe, however, doing anything at all with the resulting `SerializedMessage` is not. + /// It must be unsafly converted into a types message before it can be deserialized. + pub const fn into_untyped(self) -> SerializedMessage + { + unsafe { + mem::transmute(self) + } + } +}