mirror of
https://github.com/Drop-OSS/drop.git
synced 2026-07-26 09:44:40 +10:00
feat: init
This commit is contained in:
@@ -0,0 +1,344 @@
|
||||
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>, x: u32) -> Result<Self> {
|
||||
println!(
|
||||
"A::deserialization_and_upgrade({}, {})",
|
||||
x,
|
||||
Self::native_model_version()
|
||||
);
|
||||
if x == Self::native_model_version() {
|
||||
Ok(Self {})
|
||||
} else if x < Self::native_model_version() {
|
||||
panic!("The version {} not supported", x);
|
||||
} 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>) -> DecodeResult<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
native_model_decode(data).map_err(|e| DecodeBodyError {
|
||||
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>, x: u32) -> Result<Self> {
|
||||
println!(
|
||||
"B::deserialization_and_upgrade({}, {})",
|
||||
x,
|
||||
Self::native_model_version()
|
||||
);
|
||||
if x == Self::native_model_version() {
|
||||
Ok(Self {})
|
||||
} else if x < Self::native_model_version() {
|
||||
A::native_model_decode_upgrade_body(_data, x).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>) -> DecodeResult<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
native_model_decode(data).map_err(|e| DecodeBodyError {
|
||||
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>, x: u32) -> Result<Self> {
|
||||
println!(
|
||||
"C::deserialization_and_upgrade({}, {})",
|
||||
x,
|
||||
Self::native_model_version()
|
||||
);
|
||||
if x == Self::native_model_version() {
|
||||
Ok(Self {})
|
||||
} else if x < Self::native_model_version() {
|
||||
let result = B::native_model_decode_upgrade_body(_data, x).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>) -> DecodeResult<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
native_model_decode(data).map_err(|e| DecodeBodyError {
|
||||
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 x = 3;
|
||||
let result = C::native_model_decode_upgrade_body(vec![], x);
|
||||
dbg!(&result);
|
||||
|
||||
let x = 2;
|
||||
let result = C::native_model_decode_upgrade_body(vec![], x);
|
||||
dbg!(&result);
|
||||
|
||||
let x = 1;
|
||||
let result = C::native_model_decode_upgrade_body(vec![], x);
|
||||
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, 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);
|
||||
}
|
||||
Reference in New Issue
Block a user