From 0919e5dc35d8fcbb0dc05b598d29ea3c4fc2e19d Mon Sep 17 00:00:00 2001 From: Victor Lopez Date: Mon, 11 Jul 2022 02:09:29 +0200 Subject: [PATCH] Add `msgpacker-derive` --- Cargo.toml | 3 +- README.md | 41 ++ msgpacker-derive/Cargo.toml | 18 + msgpacker-derive/LICENSE-APACHE | 1 + msgpacker-derive/LICENSE-MIT | 1 + msgpacker-derive/README.md | 1 + msgpacker-derive/src/lib.rs | 78 +++ msgpacker/Cargo.toml | 7 +- msgpacker/src/lib.rs | 5 + msgpacker/src/message.rs | 132 ---- msgpacker/src/message_ref.rs | 120 ---- msgpacker/src/packer.rs | 141 +++++ msgpacker/src/packer/impls.rs | 1033 +++++++++++++++++++++++++++++++ 13 files changed, 1327 insertions(+), 254 deletions(-) create mode 100644 msgpacker-derive/Cargo.toml create mode 120000 msgpacker-derive/LICENSE-APACHE create mode 120000 msgpacker-derive/LICENSE-MIT create mode 120000 msgpacker-derive/README.md create mode 100644 msgpacker-derive/src/lib.rs create mode 100644 msgpacker/src/packer.rs create mode 100644 msgpacker/src/packer/impls.rs diff --git a/Cargo.toml b/Cargo.toml index a8e9621..0a4df66 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,8 @@ [workspace] members = [ "msgpacker", - "msgpacker-bench" + "msgpacker-bench", + "msgpacker-derive" ] [profile.bench] diff --git a/README.md b/README.md index aa7899e..f952a4d 100644 --- a/README.md +++ b/README.md @@ -13,8 +13,49 @@ We have two main structures available: * Message - Owned parsed values * MessageRef - Message parsed by reference and bound to the lifetime of the readers source +For convenience, a derive macro is available to implement `Packable` and `Unpackable` for the types. These implementations will allow the types to be sent and received from `MessagePacker` and `MessageUnpacker` implementations, such as `CursorPacker`. + ## Example +```rust +use msgpacker::prelude::*; + +#[derive(MsgPacker, Debug, Clone, PartialEq, Eq)] +pub struct Foo { + val: u64, + text: String, + flag: bool, + bar: Bar, +} + +#[derive(MsgPacker, Debug, Clone, PartialEq, Eq)] +pub struct Bar { + arr: [u8; 32], +} + +let bar = Bar { arr: [0xff; 32] }; +let foo = Foo { + val: 15, + text: String::from("Hello, world!"), + flag: true, + bar, +}; + +// Create a new bytes buffer +let mut buffer: Vec = vec![]; + +// Pack the message into the buffer +CursorPacker::new(&mut buffer).pack(foo.clone()).expect("failed to pack `Foo`"); + +// Unpack the message from the buffer +let foo_p = CursorPacker::new(&buffer).unpack::().expect("failed to unpack `Foo`"); + +// Assert the unpacked message is exactly the same as the original +assert_eq!(foo, foo_p); +``` + +## Example of manual implementation + ```rust use msgpacker::prelude::*; use std::io::{Cursor, Seek}; diff --git a/msgpacker-derive/Cargo.toml b/msgpacker-derive/Cargo.toml new file mode 100644 index 0000000..6d0586b --- /dev/null +++ b/msgpacker-derive/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "msgpacker-derive" +version = "0.1.0" +authors = ["Victor Lopez "] +categories = ["compression", "encoding", "parser-implementations"] +edition = "2021" +keywords = ["messagepack", "msgpack"] +license = "MIT/Apache-2.0" +readme = "README.md" +repository = "https://github.com/codx-dev/msgpacker" +description = "Derive macros for the MessagePack protocol implementation for Rust." + +[lib] +proc-macro = true + +[dependencies] +quote = "1.0" +syn = { version = "1.0", features = ["full"] } diff --git a/msgpacker-derive/LICENSE-APACHE b/msgpacker-derive/LICENSE-APACHE new file mode 120000 index 0000000..965b606 --- /dev/null +++ b/msgpacker-derive/LICENSE-APACHE @@ -0,0 +1 @@ +../LICENSE-APACHE \ No newline at end of file diff --git a/msgpacker-derive/LICENSE-MIT b/msgpacker-derive/LICENSE-MIT new file mode 120000 index 0000000..76219eb --- /dev/null +++ b/msgpacker-derive/LICENSE-MIT @@ -0,0 +1 @@ +../LICENSE-MIT \ No newline at end of file diff --git a/msgpacker-derive/README.md b/msgpacker-derive/README.md new file mode 120000 index 0000000..32d46ee --- /dev/null +++ b/msgpacker-derive/README.md @@ -0,0 +1 @@ +../README.md \ No newline at end of file diff --git a/msgpacker-derive/src/lib.rs b/msgpacker-derive/src/lib.rs new file mode 100644 index 0000000..336f06e --- /dev/null +++ b/msgpacker-derive/src/lib.rs @@ -0,0 +1,78 @@ +#![crate_type = "proc-macro"] +extern crate proc_macro; + +use proc_macro::TokenStream; +use quote::quote; +use syn::punctuated::Punctuated; +use syn::{ + parse_macro_input, parse_quote, Block, Data, DeriveInput, FieldValue, Fields, Member, Token, +}; + +#[proc_macro_derive(MsgPacker)] +pub fn msg_packer(input: TokenStream) -> TokenStream { + let input = parse_macro_input!(input as DeriveInput); + + let name = input.ident; + let data = input.data; + + let mut values: Punctuated = Punctuated::new(); + let block: Block = match data { + Data::Struct(syn::DataStruct { + struct_token: _, + fields: Fields::Named(f), + semi_token: _, + }) => f + .named + .into_pairs() + .map(|p| p.into_value()) + .fold(syn::parse_str("{}").unwrap(), |mut block, field| { + let ident = field.ident.as_ref().cloned().unwrap(); + let ty = field.ty; + + block.stmts.push(parse_quote! { + n += <#ty as msgpacker::prelude::Packable>::pack(&self.#ident, packer.by_ref())?; + }); + + let fv = FieldValue { + attrs: vec![], + member: Member::Named(ident.clone()), + colon_token: Some(::default()), + expr: parse_quote! { + <#ty as msgpacker::prelude::Unpackable>::unpack(unpacker.by_ref())? + }, + }; + values.push(fv); + + block + }), + _ => todo!(), + }; + + let expanded = quote! { + impl msgpacker::prelude::Packable for #name { + fn pack(&self, mut packer: W) -> std::io::Result + where + W: std::io::Write + { + let mut n = 0; + + #block + + Ok(n) + } + } + + impl msgpacker::prelude::Unpackable for #name { + fn unpack(mut unpacker: R) -> std::io::Result + where + R: std::io::BufRead, + { + Ok(Self { + #values + }) + } + } + }; + + TokenStream::from(expanded) +} diff --git a/msgpacker/Cargo.toml b/msgpacker/Cargo.toml index 3e63e4e..70bc983 100644 --- a/msgpacker/Cargo.toml +++ b/msgpacker/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "msgpacker" -version = "0.1.7" +version = "0.2.0" authors = ["Victor Lopez "] categories = ["compression", "encoding", "parser-implementations"] edition = "2021" @@ -11,3 +11,8 @@ repository = "https://github.com/codx-dev/msgpacker" description = "MessagePack protocol implementation for Rust." [dependencies] +msgpacker-derive = { version = "0.1", optional = true } + +[features] +default = ["derive"] +derive = ["msgpacker-derive"] diff --git a/msgpacker/src/lib.rs b/msgpacker/src/lib.rs index 018b5a2..ef80e82 100644 --- a/msgpacker/src/lib.rs +++ b/msgpacker/src/lib.rs @@ -9,6 +9,7 @@ mod integer; mod map; mod message; mod message_ref; +mod packer; pub use message::Message; pub use message_ref::MessageRef; @@ -26,5 +27,9 @@ pub mod types { pub mod prelude { pub use crate::message::Message; pub use crate::message_ref::MessageRef; + pub use crate::packer::{CursorPacker, MessagePacker, MessageUnpacker, Packable, Unpackable}; pub use crate::types::*; + + #[cfg(feature = "derive")] + pub use msgpacker_derive::MsgPacker; } diff --git a/msgpacker/src/message.rs b/msgpacker/src/message.rs index 5bc67f0..01a1dd9 100644 --- a/msgpacker/src/message.rs +++ b/msgpacker/src/message.rs @@ -763,138 +763,6 @@ impl Message { } } -impl From for Message { - fn from(i: Integer) -> Self { - Self::Integer(i) - } -} - -impl From for Message { - fn from(i: u8) -> Self { - Self::Integer(Integer::unsigned(i)) - } -} - -impl From for Message { - fn from(i: u16) -> Self { - Self::Integer(Integer::unsigned(i)) - } -} - -impl From for Message { - fn from(i: u32) -> Self { - Self::Integer(Integer::unsigned(i)) - } -} - -impl From for Message { - fn from(i: u64) -> Self { - Self::Integer(Integer::unsigned(i)) - } -} - -impl From for Message { - fn from(i: i8) -> Self { - Self::Integer(Integer::signed(i)) - } -} - -impl From for Message { - fn from(i: i16) -> Self { - Self::Integer(Integer::signed(i)) - } -} - -impl From for Message { - fn from(i: i32) -> Self { - Self::Integer(Integer::signed(i)) - } -} - -impl From for Message { - fn from(i: i64) -> Self { - Self::Integer(Integer::signed(i)) - } -} - -impl From for Message { - fn from(b: bool) -> Self { - Self::Boolean(b) - } -} - -impl From for Message { - fn from(f: Float) -> Self { - Self::Float(f) - } -} - -impl From for Message { - fn from(f: f32) -> Self { - Self::Float(Float::f32(f)) - } -} - -impl From for Message { - fn from(f: f64) -> Self { - Self::Float(Float::f64(f)) - } -} - -impl From<&str> for Message { - fn from(s: &str) -> Self { - Self::String(s.to_owned()) - } -} - -impl From for Message { - fn from(s: String) -> Self { - Self::String(s) - } -} - -impl From> for Message { - fn from(b: Vec) -> Self { - Self::Bin(b) - } -} - -impl FromIterator for Message { - fn from_iter>(iter: I) -> Self { - iter.into_iter().collect::>().into() - } -} - -impl From> for Message { - fn from(a: Vec) -> Self { - Self::Array(a) - } -} - -impl FromIterator for Message { - fn from_iter>(iter: I) -> Self { - iter.into_iter().collect::>().into() - } -} - -impl From> for Message { - fn from(m: Vec) -> Self { - Self::Map(m) - } -} - -impl FromIterator for Message { - fn from_iter>(iter: I) -> Self { - iter.into_iter().collect::>().into() - } -} - -impl From for Message { - fn from(e: Extension) -> Self { - Self::Extension(e) - } -} - impl> Index for Message { type Output = Message; diff --git a/msgpacker/src/message_ref.rs b/msgpacker/src/message_ref.rs index e87ac8e..8741063 100644 --- a/msgpacker/src/message_ref.rs +++ b/msgpacker/src/message_ref.rs @@ -767,126 +767,6 @@ impl<'a> MessageRef<'a> { } } -impl<'a> From for MessageRef<'a> { - fn from(i: Integer) -> Self { - Self::Integer(i) - } -} - -impl<'a> From for MessageRef<'a> { - fn from(i: u8) -> Self { - Self::Integer(Integer::unsigned(i)) - } -} - -impl<'a> From for MessageRef<'a> { - fn from(i: u16) -> Self { - Self::Integer(Integer::unsigned(i)) - } -} - -impl<'a> From for MessageRef<'a> { - fn from(i: u32) -> Self { - Self::Integer(Integer::unsigned(i)) - } -} - -impl<'a> From for MessageRef<'a> { - fn from(i: u64) -> Self { - Self::Integer(Integer::unsigned(i)) - } -} - -impl<'a> From for MessageRef<'a> { - fn from(i: i8) -> Self { - Self::Integer(Integer::signed(i)) - } -} - -impl<'a> From for MessageRef<'a> { - fn from(i: i16) -> Self { - Self::Integer(Integer::signed(i)) - } -} - -impl<'a> From for MessageRef<'a> { - fn from(i: i32) -> Self { - Self::Integer(Integer::signed(i)) - } -} - -impl<'a> From for MessageRef<'a> { - fn from(i: i64) -> Self { - Self::Integer(Integer::signed(i)) - } -} - -impl<'a> From for MessageRef<'a> { - fn from(b: bool) -> Self { - Self::Boolean(b) - } -} - -impl<'a> From for MessageRef<'a> { - fn from(f: Float) -> Self { - Self::Float(f) - } -} - -impl<'a> From for MessageRef<'a> { - fn from(f: f32) -> Self { - Self::Float(Float::f32(f)) - } -} - -impl<'a> From for MessageRef<'a> { - fn from(f: f64) -> Self { - Self::Float(Float::f64(f)) - } -} - -impl<'a> From<&'a str> for MessageRef<'a> { - fn from(s: &'a str) -> Self { - Self::String(s) - } -} - -impl<'a> From<&'a [u8]> for MessageRef<'a> { - fn from(b: &'a [u8]) -> Self { - Self::Bin(b) - } -} - -impl<'a> From>> for MessageRef<'a> { - fn from(a: Vec>) -> Self { - Self::Array(a) - } -} - -impl<'a> FromIterator> for MessageRef<'a> { - fn from_iter>>(iter: I) -> Self { - iter.into_iter().collect::>>().into() - } -} - -impl<'a> From>> for MessageRef<'a> { - fn from(m: Vec>) -> Self { - Self::Map(m) - } -} - -impl<'a> FromIterator> for MessageRef<'a> { - fn from_iter>>(iter: I) -> Self { - iter.into_iter().collect::>>().into() - } -} - -impl<'a> From> for MessageRef<'a> { - fn from(e: ExtensionRef<'a>) -> Self { - Self::Extension(e) - } -} - impl<'a, 'b, M: Into>> Index for MessageRef<'a> { type Output = MessageRef<'a>; diff --git a/msgpacker/src/packer.rs b/msgpacker/src/packer.rs new file mode 100644 index 0000000..6cb10aa --- /dev/null +++ b/msgpacker/src/packer.rs @@ -0,0 +1,141 @@ +use std::io::{self, BufRead, Cursor, Read, Seek, SeekFrom, Write}; + +mod impls; + +/// Define a type that can be packed into a writer. +pub trait Packable: Sized { + /// Pack the type into a writer + fn pack(&self, packer: W) -> io::Result + where + W: Write; +} + +/// Define a type that can be unpacked from a reader. +pub trait Unpackable: Sized { + /// Unpack the type from a reader + fn unpack(unpacker: R) -> io::Result + where + R: BufRead; +} + +/// A packer implementation that can receive messages +pub trait MessagePacker { + /// Pack the given argument into the internal writer + fn pack

