feat: default bincode 2.0.0-rc.*

This commit is contained in:
Vincent Herlemont
2023-10-29 09:42:30 +01:00
parent 383379fe1e
commit 39466299ed
22 changed files with 68 additions and 11 deletions
-1
View File
@@ -1 +0,0 @@
mod example;
-344
View File
@@ -1,344 +0,0 @@
use bincode::{config, Decode, Encode};
use native_model::Result;
use native_model::{DecodeBodyError, DecodeResult, EncodeBodyError, EncodeResult, Model};
// Add this function to the macro for custom serialization
fn native_model_encode<T: Encode>(obj: &T) -> anyhow::Result<Vec<u8>> {
let result = bincode::encode_to_vec(obj, config::standard())?;
Ok(result)
}
// Add this function to the macro for custom deserialization
fn native_model_decode<T: Decode>(data: Vec<u8>) -> anyhow::Result<T> {
let (result, _) =
bincode::decode_from_slice(&data, config::standard()).map_err(|e| EncodeBodyError {
msg: format!("Decode error: {}", e),
source: e.into(),
})?;
Ok(result)
}
#[derive(Debug, Encode, Decode)]
struct A {}
impl Model for A {
fn native_model_id() -> u32 {
1
}
fn native_model_version() -> u32 {
1
}
fn native_model_decode_upgrade_body(_data: Vec<u8>, _id: u32, version: u32) -> Result<Self> {
println!(
"A::deserialization_and_upgrade({}, {})",
version,
Self::native_model_version()
);
if version == Self::native_model_version() {
Ok(Self {})
} else if version < Self::native_model_version() {
panic!("The version {} not supported", version);
} else {
panic!("Not implemented");
}
}
fn native_model_encode_body(&self) -> EncodeResult<Vec<u8>>
where
Self: Sized,
{
native_model_encode(self).map_err(|e| EncodeBodyError {
msg: format!("{}", e),
source: e.into(),
})
}
fn native_model_decode_body(data: Vec<u8>, _id: u32) -> DecodeResult<Self>
where
Self: Sized,
{
native_model_decode(data).map_err(|e| DecodeBodyError::DecodeError {
msg: format!("{}", e),
source: e.into(),
})
}
fn native_model_encode_downgrade_body(self, version: u32) -> Result<Vec<u8>>
where
Self: Sized,
{
println!(
"A::serialization_and_downgrade({}, {})",
version,
Self::native_model_version()
);
if version == Self::native_model_version() {
let result = self.native_model_encode_body()?;
Ok(result)
} else if version < Self::native_model_version() {
panic!("The version {} not supported", version);
} else {
panic!("Not implemented");
}
}
}
#[derive(Debug, Encode, Decode)]
struct B {}
impl Model for B {
fn native_model_id() -> u32 {
1
}
fn native_model_version() -> u32 {
2
}
fn native_model_decode_upgrade_body(_data: Vec<u8>, id: u32, version: u32) -> Result<Self> {
println!(
"B::deserialization_and_upgrade({}, {})",
version,
Self::native_model_version()
);
if version == Self::native_model_version() {
Ok(Self {})
} else if version < Self::native_model_version() {
A::native_model_decode_upgrade_body(_data, id, version).map(|a| a.into())
} else {
panic!("Not implemented");
}
}
fn native_model_encode_body(&self) -> EncodeResult<Vec<u8>>
where
Self: Sized,
{
native_model_encode(self).map_err(|e| EncodeBodyError {
msg: format!("{}", e),
source: e.into(),
})
}
fn native_model_decode_body(data: Vec<u8>, _id: u32) -> DecodeResult<Self>
where
Self: Sized,
{
native_model_decode(data).map_err(|e| DecodeBodyError::DecodeError {
msg: format!("{}", e),
source: e.into(),
})
}
fn native_model_encode_downgrade_body(self, version: u32) -> Result<Vec<u8>>
where
Self: Sized,
{
println!(
"B::serialization_and_downgrade({}, {})",
version,
Self::native_model_version()
);
if version == Self::native_model_version() {
let result = self.native_model_encode_body()?;
Ok(result)
} else if version < Self::native_model_version() {
A::native_model_encode_downgrade_body(self.into(), version)
} else {
panic!("Not implemented");
}
}
}
impl From<B> for A {
fn from(_: B) -> Self {
Self {}
}
}
impl From<A> for B {
fn from(_: A) -> Self {
Self {}
}
}
#[derive(Debug, Encode, Decode)]
struct C {}
impl Model for C {
fn native_model_id() -> u32 {
1
}
fn native_model_version() -> u32 {
3
}
fn native_model_decode_upgrade_body(_data: Vec<u8>, id: u32, version: u32) -> Result<Self> {
println!(
"C::deserialization_and_upgrade({}, {})",
version,
Self::native_model_version()
);
if version == Self::native_model_version() {
Ok(Self {})
} else if version < Self::native_model_version() {
let result = B::native_model_decode_upgrade_body(_data, id, version).map(|b| {
b.try_into()
.map_err(|e: anyhow::Error| native_model::UpgradeError {
msg: format!("{}", e),
source: e.into(),
})
})??;
Ok(result)
} else {
panic!("Not implemented");
}
}
fn native_model_encode_body(&self) -> EncodeResult<Vec<u8>>
where
Self: Sized,
{
native_model_encode(self).map_err(|e| EncodeBodyError {
msg: format!("{}", e),
source: e.into(),
})
}
fn native_model_decode_body(data: Vec<u8>, _id: u32) -> DecodeResult<Self>
where
Self: Sized,
{
native_model_decode(data).map_err(|e| DecodeBodyError::DecodeError {
msg: format!("{}", e),
source: e.into(),
})
}
fn native_model_encode_downgrade_body(self, version: u32) -> Result<Vec<u8>>
where
Self: Sized,
{
println!(
"C::serialization_and_downgrade({}, {})",
version,
Self::native_model_version()
);
if version == Self::native_model_version() {
let result = self.native_model_encode_body()?;
Ok(result)
} else if version < Self::native_model_version() {
let result = B::native_model_encode_downgrade_body(
self.try_into()
.map_err(|e: anyhow::Error| native_model::DowngradeError {
msg: format!("{}", e),
source: e.into(),
})?,
version,
)?;
Ok(result)
} else {
panic!("Not implemented");
}
}
}
impl TryFrom<C> for B {
type Error = anyhow::Error;
fn try_from(_: C) -> anyhow::Result<Self> {
Ok(Self {})
}
}
impl TryFrom<B> for C {
type Error = anyhow::Error;
fn try_from(_: B) -> anyhow::Result<Self> {
Ok(Self {})
}
}
/**
I want to manage the upgrade and downgrade of native types using From and Into traits.
Let see 3 model A,B,C of a model id 1.
A is the oldest version of the model and is the version 1.
B is the intermediate version of the model and is the version 2.
C is the most recent version of the model and is the version 3.
We need to imagine that the data are serialized as a vector of bytes. The only things that we know
is the model id 1 and the version of the model.
I need to found an elegant way to deserialize the data as the most recent version of the model.
**/
#[test]
fn test_encode_downgrade() {
let x = 3;
let result = C::native_model_encode_downgrade_body(C {}, x);
dbg!(&result);
let x = 2;
let result = C::native_model_encode_downgrade_body(C {}, x);
dbg!(&result);
let x = 1;
let result = C::native_model_encode_downgrade_body(C {}, x);
dbg!(&result);
}
#[test]
fn test_decode_upgrade() {
let id = 1;
let version = 3;
let result = C::native_model_decode_upgrade_body(vec![], id, version);
dbg!(&result);
let version = 2;
let result = C::native_model_decode_upgrade_body(vec![], id, version);
dbg!(&result);
let version = 1;
let result = C::native_model_decode_upgrade_body(vec![], id, version);
dbg!(&result);
}
fn native_model_decode_upgrade<T>(
_data: Vec<u8>,
model_id: u32,
version: u32,
) -> native_model::Result<T>
where
T: Model,
{
if model_id == T::native_model_id() {
T::native_model_decode_upgrade_body(_data, model_id, version)
} else {
panic!("The model id {} not supported", model_id);
}
}
#[test]
fn test_decode_upgrade_c() {
let x = 3;
let result: C = native_model_decode_upgrade(vec![], 1, x).unwrap();
dbg!(&result);
let x = 2;
let result: C = native_model_decode_upgrade(vec![], 1, x).unwrap();
dbg!(&result);
let x = 1;
let result: C = native_model_decode_upgrade(vec![], 1, x).unwrap();
dbg!(&result);
}
#[test]
fn test_decode_upgrade_b() {
let x = 2;
let result: B = native_model_decode_upgrade(vec![], 1, x).unwrap();
dbg!(&result);
// let x = 2;
// let result: B = native_model_decode_upgrade(vec![], 1, x).unwrap();
// dbg!(&result);
}
@@ -1,34 +0,0 @@
use bincode;
use bincode::{config, Decode, Encode};
pub struct Bincode;
impl<T: bincode::Encode> native_model::Encode<T> for Bincode {
type Error = bincode::error::EncodeError;
fn encode(obj: &T) -> Result<Vec<u8>, bincode::error::EncodeError> {
bincode::encode_to_vec(obj, config::standard())
}
}
impl<T: bincode::Decode> native_model::Decode<T> for Bincode {
type Error = bincode::error::DecodeError;
fn decode(data: Vec<u8>) -> Result<T, bincode::error::DecodeError> {
bincode::decode_from_slice(&data, config::standard()).map(|(result, _)| result)
}
}
use native_model_macro::native_model;
#[derive(Encode, Decode, PartialEq, Debug)]
#[native_model(id = 1, version = 1, with = Bincode)]
struct DotV1(u32, u32);
#[test]
fn test_bincode_encode_decode() {
// Application 1
let dot = DotV1(1, 2);
let bytes = native_model::encode(&dot).unwrap();
// Application 1
let (dot, _) = native_model::decode::<DotV1>(bytes).unwrap();
assert_eq!(dot, DotV1(1, 2));
}
@@ -1,50 +0,0 @@
use bincode;
use serde::{Deserialize, Serialize};
// fn native_model_encode_body<T: Serialize>(
// model: &T,
// ) -> Result<Vec<u8>, bincode::error::EncodeError> {
// {
// bincode::serde::encode_to_vec(model, bincode::config::standard())
// }
// }
//
// fn native_model_decode_body<T: for<'a> Deserialize<'a>>(
// data: Vec<u8>,
// ) -> Result<T, bincode::error::DecodeError> {
// {
// Ok(bincode::serde::decode_from_slice(&data, bincode::config::standard())?.0)
// }
// }
pub struct Bincode;
impl<T: Serialize> native_model::Encode<T> for Bincode {
type Error = bincode::error::EncodeError;
fn encode(obj: &T) -> Result<Vec<u8>, bincode::error::EncodeError> {
bincode::serde::encode_to_vec(obj, bincode::config::standard())
}
}
impl<T: for<'a> Deserialize<'a>> native_model::Decode<T> for Bincode {
type Error = bincode::error::DecodeError;
fn decode(data: Vec<u8>) -> Result<T, bincode::error::DecodeError> {
Ok(bincode::serde::decode_from_slice(&data, bincode::config::standard())?.0)
}
}
use native_model_macro::native_model;
#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[native_model(id = 1, version = 1, with = Bincode)]
struct DotV1(u32, u32);
#[test]
fn test_bincode_serde_serialize_deserialize() {
// Application 1
let dot = DotV1(1, 2);
let bytes = native_model::encode(&dot).unwrap();
// Application 1
let (dot, _) = native_model::decode::<DotV1>(bytes).unwrap();
assert_eq!(dot, DotV1(1, 2));
}
@@ -1,2 +0,0 @@
mod bincode;
mod bincode_serde;
@@ -1,18 +0,0 @@
use native_model::native_model;
use serde::Deserialize;
use serde::Serialize;
#[derive(Serialize, Deserialize, PartialEq, Debug)]
#[native_model(id = 1, version = 1, with = native_model::bincode_1_3::Bincode)]
struct Example {
a: u32,
b: u32,
}
#[test]
fn encode_decode() {
let example = Example { a: 1, b: 2 };
let bytes = native_model::encode(&example).unwrap();
let (example, _) = native_model::decode::<Example>(bytes).unwrap();
assert_eq!(example, Example { a: 1, b: 2 });
}
@@ -1 +0,0 @@
mod bincode_1_3;
@@ -1,110 +0,0 @@
use bincode::{config, Decode, Encode};
use native_model_macro::native_model;
pub struct Bincode;
impl<T: bincode::Encode> native_model::Encode<T> for Bincode {
type Error = bincode::error::EncodeError;
fn encode(obj: &T) -> Result<Vec<u8>, bincode::error::EncodeError> {
bincode::encode_to_vec(obj, config::standard())
}
}
impl<T: bincode::Decode> native_model::Decode<T> for Bincode {
type Error = bincode::error::DecodeError;
fn decode(data: Vec<u8>) -> Result<T, bincode::error::DecodeError> {
bincode::decode_from_slice(&data, config::standard()).map(|(result, _)| result)
}
}
#[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,
}
impl From<DotV1> for DotV2 {
fn from(dot: DotV1) -> Self {
DotV2 {
name: "".to_string(),
x: dot.0 as u64,
y: dot.1 as u64,
}
}
}
impl From<DotV2> for DotV1 {
fn from(dot: DotV2) -> Self {
DotV1(dot.x as u32, dot.y as u32)
}
}
#[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,
}
impl TryFrom<DotV2> for DotV3 {
type Error = anyhow::Error;
fn try_from(dot: DotV2) -> Result<Self, Self::Error> {
Ok(DotV3 {
name: dot.name,
cord: Cord { x: dot.x, y: dot.y },
})
}
}
impl TryFrom<DotV3> for DotV2 {
type Error = anyhow::Error;
fn try_from(dot: DotV3) -> Result<Self, Self::Error> {
Ok(DotV2 {
name: dot.name,
x: dot.cord.x,
y: dot.cord.y,
})
}
}
#[test]
fn simple_test() {
let dot = DotV1(1, 2);
let bytes = native_model::encode(&dot).unwrap();
let (dot_decoded, _) = native_model::decode::<DotV1>(bytes.clone()).unwrap();
assert_eq!(dot, dot_decoded);
let (dot_decoded, _) = native_model::decode::<DotV2>(bytes.clone()).unwrap();
assert_eq!(
DotV2 {
name: "".to_string(),
x: 1,
y: 2
},
dot_decoded
);
let (dot_decoded, _) = native_model::decode::<DotV3>(bytes.clone()).unwrap();
assert_eq!(
DotV3 {
name: "".to_string(),
cord: Cord { x: 1, y: 2 }
},
dot_decoded
);
}
@@ -1,69 +0,0 @@
use bincode;
use bincode::{config, Decode, Encode};
use native_model::native_model;
pub struct Bincode;
impl<T: bincode::Encode> native_model::Encode<T> for Bincode {
type Error = bincode::error::EncodeError;
fn encode(obj: &T) -> Result<Vec<u8>, bincode::error::EncodeError> {
bincode::encode_to_vec(obj, config::standard())
}
}
impl<T: bincode::Decode> native_model::Decode<T> for Bincode {
type Error = bincode::error::DecodeError;
fn decode(data: Vec<u8>) -> Result<T, bincode::error::DecodeError> {
bincode::decode_from_slice(&data, config::standard()).map(|(result, _)| result)
}
}
#[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,
}
impl From<DotV1> for DotV2 {
fn from(dot: DotV1) -> Self {
DotV2 {
name: "".to_string(),
x: dot.0 as u64,
y: dot.1 as u64,
}
}
}
impl From<DotV2> for DotV1 {
fn from(dot: DotV2) -> Self {
DotV1(dot.x as u32, dot.y as u32)
}
}
#[test]
fn run_example() {
// Application 1
let dot = DotV1(1, 2);
let bytes = native_model::encode(&dot).unwrap();
// Application 1 sends bytes to Application 2.
// Application 2
let (mut dot, source_version) = native_model::decode::<DotV2>(bytes).unwrap();
// Use the struct DataV2 which has more fields and a different structure.
dot.name = "Dot".to_string();
dot.x = 5;
// Encode the dot with the application 1 version in order to be compatible with it.
let bytes = native_model::encode_downgrade(dot, source_version).unwrap();
// Application 2 sends bytes to Application 1.
// Application 1
let (dot, _) = native_model::decode::<DotV1>(bytes).unwrap();
assert_eq!(dot, DotV1(5, 2));
}
@@ -1,3 +0,0 @@
mod default_codec;
mod example_define_model;
mod example_main;
-51
View File
@@ -1,51 +0,0 @@
use bincode::{config, Decode, Encode};
use native_model::Model;
use native_model_macro::native_model;
pub struct Bincode;
impl<T: bincode::Encode> native_model::Encode<T> for Bincode {
type Error = bincode::error::EncodeError;
fn encode(obj: &T) -> Result<Vec<u8>, bincode::error::EncodeError> {
bincode::encode_to_vec(obj, config::standard())
}
}
impl<T: bincode::Decode> native_model::Decode<T> for Bincode {
type Error = bincode::error::DecodeError;
fn decode(data: Vec<u8>) -> Result<T, bincode::error::DecodeError> {
bincode::decode_from_slice(&data, config::standard()).map(|(result, _)| result)
}
}
#[derive(Debug, Encode, Decode)]
#[native_model(id = 1, version = 1, with = Bincode)]
struct Foo1 {
x: i32,
}
#[derive(Debug, Encode, Decode)]
#[native_model(id = 1, version = 2, with = Bincode, from = Foo1)]
struct Foo2 {
x: i32,
}
impl From<Foo1> for Foo2 {
fn from(foo1: Foo1) -> Self {
Foo2 { x: foo1.x }
}
}
impl From<Foo2> for Foo1 {
fn from(foo2: Foo2) -> Self {
Foo1 { x: foo2.x }
}
}
#[test]
fn test_simple() {
assert_eq!(Foo1::native_model_id(), 1);
assert_eq!(Foo1::native_model_version(), 1);
assert_eq!(Foo2::native_model_id(), 1);
assert_eq!(Foo2::native_model_version(), 2);
}
@@ -1,179 +0,0 @@
use bincode::{config, Decode, Encode};
use native_model::Model;
use native_model_macro::native_model;
pub struct Bincode;
impl<T: bincode::Encode> native_model::Encode<T> for Bincode {
type Error = bincode::error::EncodeError;
fn encode(obj: &T) -> Result<Vec<u8>, bincode::error::EncodeError> {
bincode::encode_to_vec(obj, config::standard())
}
}
impl<T: bincode::Decode> native_model::Decode<T> for Bincode {
type Error = bincode::error::DecodeError;
fn decode(data: Vec<u8>) -> Result<T, bincode::error::DecodeError> {
bincode::decode_from_slice(&data, config::standard()).map(|(result, _)| result)
}
}
#[derive(Debug, Encode, Decode, PartialEq)]
#[native_model(id = 1, version = 1, with = Bincode)]
struct Foo1 {
x: i32,
}
#[derive(Debug, Encode, Decode, PartialEq)]
#[native_model(id = 1, version = 2, with = Bincode, from = Foo1)]
struct Foo2 {
x: String,
}
impl From<Foo1> for Foo2 {
fn from(foo1: Foo1) -> Self {
Foo2 {
x: foo1.x.to_string(),
}
}
}
impl From<Foo2> for Foo1 {
fn from(foo2: Foo2) -> Self {
Foo1 {
x: foo2.x.parse::<i32>().unwrap(),
}
}
}
#[derive(Debug, Encode, Decode, PartialEq)]
#[native_model(id = 1, version = 3, with = Bincode, from = Foo2)]
enum Foo3 {
X(i32),
}
impl From<Foo2> for Foo3 {
fn from(foo2: Foo2) -> Self {
Foo3::X(foo2.x.parse::<i32>().unwrap())
}
}
impl From<Foo3> for Foo2 {
fn from(foo3: Foo3) -> Self {
match foo3 {
Foo3::X(x) => Foo2 { x: x.to_string() },
}
}
}
#[test]
fn test_decode_foo1_to_foo2() {
let foo1 = Foo1 { x: 100 };
let foo1_encoded = foo1.native_model_encode_body().unwrap();
let foo2_decoded = Foo2::native_model_decode_upgrade_body(foo1_encoded, 1, 1).unwrap();
assert_eq!(foo1.x.to_string(), foo2_decoded.x);
}
#[test]
fn test_decode_foo2_to_foo3() {
let foo2 = Foo2 {
x: "100".to_string(),
};
let foo2_encoded = foo2.native_model_encode_body().unwrap();
let foo3_decoded = Foo3::native_model_decode_upgrade_body(foo2_encoded, 1, 2).unwrap();
assert_eq!(Foo3::X(100), foo3_decoded);
}
#[test]
fn test_decode_foo1_to_foo3() {
let foo1 = Foo1 { x: 100 };
let foo1_encoded = foo1.native_model_encode_body().unwrap();
let foo3_decoded = Foo3::native_model_decode_upgrade_body(foo1_encoded, 1, 1).unwrap();
assert_eq!(Foo3::X(100), foo3_decoded);
}
#[test]
fn test_decode_foo1_to_foo1() {
let foo1 = Foo1 { x: 100 };
let foo1_encoded = foo1.native_model_encode_body().unwrap();
let foo1_decoded = Foo1::native_model_decode_upgrade_body(foo1_encoded, 1, 1).unwrap();
assert_eq!(foo1, foo1_decoded);
}
#[test]
fn test_decode_foo2_to_foo2() {
let foo2 = Foo2 {
x: "100".to_string(),
};
let foo2_encoded = foo2.native_model_encode_body().unwrap();
let foo2_decoded = Foo2::native_model_decode_upgrade_body(foo2_encoded, 1, 2).unwrap();
assert_eq!(foo2, foo2_decoded);
}
#[test]
fn test_decode_foo3_to_foo3() {
let foo3 = Foo3::X(100);
let foo3_encoded = foo3.native_model_encode_body().unwrap();
let foo3_decoded = Foo3::native_model_decode_upgrade_body(foo3_encoded, 1, 3).unwrap();
assert_eq!(foo3, foo3_decoded);
}
#[test]
fn test_should_fail_decode_foo3_to_foo2() {
let foo3 = Foo3::X(100);
let foo3_encoded = foo3.native_model_encode_body().unwrap();
let foo3_decoded = Foo2::native_model_decode_upgrade_body(foo3_encoded, 1, 3);
assert!(foo3_decoded.is_err());
assert!(matches!(
foo3_decoded.unwrap_err(),
native_model::Error::UpgradeNotSupported { from: 3, to: 2 }
));
}
#[test]
fn test_should_fail_decode_foo3_to_foo1() {
let foo3 = Foo3::X(100);
let foo3_encoded = foo3.native_model_encode_body().unwrap();
let foo3_decoded = Foo1::native_model_decode_upgrade_body(foo3_encoded, 1, 3);
assert!(foo3_decoded.is_err());
assert!(matches!(
foo3_decoded.unwrap_err(),
native_model::Error::UpgradeNotSupported { from: 3, to: 1 }
));
}
#[test]
fn test_should_fail_decode_foo2_to_foo1() {
let foo2 = Foo2 {
x: "100".to_string(),
};
let foo2_encoded = foo2.native_model_encode_body().unwrap();
let foo2_decoded = Foo1::native_model_decode_upgrade_body(foo2_encoded, 1, 2);
assert!(foo2_decoded.is_err());
assert!(matches!(
foo2_decoded.unwrap_err(),
native_model::Error::UpgradeNotSupported { from: 2, to: 1 }
));
}
#[derive(Debug, Encode, Decode, PartialEq)]
#[native_model(id = 2, version = 1, with = Bincode)]
struct Foo1Bis {
x: i32,
}
#[test]
fn test_prevent_to_decode_the_wrong_model() {
let foo1 = Foo1 { x: 100 };
let foo1_encoded = foo1.native_model_encode_body().unwrap();
let foo1_decoded = Foo1Bis::native_model_decode_upgrade_body(foo1_encoded, 1, 1);
dbg!(&foo1_decoded);
// assert!(foo1_decoded.is_err());
// assert!(matches!(
// foo1_decoded.unwrap_err(),
// native_model::Error::TypeIdMismatch {
// expected: 1,
// actual: 1
// }
// ));
}
@@ -1,56 +0,0 @@
use bincode::{config, Decode, Encode};
use native_model::Model;
use native_model_macro::native_model;
pub struct Bincode;
impl<T: bincode::Encode> native_model::Encode<T> for Bincode {
type Error = bincode::error::EncodeError;
fn encode(obj: &T) -> Result<Vec<u8>, bincode::error::EncodeError> {
bincode::encode_to_vec(obj, config::standard())
}
}
impl<T: bincode::Decode> native_model::Decode<T> for Bincode {
type Error = bincode::error::DecodeError;
fn decode(data: Vec<u8>) -> Result<T, bincode::error::DecodeError> {
bincode::decode_from_slice(&data, config::standard()).map(|(result, _)| result)
}
}
#[derive(Debug, Encode, Decode, PartialEq)]
#[native_model(id = 1, version = 1, with = Bincode)]
struct Foo1 {
x: i32,
}
#[derive(Debug, Encode, Decode, PartialEq)]
#[native_model(id = 1, version = 2, with = Bincode, from = Foo1)]
struct Foo2 {
x: i32,
}
impl From<Foo1> for Foo2 {
fn from(foo1: Foo1) -> Self {
Foo2 { x: foo1.x }
}
}
impl From<Foo2> for Foo1 {
fn from(foo2: Foo2) -> Self {
Foo1 { x: foo2.x }
}
}
#[test]
fn test_simple() {
let foo1 = Foo1 { x: 100 };
let foo2 = Foo2 { x: 200 };
let foo1_encoded = foo1.native_model_encode().unwrap();
let foo2_encoded = foo2.native_model_encode().unwrap();
let (foo1_decoded, _) = Foo1::native_model_decode(foo1_encoded).unwrap();
assert!(foo1_decoded == foo1);
let (foo2_decoded, _) = Foo2::native_model_decode(foo2_encoded).unwrap();
assert!(foo2_decoded == foo2);
}
@@ -1,107 +0,0 @@
use bincode::{config, Decode, Encode};
use native_model_macro::native_model;
pub struct Bincode;
impl<T: bincode::Encode> native_model::Encode<T> for Bincode {
type Error = bincode::error::EncodeError;
fn encode(obj: &T) -> Result<Vec<u8>, bincode::error::EncodeError> {
bincode::encode_to_vec(obj, config::standard())
}
}
impl<T: bincode::Decode> native_model::Decode<T> for Bincode {
type Error = bincode::error::DecodeError;
fn decode(data: Vec<u8>) -> Result<T, bincode::error::DecodeError> {
bincode::decode_from_slice(&data, config::standard()).map(|(result, _)| result)
}
}
#[derive(Debug, Encode, Decode, PartialEq)]
#[native_model(id = 1, version = 1, with = Bincode)]
struct Foo1 {
x: i32,
}
#[derive(Debug, Encode, Decode, PartialEq)]
#[native_model(id = 1, version = 2, with = Bincode, from = Foo1)]
struct Foo2 {
x: i32,
c: char,
}
impl From<Foo1> for Foo2 {
fn from(foo1: Foo1) -> Self {
Foo2 { x: foo1.x, c: 'a' }
}
}
impl From<Foo2> for Foo1 {
fn from(foo2: Foo2) -> Self {
Foo1 { x: foo2.x }
}
}
impl PartialEq<Foo1> for Foo2 {
fn eq(&self, other: &Foo1) -> bool {
self.x == other.x
}
}
#[test]
fn test_decode_foo1_to_foo1() {
let foo1 = Foo1 { x: 100 };
let foo1_packed = native_model::encode(&foo1).unwrap();
let (foo1_decoded, _) = native_model::decode::<Foo1>(foo1_packed.clone()).unwrap();
assert_eq!(foo1, foo1_decoded);
}
#[test]
fn test_decode_foo1_to_foo2() {
let foo1 = Foo1 { x: 100 };
let foo1_packed = native_model::encode(&foo1).unwrap();
let (foo2_decoded, _) = native_model::decode::<Foo2>(foo1_packed.clone()).unwrap();
assert_eq!(Foo2 { x: 100, c: 'a' }, foo2_decoded);
}
#[test]
fn test_encode_foo2_to_foo1() {
let foo2 = Foo2 { x: 100, c: 'a' };
let foo2_packed = native_model::encode(&foo2).unwrap();
assert_eq!(foo2_packed, vec![1, 0, 0, 0, 2, 0, 0, 0, 200, 97]);
let (foo2_decoded, _) = native_model::decode::<Foo2>(foo2_packed.clone()).unwrap();
assert_eq!(Foo2 { x: 100, c: 'a' }, foo2_decoded);
let foo1_packed = native_model::encode_downgrade(foo2, 1).unwrap();
assert_eq!(foo1_packed, vec![1, 0, 0, 0, 1, 0, 0, 0, 200]);
let (foo1_decoded, _) = native_model::decode::<Foo1>(foo1_packed.clone()).unwrap();
assert_eq!(Foo1 { x: 100 }, foo1_decoded);
}
#[test]
fn test_encode_foo1_to_foo1() {
let foo1 = Foo1 { x: 100 };
let foo1_packed = native_model::encode(&foo1).unwrap();
assert_eq!(foo1_packed, vec![1, 0, 0, 0, 1, 0, 0, 0, 200]);
let (foo1_decoded, _) = native_model::decode::<Foo1>(foo1_packed.clone()).unwrap();
assert_eq!(Foo1 { x: 100 }, foo1_decoded);
let foo1_packed = native_model::encode_downgrade(foo1, 1).unwrap();
assert_eq!(foo1_packed, vec![1, 0, 0, 0, 1, 0, 0, 0, 200]);
let (foo1_decoded, _) = native_model::decode::<Foo1>(foo1_packed.clone()).unwrap();
assert_eq!(Foo1 { x: 100 }, foo1_decoded);
}
#[test]
fn encode_decode_with_same_version() {
// Client 1
let foo1 = Foo1 { x: 100 };
let foo_packed = native_model::encode(&foo1).unwrap();
// Send foo_packed to server
// Server
let (mut foo2, version) = native_model::decode::<Foo2>(foo_packed.clone()).unwrap();
// Do something with foo2
foo2.x += 1;
let foo_packed = native_model::encode_downgrade(foo2, version).unwrap();
// Send foo_packed back to client
// Client
let (foo1_decoded, _) = native_model::decode::<Foo1>(foo_packed.clone()).unwrap();
assert_eq!(Foo1 { x: 101 }, foo1_decoded);
}
@@ -1,81 +0,0 @@
use bincode::{config, Decode, Encode};
use native_model_macro::native_model;
pub struct Bincode;
impl<T: bincode::Encode> native_model::Encode<T> for Bincode {
type Error = bincode::error::EncodeError;
fn encode(obj: &T) -> Result<Vec<u8>, bincode::error::EncodeError> {
bincode::encode_to_vec(obj, config::standard())
}
}
impl<T: bincode::Decode> native_model::Decode<T> for Bincode {
type Error = bincode::error::DecodeError;
fn decode(data: Vec<u8>) -> Result<T, bincode::error::DecodeError> {
bincode::decode_from_slice(&data, config::standard()).map(|(result, _)| result)
}
}
#[derive(Debug, Encode, Decode, PartialEq)]
#[native_model(id = 1, version = 1, with = Bincode)]
struct Foo1 {
x: i32,
}
#[derive(Debug, Encode, Decode, PartialEq)]
#[native_model(id = 1, version = 2, with = Bincode, try_from = (Foo1, anyhow::Error))]
struct Foo2 {
x: i32,
}
impl TryFrom<Foo1> for Foo2 {
type Error = anyhow::Error;
fn try_from(foo1: Foo1) -> Result<Self, Self::Error> {
if foo1.x > 10 {
return Err(anyhow::anyhow!("x > 10"));
}
Ok(Foo2 { x: foo1.x })
}
}
impl TryFrom<Foo2> for Foo1 {
type Error = anyhow::Error;
fn try_from(foo2: Foo2) -> Result<Self, Self::Error> {
if foo2.x > 10 {
return Err(anyhow::anyhow!("x > 10"));
}
Ok(Foo1 { x: foo2.x })
}
}
#[test]
fn test_foo1_to_foo1() {
let foo1 = Foo1 { x: 1 };
let foo1_packed = native_model::encode(&foo1).unwrap();
let (foo1_decoded, _) = native_model::decode::<Foo1>(foo1_packed.clone()).unwrap();
assert_eq!(foo1, foo1_decoded);
}
#[test]
fn test_foo1_to_foo2() {
let foo1 = Foo1 { x: 1 };
let foo1_packed = native_model::encode(&foo1).unwrap();
let (foo2_decoded, _) = native_model::decode::<Foo2>(foo1_packed.clone()).unwrap();
assert_eq!(Foo2 { x: 1 }, foo2_decoded);
}
#[test]
fn test_foo1_to_foo2_error() {
let foo1 = Foo1 { x: 1000 };
let foo1_packed = native_model::encode(&foo1).unwrap();
let foo2_decoded = native_model::decode::<Foo2>(foo1_packed.clone());
assert!(foo2_decoded.is_err());
assert!(matches!(
foo2_decoded.unwrap_err(),
native_model::Error::UpgradeError(_)
));
}