From 646673efda9030b66422dffb338f29222d0155ac Mon Sep 17 00:00:00 2001 From: Dylan Bowker Date: Sun, 12 May 2024 08:18:10 -0600 Subject: [PATCH] feat: add support for `rmp-serde` --- libraries/native_model/Cargo.toml | 3 +- .../native_model/src/codec/bincode_1_3.rs | 49 +++++++++++---- .../native_model/src/codec/bincode_2_rc.rs | 59 ++++++++++++++----- libraries/native_model/src/codec/mod.rs | 11 +++- .../native_model/src/codec/postcard_1_0.rs | 50 ++++++++++++---- .../native_model/src/codec/rmp_serde_1_3.rs | 41 +++++++++++++ libraries/native_model/src/lib.rs | 13 +++- 7 files changed, 184 insertions(+), 42 deletions(-) create mode 100644 libraries/native_model/src/codec/rmp_serde_1_3.rs diff --git a/libraries/native_model/Cargo.toml b/libraries/native_model/Cargo.toml index d89fb2cf..b91fa456 100644 --- a/libraries/native_model/Cargo.toml +++ b/libraries/native_model/Cargo.toml @@ -24,6 +24,7 @@ serde = { version = "1.0.200", features = ["derive"], optional = true } bincode_1_3 = { package = "bincode", version = "1.3.3", optional = true } bincode_2_rc = { package = "bincode", version = "2.0.0-rc.3", features = ["serde"], optional = true } postcard_1_0 = { package = "postcard", version = "1.0.8", features = ["alloc"], optional = true } +rmp_serde_1_3 = { package = "rmp-serde", version = "1.3", optional = true } [dev-dependencies] serde_json = "1.0.116" @@ -38,4 +39,4 @@ name = "overhead" harness = false [build-dependencies] -skeptic = "0.13.7" \ No newline at end of file +skeptic = "0.13.7" diff --git a/libraries/native_model/src/codec/bincode_1_3.rs b/libraries/native_model/src/codec/bincode_1_3.rs index a3fe397d..dc598e8f 100644 --- a/libraries/native_model/src/codec/bincode_1_3.rs +++ b/libraries/native_model/src/codec/bincode_1_3.rs @@ -1,19 +1,48 @@ -use bincode_1_3::{deserialize, serialize, Error}; -use serde::{Deserialize, Serialize}; +//! ⚠️ [`Read the docs before using`](crate::bincode_1_3::Bincode#warning). +//! Annotate your type with `native_model::bincode_1_3::Bincode` to use the +//! bincode 1.3 crate for serializing & deserializing. +/// Used to specify the [bincode](https://crates.io/crates/bincode/1.3.3) `1.3` +/// crate for serialization & deserialization. +/// +/// # Warning +/// +/// `bincode` [does not implement](https://github.com/bincode-org/bincode/issues/548) +/// all [serde](https://crates.io/crates/serde) features. Errors may be +/// encountered when using this with some types. +/// +/// # Basic usage +/// +/// Use the [`with`](crate::native_model) attribute on your type to instruct +/// `native_model` to use `Bincode` for serialization & deserialization. +/// +/// Example: +/// +/// ```rust +/// #[native_model(id = 1, version = 1, with = native_model::bincode_1_3::Bincode)] +/// struct MyStruct { +/// my_string: String +/// } +/// ``` + +#[doc(cfg(all(feature = "serde", feature = "bincode_1_3")))] #[derive(Default)] pub struct Bincode; -impl super::Encode for Bincode { - type Error = Error; - fn encode(obj: &T) -> Result, Error> { - Ok(serialize(obj)?) +#[cfg(all(feature = "serde", feature = "bincode_1_3"))] +impl super::Encode for Bincode { + type Error = bincode_1_3::Error; + /// Serializes a type into bytes using the `bincode` `1.3` crate. + fn encode(obj: &T) -> Result, Self::Error> { + bincode_1_3::serialize(obj) } } -impl Deserialize<'a>> super::Decode for Bincode { - type Error = Error; - fn decode(data: Vec) -> Result { - Ok(deserialize(&data[..])?) +#[cfg(all(feature = "serde", feature = "bincode_1_3"))] +impl serde::Deserialize<'de>> super::Decode for Bincode { + type Error = bincode_1_3::Error; + /// Deserializes a type from bytes using the `bincode` `1.3` crate. + fn decode(data: Vec) -> Result { + bincode_1_3::deserialize(&data[..]) } } diff --git a/libraries/native_model/src/codec/bincode_2_rc.rs b/libraries/native_model/src/codec/bincode_2_rc.rs index 400bf405..80597947 100644 --- a/libraries/native_model/src/codec/bincode_2_rc.rs +++ b/libraries/native_model/src/codec/bincode_2_rc.rs @@ -1,22 +1,53 @@ -use bincode_2_rc::{ - config, - error::{DecodeError, EncodeError}, - serde::{decode_from_slice, encode_to_vec}, -}; -use serde::{Deserialize, Serialize}; +//! ⚠️ [`Read the docs before using`](crate::bincode_2_rc::Bincode#warning). +//! Annotate your type with `native_model::bincode_2_rc::Bincode` to use +//! the bincode 2.0.0-rc.3 crate for serializing & deserializing. +/// Used to specify the [bincode](https://crates.io/crates/bincode/2.0.0-rc.3) +/// `2.0.0-rc.3` crate for serialization & deserialization. +/// +/// # Warning +/// +/// `bincode` [does not implement](https://docs.rs/bincode/2.0.0-rc.3/bincode/serde/index.html#known-issues) +/// all [serde](https://crates.io/crates/serde) features. Errors may be +/// encountered when using this with some types. +/// +/// # Basic usage +/// +/// Use the [`with`](crate::native_model) attribute on your type to instruct +/// `native_model` to use `Bincode` for serialization & deserialization. +/// +/// Example: +/// +/// ```rust +/// #[native_model(id = 1, version = 1, with = native_model::bincode_2_rc::Bincode)] +/// struct MyStruct { +/// my_string: String +/// } +/// ``` + +#[doc(cfg(all(feature = "serde", feature = "bincode_2_rc")))] pub struct Bincode; -impl super::Encode for Bincode { - type Error = EncodeError; - fn encode(obj: &T) -> Result, EncodeError> { - encode_to_vec(obj, config::standard()) +#[cfg(all(feature = "serde", feature = "bincode_2_rc"))] +impl super::Encode for Bincode { + type Error = bincode_2_rc::error::EncodeError; + /// Serializes a type into bytes using the `bincode` `2.0.0-rc.3` crate. + fn encode(obj: &T) -> Result, Self::Error> { + bincode_2_rc::serde::encode_to_vec( + obj, + bincode_2_rc::config::standard() + ) } } -impl Deserialize<'a>> super::Decode for Bincode { - type Error = DecodeError; - fn decode(data: Vec) -> Result { - Ok(decode_from_slice(&data, config::standard())?.0) +#[cfg(all(feature = "serde", feature = "bincode_2_rc"))] +impl serde::Deserialize<'de>> super::Decode for Bincode { + type Error = bincode_2_rc::error::DecodeError; + /// Deserializes a type from bytes using the `bincode` `2.0.0-rc.3` crate. + fn decode(data: Vec) -> Result { + Ok(bincode_2_rc::serde::decode_from_slice( + &data, + bincode_2_rc::config::standard() + )?.0) } } diff --git a/libraries/native_model/src/codec/mod.rs b/libraries/native_model/src/codec/mod.rs index 7d9a73c2..24c47f6d 100644 --- a/libraries/native_model/src/codec/mod.rs +++ b/libraries/native_model/src/codec/mod.rs @@ -1,9 +1,14 @@ -#[cfg(all(feature = "serde", feature = "bincode_1_3"))] +//! Traits and implementations for encoding types into a series of bytes and +//! decoding bytes back into types. + +#[cfg(any(all(feature = "serde", feature = "bincode_1_3"), doc))] pub mod bincode_1_3; -#[cfg(all(feature = "serde", feature = "bincode_2_rc"))] +#[cfg(any(all(feature = "serde", feature = "bincode_2_rc"), doc))] pub mod bincode_2_rc; -#[cfg(all(feature = "serde", feature = "postcard_1_0"))] +#[cfg(any(all(feature = "serde", feature = "postcard_1_0"), doc))] pub mod postcard_1_0; +#[cfg(any(all(feature = "serde", feature = "rmp_serde_1_3"), doc))] +pub mod rmp_serde_1_3; /// Encode trait for your own encoding method. /// diff --git a/libraries/native_model/src/codec/postcard_1_0.rs b/libraries/native_model/src/codec/postcard_1_0.rs index ddea1584..b37c7d0a 100644 --- a/libraries/native_model/src/codec/postcard_1_0.rs +++ b/libraries/native_model/src/codec/postcard_1_0.rs @@ -1,18 +1,46 @@ -use postcard_1_0::{from_bytes, to_allocvec, Error}; -use serde::{Deserialize, Serialize}; +//! ⚠️ [`Read the docs before using`](crate::postcard_1_0::PostCard#warning). +//! Annotate your type with `native_model::postcard_1_0::PostCard` to +//! use the postcard 1.0 crate for serializing & deserializing. +/// Used to specify the [postcard](https://crates.io/crates/postcard/1.0.8) +/// `1.0` crate for serialization & deserialization. +/// +/// # Warning +/// +/// `postcard` does not implement all [serde](https://crates.io/crates/serde) +/// features. Errors may be encountered when using this with some types. +/// +/// # Basic usage +/// +/// Use the [`with`](crate::native_model) attribute on your type to instruct +/// `native_model` to use `PostCard` for serialization & deserialization. +/// +/// Example: +/// +/// ```rust +/// #[native_model(id = 1, version = 1, with = native_model::postcard_1_0::PostCard)] +/// struct MyStruct { +/// my_string: String +/// } +/// ``` + +#[doc(cfg(all(feature = "serde", feature = "postcard_1_0")))] pub struct PostCard; -impl super::Encode for PostCard { - type Error = Error; - fn encode(obj: &T) -> Result, Error> { - Ok(to_allocvec(obj)?) +#[cfg(all(feature = "serde", feature = "postcard_1_0"))] +impl super::Encode for PostCard { + type Error = postcard_1_0::Error; + /// Serializes a type into bytes using the `postcard` `1.0` crate. + fn encode(obj: &T) -> Result, Self::Error> { + postcard_1_0::to_allocvec(obj) } } -impl Deserialize<'a>> super::Decode for PostCard { - type Error = Error; - fn decode(data: Vec) -> Result { - Ok(from_bytes(&data)?) +#[cfg(all(feature = "serde", feature = "postcard_1_0"))] +impl serde::Deserialize<'de>> super::Decode for PostCard { + type Error = postcard_1_0::Error; + /// Deserializes a type from bytes using the `postcard` `1.0` crate. + fn decode(data: Vec) -> Result { + postcard_1_0::from_bytes(&data) } -} +} \ No newline at end of file diff --git a/libraries/native_model/src/codec/rmp_serde_1_3.rs b/libraries/native_model/src/codec/rmp_serde_1_3.rs new file mode 100644 index 00000000..ec5cee77 --- /dev/null +++ b/libraries/native_model/src/codec/rmp_serde_1_3.rs @@ -0,0 +1,41 @@ +//! [`Annotate your type`](crate::native_model) with +//! `native_model::rmp_serde_1_3::RmpSerde` to use the rmp-serde 1.3 crate for +//! serializing & deserializing. + +/// Used to specify the [rmp-serde](https://crates.io/crates/rmp-serde/1.3.0) +/// `1.3` crate for serialization & deserialization. +/// +/// # Basic usage +/// +/// Use the [`with`](crate::native_model) attribute on your type to instruct +/// `native_model` to use `RmpSerde` for serialization & deserialization. +/// +/// Example: +/// +/// ```rust +/// #[native_model(id = 1, version = 1, with = native_model::rmp_serde_1_3::RmpSerde)] +/// struct MyStruct { +/// my_string: String +/// } +/// ``` + +#[doc(cfg(all(feature = "serde", feature = "rmp_serde_1_3")))] +pub struct RmpSerde; + +#[cfg(all(feature = "serde", feature = "rmp_serde_1_3"))] +impl crate::Encode for RmpSerde { + type Error = rmp_serde_1_3::encode::Error; + /// Serializes a type into bytes using the `rmp-serde` `1.3` crate. + fn encode(obj: &T) -> Result, Self::Error> { + rmp_serde_1_3::encode::to_vec(obj) + } +} + +#[cfg(all(feature = "serde", feature = "rmp_serde_1_3"))] +impl serde::Deserialize<'de>> crate::Decode for RmpSerde { + type Error = rmp_serde_1_3::decode::Error; + /// Deserializes a type from bytes using the `rmp-serde` `1.3` crate. + fn decode(data: Vec) -> Result { + rmp_serde_1_3::decode::from_slice(&data) + } +} \ No newline at end of file diff --git a/libraries/native_model/src/lib.rs b/libraries/native_model/src/lib.rs index 8b68b606..0079b626 100644 --- a/libraries/native_model/src/lib.rs +++ b/libraries/native_model/src/lib.rs @@ -14,12 +14,19 @@ //! - The crate is in early development, and performance is expected to improve over time. //! //! See examples in the [README.md](https://github.com/vincent-herlemont/native_model) file. +//! +//! You may also want to check [David Koloski](https://github.com/djkoloski)'s +//! [Rust serialization benchmarks](https://github.com/djkoloski/rust_serialization_benchmark) +//! for help selecting the codec right for your project. + +#![feature(doc_cfg)] #[cfg(any( feature = "serde", feature = "bincode_1_3", feature = "bincode_2_rc", - feature = "postcard_1_0" + feature = "postcard_1_0", + doc ))] mod codec; @@ -27,7 +34,8 @@ mod codec; feature = "serde", feature = "bincode_1_3", feature = "bincode_2_rc", - feature = "postcard_1_0" + feature = "postcard_1_0", + doc ))] pub use codec::*; mod header; @@ -187,7 +195,6 @@ pub trait Model: Sized { where Self: Sized, { - let version = version.clone(); let mut data = self.native_model_encode_downgrade_body(version)?; let data = crate::native_model_encode(&mut data, Self::native_model_id(), version); Ok(data)