From 1f0c387b82287fd675f34bf8e9210ef7901ff36c Mon Sep 17 00:00:00 2001 From: Vincent Herlemont Date: Sun, 29 Oct 2023 09:45:28 +0100 Subject: [PATCH] test: fix test readme --- libraries/native_model/README.md | 178 +++++++++++------------- libraries/native_model/README.md.skt.md | 45 +----- libraries/native_model/src/codec/mod.rs | 20 +-- 3 files changed, 100 insertions(+), 143 deletions(-) diff --git a/libraries/native_model/README.md b/libraries/native_model/README.md index 2d569fc2..7d19f18c 100644 --- a/libraries/native_model/README.md +++ b/libraries/native_model/README.md @@ -5,7 +5,7 @@ [![Documentation](https://docs.rs/native_model/badge.svg)](https://docs.rs/native_model) [![License](https://img.shields.io/crates/l/native_model)](LICENSE) -A thin wrapper around serialized data which add information of identity and version. +Add interoperability on the top of serialization formats like bincode, postcard etc. See [concepts](#concepts) for more details. @@ -20,12 +20,12 @@ See [concepts](#concepts) for more details. ## Usage ``` - Application 1 (DotV1) Application 2 (DotV1 and DotV2) - | | - Encode DotV1 |----------------------------------------> | Decode DotV1 to DotV2 - | | Modify DotV2 - Decode DotV1 | <----------------------------------------| Encode DotV2 back to DotV1 - | | + Application 1 (DotV1) Application 2 (DotV1 and DotV2) + | | + Encode DotV1 |--------------------------------> | Decode DotV1 to DotV2 + | | Modify DotV2 + Decode DotV1 | <--------------------------------| Encode DotV2 back to DotV1 + | | ``` @@ -56,20 +56,83 @@ let (dot, _) = native_model::decode::(bytes).unwrap(); assert_eq!(dot, DotV1(5, 2)); ``` -Full example [here](./tests/example/example_main.rs). + - Full example [here](./tests_crate/tests/example/example_main.rs). -When to use it? -- Your applications that interact with each other are written in Rust. -- Your applications evolve independently need to read serialized data coming from each other. -- Your applications store data locally and need to read it later by a newer version of the application. -- Your systems need to be upgraded incrementally. Instead of having to upgrade the entire system at once, individual - applications can be upgraded one at a time, while still being able to communicate with each other. +## Serialization format -When not to use it? -- Your applications that interact with each other are **not all** written in Rust. -- Your applications need to communicate with other systems that you don't control. -- You need to have a human-readable format. (You can use a human-readable format like JSON wrapped in a native model, - but you have to unwrap it to see the data correctly.) +You can use default serialization formats via the feature flags, like: + +```toml +[dependencies] +native_model = { version = "0.1", features = ["bincode_2_rc"] } +``` + +Each feature flag corresponds to a specific minor version of the serialization format. In order to avoid breaking +changes, the default serialization format is the oldest one. + +- `bincode_1_3`: [bincode](https://docs.rs/bincode/1.3.3/bincode/) v1.3 (default) +- `bincode_2_rc`: [bincode](https://docs.rs/bincode/2.0.0-rc.3/bincode/) v2.0.0-rc3 +- `postcard_1_0`: [postcard](https://docs.rs/postcard/1.0.0/postcard/) v1.0 + +### Custom serialization format + +Define a struct with the name you want. This struct must implement [`native_model::Encode`](https://docs.rs/native_model/latest/native_model/trait.Encode.html) and [`native_model::Decode`](https://docs.rs/native_model/latest/native_model/trait.Decode.html) traits. + +Full examples: +- [bincode with encode/decode](./tests_crate/tests/example/encode_decode/bincode.rs) +- [bincode with serde](./tests_crate/tests/example/encode_decode/bincode_serde.rs) + +Others examples, see the default implementations: +- [bincode v1.3](./src/codec/bincode_1_3.rs) +- [bincode v2.0 (rc)](./src/codec/bincode_2_rc.rs) +- [postcard v1.0](./src/codec/postcard_1_0.rs) + +## Data model + +Define your model using the macro [`native_model`](file:///home/vincentherlemont/IdeaProjects/native_model/target/doc/native_model/attr.native_model.html). + +Attributes: +- `id = u32`: The unique identifier of the model. +- `version = u32`: The version of the model. +- `with = type`: The serialization format that you use for the Encode/Decode implementation. Setup [here](#setup-your-serialization-format). +- `from = type`: Optional, the previous version of the model. + - `type`: The previous version of the model that you use for the From implementation. +- `try_from = (type, error)`: Optional, the previous version of the model with error handling. + - `type`: The previous version of the model that you use for the TryFrom implementation. + - `error`: The error type that you use for the TryFrom implementation. + +```rust,skt-define-models +use native_model::native_model; + +#[derive(Deserialize, Serialize, PartialEq, Debug)] +#[native_model(id = 1, version = 1)] +struct DotV1(u32, u32); + +#[derive(Deserialize, Serialize, PartialEq, Debug)] +#[native_model(id = 1, version = 2, from = DotV1)] +struct DotV2 { + name: String, + x: u64, + y: u64, +} + +// Implement the conversion between versions From for DotV2 and From for DotV1. + +#[derive(Deserialize, Serialize, PartialEq, Debug)] +#[native_model(id = 1, version = 3, try_from = (DotV2, anyhow::Error))] +struct DotV3 { + name: String, + cord: Cord, +} + +#[derive(Deserialize, Serialize, PartialEq, Debug)] +struct Cord { + x: u64, + y: u64, +} + +// Implement the conversion between versions From for DotV3 and From for DotV2. +``` ## Status @@ -96,83 +159,6 @@ Under the hood, the native model is a thin wrapper around serialized data. The ` +------------------+------------------+------------------------------------+ ``` -## Setup your serialization format - -First, you need to set up your serialization format. You can use any serialization format. - -Just define a struct with the name you want. This struct must implement [`native_model::Encode`](https://docs.rs/native_model/latest/native_model/trait.Encode.html) and [`native_model::Decode`](https://docs.rs/native_model/latest/native_model/trait.Decode.html) traits. - -In the below example we have created a struct `Bincode` that use the [bincode](https://docs.rs/bincode/latest/bincode/) crate: -```rust,skt-define-serilization-format -pub struct Bincode; - -impl native_model::Encode for Bincode { - type Error = bincode::error::EncodeError; - fn encode(obj: &T) -> Result, bincode::error::EncodeError> { - bincode::encode_to_vec(obj, bincode::config::standard()) - } -} - -impl native_model::Decode for Bincode { - type Error = bincode::error::DecodeError; - fn decode(data: Vec) -> Result { - bincode::decode_from_slice(&data, bincode::config::standard()).map(|(result, _)| result) - } -} -``` - -Full examples: -- [bincode with encode/decode](./tests/example/encode_decode/bincode.rs) -- [bincode with serde](./tests/example/encode_decode/bincode_serde.rs) - - -## Setup your data model - -Define your model using the macro [`native_model`](file:///home/vincentherlemont/IdeaProjects/native_model/target/doc/native_model/attr.native_model.html). - -Attributes: -- `id = u32`: The unique identifier of the model. -- `version = u32`: The version of the model. -- `with = type`: The serialization format that you use for the Encode/Decode implementation. Setup [here](#setup-your-serialization-format). -- `from = type`: Optional, the previous version of the model. - - `type`: The previous version of the model that you use for the From implementation. -- `try_from = (type, error)`: Optional, the previous version of the model with error handling. - - `type`: The previous version of the model that you use for the TryFrom implementation. - - `error`: The error type that you use for the TryFrom implementation. - -```rust,skt-define-models -use native_model::native_model; - -#[derive(Encode, Decode, PartialEq, Debug)] -#[native_model(id = 1, version = 1, with = Bincode)] -struct DotV1(u32, u32); - -#[derive(Encode, Decode, PartialEq, Debug)] -#[native_model(id = 1, version = 2, with = Bincode, from = DotV1)] -struct DotV2 { - name: String, - x: u64, - y: u64, -} - -// Implement the conversion between versions From for DotV2 and From for DotV1. - -#[derive(Encode, Decode, PartialEq, Debug)] -#[native_model(id = 1, version = 3, with = Bincode, try_from = (DotV2, anyhow::Error))] -struct DotV3 { - name: String, - cord: Cord, -} - -#[derive(Encode, Decode, PartialEq, Debug)] -struct Cord { - x: u64, - y: u64, -} - -// Implement the conversion between versions From for DotV3 and From for DotV2. -``` - Full example [here](tests/example/example_define_model.rs). ## Performance diff --git a/libraries/native_model/README.md.skt.md b/libraries/native_model/README.md.skt.md index 9cb43ea9..a8ab5d47 100644 --- a/libraries/native_model/README.md.skt.md +++ b/libraries/native_model/README.md.skt.md @@ -1,30 +1,13 @@ ```rust,skt-main -use bincode; -use bincode::{{Decode, Encode, config}}; use native_model_macro::native_model; +use serde::{{Deserialize, Serialize}}; -pub struct Bincode; - -impl native_model::Encode for Bincode {{ - type Error = bincode::error::EncodeError; - fn encode(obj: &T) -> Result, bincode::error::EncodeError> {{ - bincode::encode_to_vec(obj, config::standard()) - }} -}} - -impl native_model::Decode for Bincode {{ - type Error = bincode::error::DecodeError; - fn decode(data: Vec) -> Result {{ - bincode::decode_from_slice(&data, config::standard()).map(|(result, _)| result) - }} -}} - -#[derive(Encode, Decode, PartialEq, Debug)] -#[native_model(id = 1, version = 1, with = Bincode)] +#[derive(Deserialize, Serialize, PartialEq, Debug)] +#[native_model(id = 1, version = 1)] struct DotV1(u32, u32); -#[derive(Encode, Decode, PartialEq, Debug)] -#[native_model(id = 1, version = 2, with = Bincode, from = DotV1)] +#[derive(Deserialize, Serialize, PartialEq, Debug)] +#[native_model(id = 1, version = 2, from = DotV1)] struct DotV2 {{ name: String, x: u64, @@ -54,23 +37,7 @@ fn main() {{ ``` ```rust,skt-define-models -use bincode::{{config, Decode, Encode}}; - -pub struct Bincode; - -impl native_model::Encode for Bincode {{ - type Error = bincode::error::EncodeError; - fn encode(obj: &T) -> Result, bincode::error::EncodeError> {{ - bincode::encode_to_vec(obj, config::standard()) - }} -}} - -impl native_model::Decode for Bincode {{ - type Error = bincode::error::DecodeError; - fn decode(data: Vec) -> Result {{ - bincode::decode_from_slice(&data, config::standard()).map(|(result, _)| result) - }} -}} +use serde::{{Deserialize, Serialize}}; {} diff --git a/libraries/native_model/src/codec/mod.rs b/libraries/native_model/src/codec/mod.rs index 1f50b559..7d9a73c2 100644 --- a/libraries/native_model/src/codec/mod.rs +++ b/libraries/native_model/src/codec/mod.rs @@ -9,12 +9,14 @@ pub mod postcard_1_0; /// /// Example: /// ```rust +/// use bincode_2_rc::{error::EncodeError,serde::encode_to_vec, config::standard}; +/// use serde::Serialize; /// pub struct Bincode; /// -/// impl native_model::Encode for Bincode { -/// type Error = bincode::error::EncodeError; -/// fn encode(obj: &T) -> Result, bincode::error::EncodeError> { -/// bincode::encode_to_vec(obj, bincode::config::standard()) +/// impl native_model::Encode for Bincode { +/// type Error = EncodeError; +/// fn encode(obj: &T) -> Result, EncodeError> { +/// Ok(encode_to_vec(&obj, standard())?) /// } /// } /// ``` @@ -27,12 +29,14 @@ pub trait Encode { /// /// Example: /// ```rust +/// use bincode_2_rc::{error::DecodeError,serde::decode_from_slice, config::standard}; +/// use serde::Deserialize; /// pub struct Bincode; /// -/// impl native_model::Decode for Bincode { -/// type Error = bincode::error::DecodeError; -/// fn decode(data: Vec) -> Result { -/// bincode::decode_from_slice(&data, bincode::config::standard()).map(|(result, _)| result) +/// impl Deserialize<'a>> native_model::Decode for Bincode { +/// type Error = DecodeError; +/// fn decode(data: Vec) -> Result { +/// Ok(decode_from_slice(&data, standard())?.0) /// } /// } pub trait Decode {