(&mut self, package: P) -> io::Result + where + P: Packable; +} + +/// An unpacker implementation that can output messages +pub trait MessageUnpacker { + /// Unpack a message from the internal reader + fn unpack

(&mut self) -> io::Result

+ where + P: Unpackable; +} + +/// A packer/unpacker implementation with an underlying [`Cursor`] +#[derive(Debug, Default, Clone, PartialEq, Eq)] +pub struct CursorPacker { + cursor: Cursor, +} + +impl From> for CursorPacker { + fn from(cursor: Cursor) -> Self { + Self { cursor } + } +} + +impl From> for Cursor { + fn from(packer: CursorPacker) -> Self { + packer.cursor + } +} + +impl CursorPacker { + /// Create a new cursor packer with an underlying [`Cursor`] + pub fn new(buffer: B) -> Self { + Cursor::new(buffer).into() + } +} + +impl Read for CursorPacker +where + B: AsRef<[u8]>, +{ + fn read(&mut self, buf: &mut [u8]) -> io::Result { + self.cursor.read(buf) + } +} + +impl MessageUnpacker for CursorPacker +where + B: AsRef<[u8]>, +{ + fn unpack

(&mut self) -> io::Result

+ where + P: Unpackable, + { + P::unpack(self) + } +} + +macro_rules! impl_packer_writer { + ($b:ty) => { + impl Write for CursorPacker<$b> { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.cursor.write(buf) + } + + fn flush(&mut self) -> io::Result<()> { + self.cursor.flush() + } + } + + impl MessagePacker for CursorPacker<$b> { + fn pack

(&mut self, package: P) -> io::Result + where + P: Packable, + { + package.pack(self) + } + } + }; +} + +// Implemented this way due to architectural restrictions for cursor implementation in stdlib +impl_packer_writer!(Vec); +impl_packer_writer!(&mut [u8]); +impl_packer_writer!(&mut Vec); + +impl Write for CursorPacker<[u8; N]> { + fn write(&mut self, buf: &[u8]) -> io::Result { + self.cursor.write(buf) + } + + fn flush(&mut self) -> io::Result<()> { + self.cursor.flush() + } +} + +impl BufRead for CursorPacker +where + B: AsRef<[u8]>, +{ + fn fill_buf(&mut self) -> io::Result<&[u8]> { + self.cursor.fill_buf() + } + + fn consume(&mut self, amt: usize) { + self.cursor.consume(amt) + } +} + +impl Seek for CursorPacker +where + B: AsRef<[u8]>, +{ + fn seek(&mut self, pos: SeekFrom) -> io::Result { + self.cursor.seek(pos) + } +} diff --git a/msgpacker/src/packer/impls.rs b/msgpacker/src/packer/impls.rs new file mode 100644 index 0000000..f54c237 --- /dev/null +++ b/msgpacker/src/packer/impls.rs @@ -0,0 +1,1033 @@ +use crate::packer::{Packable, Unpackable}; +use crate::types::{Extension, ExtensionRef, Float, Integer, MapEntry, MapEntryRef}; +use crate::{Message, MessageRef}; + +use std::io; + +macro_rules! packable { + ($t:ty) => { + impl Packable for $t { + fn pack(&self, mut packer: W) -> io::Result + where + W: io::Write, + { + MessageRef::from(self).pack(packer.by_ref()) + } + } + + impl Unpackable for $t { + fn unpack(mut unpacker: R) -> io::Result + where + R: io::BufRead, + { + // Safety: The temporary message reference lives long enough until deserialize + unsafe { MessageRef::unpack(unpacker.by_ref()) }.and_then(MessageRef::try_into) + } + } + }; +} + +macro_rules! packable_copy { + ($t:ty) => { + impl Packable for $t { + fn pack(&self, mut packer: W) -> io::Result + where + W: io::Write, + { + MessageRef::from(*self).pack(packer.by_ref()) + } + } + + impl Unpackable for $t { + fn unpack(mut unpacker: R) -> io::Result + where + R: io::BufRead, + { + // Safety: The temporary message reference lives long enough until deserialize + unsafe { MessageRef::unpack(unpacker.by_ref()) }.and_then(MessageRef::try_into) + } + } + }; +} + +macro_rules! packable_vec { + ($t:ty) => { + impl Packable for Vec<$t> { + fn pack(&self, mut packer: W) -> io::Result + where + W: io::Write, + { + self.iter() + .try_fold(0, |s, m| Ok(s + m.pack(packer.by_ref())?)) + } + } + + impl Unpackable for Vec<$t> { + fn unpack(mut unpacker: R) -> io::Result + where + R: io::BufRead, + { + // Safety: The temporary message reference lives long enough until deserialize + unsafe { MessageRef::unpack(unpacker.by_ref()) }? + .as_array() + .ok_or_else(|| { + io::Error::new(io::ErrorKind::InvalidData, "expected vector of messages") + })? + .into_iter() + .cloned() + .map(MessageRef::try_into) + .collect() + } + } + }; +} + +packable_copy!(Integer); +packable_copy!(u8); +packable_copy!(u16); +packable_copy!(u32); +packable_copy!(u64); +packable_copy!(i8); +packable_copy!(i16); +packable_copy!(i32); +packable_copy!(i64); +packable_copy!(bool); +packable_copy!(Float); +packable_copy!(f32); +packable_copy!(f64); +packable_copy!(&str); +packable_copy!(&[u8]); +packable!(String); +packable!(Vec); +packable!(Extension); + +packable_vec!(Integer); +packable_vec!(u16); +packable_vec!(u32); +packable_vec!(u64); +packable_vec!(i8); +packable_vec!(i16); +packable_vec!(i32); +packable_vec!(i64); +packable_vec!(bool); +packable_vec!(Float); +packable_vec!(f32); +packable_vec!(f64); +packable_vec!(String); +packable_vec!(Vec); +packable_vec!(Extension); + +impl Packable for Message { + fn pack(&self, mut packer: W) -> io::Result + where + W: io::Write, + { + self.pack(packer.by_ref()) + } +} + +impl Unpackable for Message { + fn unpack(mut unpacker: R) -> io::Result + where + R: io::BufRead, + { + Message::unpack(unpacker.by_ref()) + } +} + +impl Packable for Vec { + fn pack(&self, mut packer: W) -> io::Result + where + W: io::Write, + { + self.iter() + .try_fold(0, |s, m| Ok(s + m.pack(packer.by_ref())?)) + } +} + +impl Unpackable for Vec { + fn unpack(mut unpacker: R) -> io::Result + where + R: io::BufRead, + { + let v = unsafe { + MessageRef::unpack(unpacker.by_ref())? + .as_array() + .ok_or_else(|| { + io::Error::new(io::ErrorKind::InvalidData, "expected vector of messages") + })? + .into_iter() + .cloned() + .map(|m| m.into_owned()) + .collect() + }; + + Ok(v) + } +} + +impl From for Message { + fn from(v: Integer) -> Self { + Self::Integer(v) + } +} + +impl From for Message { + fn from(v: u8) -> Self { + Self::Integer(Integer::unsigned(v)) + } +} + +impl From for Message { + fn from(v: u16) -> Self { + Self::Integer(Integer::unsigned(v)) + } +} + +impl From for Message { + fn from(v: u32) -> Self { + Self::Integer(Integer::unsigned(v)) + } +} + +impl From for Message { + fn from(v: u64) -> Self { + Self::Integer(Integer::unsigned(v)) + } +} + +impl From for Message { + fn from(v: i8) -> Self { + Self::Integer(Integer::signed(v)) + } +} + +impl From for Message { + fn from(v: i16) -> Self { + Self::Integer(Integer::signed(v)) + } +} + +impl From for Message { + fn from(v: i32) -> Self { + Self::Integer(Integer::signed(v)) + } +} + +impl From for Message { + fn from(v: i64) -> Self { + Self::Integer(Integer::signed(v)) + } +} + +impl From for Message { + fn from(v: bool) -> Self { + Self::Boolean(v) + } +} + +impl From for Message { + fn from(v: Float) -> Self { + Self::Float(v) + } +} + +impl From for Message { + fn from(v: f32) -> Self { + Self::Float(Float::f32(v)) + } +} + +impl From for Message { + fn from(v: f64) -> Self { + Self::Float(Float::f64(v)) + } +} + +impl From<&str> for Message { + fn from(v: &str) -> Self { + Self::String(v.to_owned()) + } +} + +impl From for Message { + fn from(v: String) -> Self { + Self::String(v) + } +} + +impl From> for Message { + fn from(b: Vec) -> Self { + Self::Bin(b) + } +} + +impl From> for Message { + fn from(a: Vec) -> Self { + Self::Array(a) + } +} + +impl From for Message { + fn from(m: MapEntry) -> Self { + Self::Map(vec![m]) + } +} + +impl From> for Message { + fn from(m: Vec) -> Self { + Self::Map(m) + } +} + +impl From for Message { + fn from(e: Extension) -> Self { + Self::Extension(e) + } +} + +impl<'a> From<&'a Extension> for MessageRef<'a> { + fn from(e: &'a Extension) -> Self { + MessageRef::Extension(e.to_ref()) + } +} + +impl<'a> From for MessageRef<'a> { + fn from(v: Integer) -> Self { + Self::Integer(v) + } +} + +impl<'a> From for MessageRef<'a> { + fn from(v: u8) -> Self { + Self::Integer(Integer::unsigned(v)) + } +} + +impl<'a> From for MessageRef<'a> { + fn from(v: u16) -> Self { + Self::Integer(Integer::unsigned(v)) + } +} + +impl<'a> From for MessageRef<'a> { + fn from(v: u32) -> Self { + Self::Integer(Integer::unsigned(v)) + } +} + +impl<'a> From for MessageRef<'a> { + fn from(v: u64) -> Self { + Self::Integer(Integer::unsigned(v)) + } +} + +impl<'a> From for MessageRef<'a> { + fn from(v: i8) -> Self { + Self::Integer(Integer::signed(v)) + } +} + +impl<'a> From for MessageRef<'a> { + fn from(v: i16) -> Self { + Self::Integer(Integer::signed(v)) + } +} + +impl<'a> From for MessageRef<'a> { + fn from(v: i32) -> Self { + Self::Integer(Integer::signed(v)) + } +} + +impl<'a> From for MessageRef<'a> { + fn from(v: i64) -> Self { + Self::Integer(Integer::signed(v)) + } +} + +impl<'a> From for MessageRef<'a> { + fn from(v: bool) -> Self { + Self::Boolean(v) + } +} + +impl<'a> From for MessageRef<'a> { + fn from(v: Float) -> Self { + Self::Float(v) + } +} + +impl<'a> From for MessageRef<'a> { + fn from(v: f32) -> Self { + Self::Float(Float::f32(v)) + } +} + +impl<'a> From for MessageRef<'a> { + fn from(v: f64) -> Self { + Self::Float(Float::f64(v)) + } +} + +impl<'a> From<&'a str> for MessageRef<'a> { + fn from(s: &'a str) -> Self { + Self::String(s) + } +} + +impl<'a> From<&'a String> for MessageRef<'a> { + fn from(v: &'a String) -> Self { + Self::String(v.as_str()) + } +} + +impl<'a> From<&'a [u8]> for MessageRef<'a> { + fn from(b: &'a [u8]) -> Self { + Self::Bin(b) + } +} + +impl<'a> From<&'a Vec> for MessageRef<'a> { + fn from(b: &'a Vec) -> Self { + Self::Bin(b) + } +} + +impl<'a> From>> for MessageRef<'a> { + fn from(a: Vec>) -> Self { + Self::Array(a) + } +} + +impl<'a> From<&'a [MessageRef<'a>]> for MessageRef<'a> { + fn from(a: &'a [MessageRef<'a>]) -> Self { + Self::Array(a.to_vec()) + } +} + +impl<'a> From> for MessageRef<'a> { + fn from(m: MapEntryRef<'a>) -> Self { + Self::Map(vec![m]) + } +} + +impl<'a> From>> for MessageRef<'a> { + fn from(m: Vec>) -> Self { + Self::Map(m) + } +} + +impl<'a> From<&'a [MapEntryRef<'a>]> for MessageRef<'a> { + fn from(m: &'a [MapEntryRef<'a>]) -> Self { + Self::Map(m.to_vec()) + } +} + +impl<'a> From> for MessageRef<'a> { + fn from(e: ExtensionRef<'a>) -> Self { + Self::Extension(e) + } +} + +macro_rules! packable_array { + ($n:expr) => { + impl From<[u8; $n]> for Message { + fn from(b: [u8; $n]) -> Self { + Self::from(b.to_vec()) + } + } + + impl<'a> From<&'a [u8; $n]> for MessageRef<'a> { + fn from(b: &'a [u8; $n]) -> Self { + MessageRef::from(&b[..]) + } + } + + impl TryFrom for [u8; $n] { + type Error = io::Error; + + fn try_from(m: Message) -> Result<[u8; $n], Self::Error> { + m.as_bin() + .ok_or_else(|| { + io::Error::new(io::ErrorKind::InvalidData, "expected fixed array message") + }) + .and_then(|b| { + <[u8; $n]>::try_from(b).map_err(|_| { + io::Error::new( + io::ErrorKind::InvalidData, + "expected fixed array message - invalid len", + ) + }) + }) + } + } + + impl<'a> TryFrom> for [u8; $n] { + type Error = io::Error; + + fn try_from(m: MessageRef<'a>) -> Result<[u8; $n], Self::Error> { + m.as_bin() + .ok_or_else(|| { + io::Error::new(io::ErrorKind::InvalidData, "expected fixed array message") + }) + .and_then(|b| { + <[u8; $n]>::try_from(b).map_err(|_| { + io::Error::new( + io::ErrorKind::InvalidData, + "expected fixed array message - invalid len", + ) + }) + }) + } + } + + impl Packable for [u8; $n] { + fn pack(&self, mut packer: W) -> io::Result + where + W: io::Write, + { + MessageRef::from(&self[..]).pack(packer.by_ref()) + } + } + + impl Unpackable for [u8; $n] { + fn unpack(mut unpacker: R) -> io::Result + where + R: io::BufRead, + { + // Safety: The temporary message reference lives long enough until deserialize + unsafe { MessageRef::unpack(unpacker.by_ref()) }.and_then(MessageRef::try_into) + } + } + }; +} + +packable_array!(1); +packable_array!(2); +packable_array!(3); +packable_array!(4); +packable_array!(5); +packable_array!(6); +packable_array!(7); +packable_array!(8); +packable_array!(9); +packable_array!(10); +packable_array!(11); +packable_array!(12); +packable_array!(13); +packable_array!(14); +packable_array!(15); +packable_array!(16); +packable_array!(17); +packable_array!(18); +packable_array!(19); +packable_array!(20); +packable_array!(21); +packable_array!(22); +packable_array!(23); +packable_array!(24); +packable_array!(25); +packable_array!(26); +packable_array!(27); +packable_array!(28); +packable_array!(29); +packable_array!(30); +packable_array!(31); +packable_array!(32); +packable_array!(33); +packable_array!(34); +packable_array!(35); +packable_array!(36); +packable_array!(37); +packable_array!(38); +packable_array!(39); +packable_array!(40); +packable_array!(41); +packable_array!(42); +packable_array!(43); +packable_array!(44); +packable_array!(45); +packable_array!(46); +packable_array!(47); +packable_array!(48); +packable_array!(49); +packable_array!(50); +packable_array!(51); +packable_array!(52); +packable_array!(53); +packable_array!(54); +packable_array!(55); +packable_array!(56); +packable_array!(57); +packable_array!(58); +packable_array!(59); +packable_array!(60); +packable_array!(61); +packable_array!(62); +packable_array!(63); +packable_array!(64); + +impl TryFrom for Integer { + type Error = io::Error; + + fn try_from(message: Message) -> Result { + message.as_integer().ok_or(io::Error::new( + io::ErrorKind::InvalidData, + "expected integer message", + )) + } +} + +impl<'a> TryFrom> for Integer { + type Error = io::Error; + + fn try_from(message: MessageRef<'a>) -> Result { + message.as_integer().ok_or(io::Error::new( + io::ErrorKind::InvalidData, + "expected integer message", + )) + } +} + +impl TryFrom for u8 { + type Error = io::Error; + + fn try_from(message: Message) -> Result { + message + .as_integer() + .map(|i| i.as_unsigned() as u8) + .ok_or(io::Error::new( + io::ErrorKind::InvalidData, + "expected byte message", + )) + } +} + +impl<'a> TryFrom> for u8 { + type Error = io::Error; + + fn try_from(message: MessageRef<'a>) -> Result { + message + .as_integer() + .map(|i| i.as_unsigned() as u8) + .ok_or(io::Error::new( + io::ErrorKind::InvalidData, + "expected byte message", + )) + } +} + +impl TryFrom for u16 { + type Error = io::Error; + + fn try_from(message: Message) -> Result { + message + .as_integer() + .map(|i| i.as_unsigned() as u16) + .ok_or(io::Error::new( + io::ErrorKind::InvalidData, + "expected u16 message", + )) + } +} + +impl<'a> TryFrom> for u16 { + type Error = io::Error; + + fn try_from(message: MessageRef<'a>) -> Result { + message + .as_integer() + .map(|i| i.as_unsigned() as u16) + .ok_or(io::Error::new( + io::ErrorKind::InvalidData, + "expected u16 message", + )) + } +} + +impl TryFrom for u32 { + type Error = io::Error; + + fn try_from(message: Message) -> Result { + message + .as_integer() + .map(|i| i.as_unsigned() as u32) + .ok_or(io::Error::new( + io::ErrorKind::InvalidData, + "expected u32 message", + )) + } +} + +impl<'a> TryFrom> for u32 { + type Error = io::Error; + + fn try_from(message: MessageRef<'a>) -> Result { + message + .as_integer() + .map(|i| i.as_unsigned() as u32) + .ok_or(io::Error::new( + io::ErrorKind::InvalidData, + "expected u32 message", + )) + } +} + +impl TryFrom for u64 { + type Error = io::Error; + + fn try_from(message: Message) -> Result { + message + .as_integer() + .map(|i| i.as_unsigned() as u64) + .ok_or(io::Error::new( + io::ErrorKind::InvalidData, + "expected u64 message", + )) + } +} + +impl<'a> TryFrom> for u64 { + type Error = io::Error; + + fn try_from(message: MessageRef<'a>) -> Result { + message + .as_integer() + .map(|i| i.as_unsigned() as u64) + .ok_or(io::Error::new( + io::ErrorKind::InvalidData, + "expected u64 message", + )) + } +} + +impl TryFrom for i8 { + type Error = io::Error; + + fn try_from(message: Message) -> Result { + message + .as_integer() + .map(|i| i.as_signed() as i8) + .ok_or(io::Error::new( + io::ErrorKind::InvalidData, + "expected signed byte message", + )) + } +} + +impl<'a> TryFrom> for i8 { + type Error = io::Error; + + fn try_from(message: MessageRef<'a>) -> Result { + message + .as_integer() + .map(|i| i.as_signed() as i8) + .ok_or(io::Error::new( + io::ErrorKind::InvalidData, + "expected signed byte message", + )) + } +} + +impl TryFrom for i16 { + type Error = io::Error; + + fn try_from(message: Message) -> Result { + message + .as_integer() + .map(|i| i.as_signed() as i16) + .ok_or(io::Error::new( + io::ErrorKind::InvalidData, + "expected i16 message", + )) + } +} + +impl<'a> TryFrom> for i16 { + type Error = io::Error; + + fn try_from(message: MessageRef<'a>) -> Result { + message + .as_integer() + .map(|i| i.as_signed() as i16) + .ok_or(io::Error::new( + io::ErrorKind::InvalidData, + "expected i16 message", + )) + } +} + +impl TryFrom for i32 { + type Error = io::Error; + + fn try_from(message: Message) -> Result { + message + .as_integer() + .map(|i| i.as_signed() as i32) + .ok_or(io::Error::new( + io::ErrorKind::InvalidData, + "expected i32 message", + )) + } +} + +impl<'a> TryFrom> for i32 { + type Error = io::Error; + + fn try_from(message: MessageRef<'a>) -> Result { + message + .as_integer() + .map(|i| i.as_signed() as i32) + .ok_or(io::Error::new( + io::ErrorKind::InvalidData, + "expected i32 message", + )) + } +} + +impl TryFrom for i64 { + type Error = io::Error; + + fn try_from(message: Message) -> Result { + message + .as_integer() + .map(|i| i.as_signed() as i64) + .ok_or(io::Error::new( + io::ErrorKind::InvalidData, + "expected i64 message", + )) + } +} + +impl<'a> TryFrom> for i64 { + type Error = io::Error; + + fn try_from(message: MessageRef<'a>) -> Result { + message + .as_integer() + .map(|i| i.as_signed() as i64) + .ok_or(io::Error::new( + io::ErrorKind::InvalidData, + "expected i64 message", + )) + } +} + +impl TryFrom for bool { + type Error = io::Error; + + fn try_from(message: Message) -> Result { + message.as_boolean().ok_or(io::Error::new( + io::ErrorKind::InvalidData, + "expected bool message", + )) + } +} + +impl<'a> TryFrom> for bool { + type Error = io::Error; + + fn try_from(message: MessageRef<'a>) -> Result { + message.as_boolean().ok_or(io::Error::new( + io::ErrorKind::InvalidData, + "expected bool message", + )) + } +} + +impl TryFrom for Float { + type Error = io::Error; + + fn try_from(message: Message) -> Result { + message.as_float().ok_or(io::Error::new( + io::ErrorKind::InvalidData, + "expected float message", + )) + } +} + +impl<'a> TryFrom> for Float { + type Error = io::Error; + + fn try_from(message: MessageRef<'a>) -> Result { + message.as_float().ok_or(io::Error::new( + io::ErrorKind::InvalidData, + "expected float message", + )) + } +} + +impl TryFrom for f32 { + type Error = io::Error; + + fn try_from(message: Message) -> Result { + message + .as_float() + .and_then(|f| f.as_f32()) + .ok_or(io::Error::new( + io::ErrorKind::InvalidData, + "expected f32 message", + )) + } +} + +impl<'a> TryFrom> for f32 { + type Error = io::Error; + + fn try_from(message: MessageRef<'a>) -> Result { + message + .as_float() + .and_then(|f| f.as_f32()) + .ok_or(io::Error::new( + io::ErrorKind::InvalidData, + "expected f32 message", + )) + } +} + +impl TryFrom for f64 { + type Error = io::Error; + + fn try_from(message: Message) -> Result { + message + .as_float() + .and_then(|f| f.as_f64()) + .ok_or(io::Error::new( + io::ErrorKind::InvalidData, + "expected f64 message", + )) + } +} + +impl<'a> TryFrom> for f64 { + type Error = io::Error; + + fn try_from(message: MessageRef<'a>) -> Result { + message + .as_float() + .and_then(|f| f.as_f64()) + .ok_or(io::Error::new( + io::ErrorKind::InvalidData, + "expected f64 message", + )) + } +} + +impl TryFrom for String { + type Error = io::Error; + + fn try_from(message: Message) -> Result { + message + .as_string() + .map(|s| s.to_owned()) + .ok_or(io::Error::new( + io::ErrorKind::InvalidData, + "expected string message", + )) + } +} + +impl<'a> TryFrom> for &'a str { + type Error = io::Error; + + fn try_from(message: MessageRef<'a>) -> Result { + message.as_string().ok_or(io::Error::new( + io::ErrorKind::InvalidData, + "expected string message", + )) + } +} + +impl<'a> TryFrom> for String { + type Error = io::Error; + + fn try_from(message: MessageRef<'a>) -> Result { + message + .as_string() + .map(|s| s.to_owned()) + .ok_or(io::Error::new( + io::ErrorKind::InvalidData, + "expected string message", + )) + } +} + +impl TryFrom for Vec { + type Error = io::Error; + + fn try_from(message: Message) -> Result { + message.as_bin().map(|s| s.to_owned()).ok_or(io::Error::new( + io::ErrorKind::InvalidData, + "expected binary message", + )) + } +} + +impl<'a> TryFrom> for &'a [u8] { + type Error = io::Error; + + fn try_from(message: MessageRef<'a>) -> Result { + message.as_bin().ok_or(io::Error::new( + io::ErrorKind::InvalidData, + "expected binary message", + )) + } +} + +impl<'a> TryFrom> for Vec { + type Error = io::Error; + + fn try_from(message: MessageRef<'a>) -> Result { + message.as_bin().map(|s| s.to_owned()).ok_or(io::Error::new( + io::ErrorKind::InvalidData, + "expected binary message", + )) + } +} + +impl<'a> TryFrom> for Extension { + type Error = io::Error; + + fn try_from(message: MessageRef<'a>) -> Result { + match message { + // Safety: Owned extension will be cloned + MessageRef::Extension(x) => Ok(unsafe { x.into_owned() }), + + _ => Err(io::Error::new( + io::ErrorKind::InvalidData, + "expected extension message", + )), + } + } +} + +impl FromIterator for Message { + fn from_iter>(iter: I) -> Self { + iter.into_iter().collect::>().into() + } +} + +impl FromIterator for Message { + fn from_iter>(iter: I) -> Self { + iter.into_iter().collect::>().into() + } +} + +impl FromIterator for Message { + fn from_iter>(iter: I) -> Self { + iter.into_iter().collect::>().into() + } +} + +impl<'a> FromIterator> for MessageRef<'a> { + fn from_iter>>(iter: I) -> Self { + iter.into_iter().collect::>>().into() + } +} + +impl<'a> FromIterator> for MessageRef<'a> { + fn from_iter>>(iter: I) -> Self { + iter.into_iter().collect::>>().into() + } +}