Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bincode 1 compatibility framework #489

Merged
merged 7 commits into from
Feb 1, 2022
3 changes: 2 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[workspace]
members = [
"derive"
"derive",
"compatibility"
]

[package]
Expand Down
12 changes: 12 additions & 0 deletions compatibility/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[package]
name = "bincode_compatibility"
version = "0.1.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
bincode_2 = { path = "..", package = "bincode" }
bincode_1 = { version = "1", package = "bincode" }
serde = { version = "1", features = ["derive"] }
rand = "0.8"
107 changes: 107 additions & 0 deletions compatibility/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,107 @@
#![cfg(test)]

use ::rand::Rng;
use bincode_1::Options;

mod rand;
mod sway;

pub fn test_same_with_config<T, C, O>(t: &T, bincode_1_options: O, bincode_2_config: C)
where
T: bincode_2::Encode
+ bincode_2::Decode
+ serde::Serialize
+ serde::de::DeserializeOwned
+ core::fmt::Debug
+ PartialEq,
C: bincode_2::config::Config,
O: bincode_1::Options + Copy,
{
let bincode_1_output = bincode_1_options.serialize(t).unwrap();
let bincode_2_output = bincode_2::encode_to_vec(t, bincode_2_config).unwrap();

assert_eq!(
bincode_1_output, bincode_2_output,
"{:?} serializes differently",
t
);

let decoded: T = bincode_1_options.deserialize(&bincode_1_output).unwrap();
VictorKoenders marked this conversation as resolved.
Show resolved Hide resolved
assert_eq!(&decoded, t);
let decoded: T = bincode_1_options.deserialize(&bincode_2_output).unwrap();
assert_eq!(&decoded, t);

let decoded: T = bincode_2::decode_from_slice(&bincode_1_output, bincode_2_config)
.unwrap()
.0;
assert_eq!(&decoded, t);
let decoded: T = bincode_2::decode_from_slice(&bincode_2_output, bincode_2_config)
.unwrap()
.0;
assert_eq!(&decoded, t);
}

pub fn test_same<T>(t: T)
where
T: bincode_2::Encode
+ bincode_2::Decode
+ serde::Serialize
+ serde::de::DeserializeOwned
+ core::fmt::Debug
+ PartialEq,
{
test_same_with_config(
VictorKoenders marked this conversation as resolved.
Show resolved Hide resolved
&t,
// This is the config used internally by bincode 1
bincode_1::options().with_fixint_encoding(),
// Should match `::legacy()`
bincode_2::config::legacy(),
);

// Check a bunch of different configs:
test_same_with_config(
&t,
bincode_1::options()
.with_big_endian()
.with_varint_encoding(),
bincode_2::config::legacy()
.with_big_endian()
.with_variable_int_encoding(),
);
test_same_with_config(
&t,
bincode_1::options()
.with_little_endian()
.with_varint_encoding(),
bincode_2::config::legacy()
.with_little_endian()
.with_variable_int_encoding(),
);
test_same_with_config(
&t,
bincode_1::options()
.with_big_endian()
.with_fixint_encoding(),
bincode_2::config::legacy()
.with_big_endian()
.with_fixed_int_encoding(),
);
test_same_with_config(
&t,
bincode_1::options()
.with_little_endian()
.with_fixint_encoding(),
bincode_2::config::legacy()
.with_little_endian()
.with_fixed_int_encoding(),
);
}

pub fn gen_string(rng: &mut impl Rng) -> String {
let len = rng.gen_range(0..100usize);
let mut result = String::with_capacity(len * 4);
for _ in 0..len {
result.push(rng.gen_range('\0'..char::MAX));
}
result
}
25 changes: 25 additions & 0 deletions compatibility/src/rand.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
// Simplified case, taken from:
// https://github.com/rust-random/rand/blob/19404d68764ed08513131f82157e2ccad69dcf83/rand_pcg/src/pcg64.rs#L37-L40
VictorKoenders marked this conversation as resolved.
Show resolved Hide resolved
// Original license: MIT OR Apache-2.0

use rand::Rng;

#[derive(
Debug, bincode_2::Encode, bincode_2::Decode, serde::Serialize, serde::Deserialize, PartialEq,
)]
#[bincode(crate = "bincode_2")]
pub struct Lcg64Xsh32 {
state: u64,
increment: u64,
}

#[test]
pub fn test() {
let mut rng = rand::thread_rng();
for _ in 0..1000 {
crate::test_same(Lcg64Xsh32 {
state: rng.gen(),
increment: rng.gen(),
});
}
}
85 changes: 85 additions & 0 deletions compatibility/src/sway.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,85 @@
// Credits to Sway in the Rust Programming Language
ZoeyR marked this conversation as resolved.
Show resolved Hide resolved

use rand::Rng;
use serde::{Deserialize, Serialize};

#[test]
pub fn test() {
let mut rng = rand::thread_rng();
for _ in 0..1000 {
crate::test_same(random(&mut rng));
}
}

fn random(rng: &mut impl Rng) -> FTXresponse<Trade> {
if rng.gen() {
FTXresponse::Result(FTXresponseSuccess {
result: Trade::random(rng),
success: rng.gen(),
})
} else {
FTXresponse::Error(FTXresponseFailure {
success: rng.gen(),
error: crate::gen_string(rng),
})
}
}

#[derive(bincode_2::Encode, bincode_2::Decode, Serialize, Deserialize, Debug, PartialEq)]
#[bincode(crate = "bincode_2")]
pub enum FTXresponse<T> {
Result(FTXresponseSuccess<T>),
Error(FTXresponseFailure),
}

#[derive(
bincode_2::Encode, bincode_2::Decode, serde::Serialize, serde::Deserialize, Debug, PartialEq,
)]
#[bincode(crate = "bincode_2")]
pub struct FTXresponseSuccess<T> {
pub success: bool,
pub result: T,
}

#[derive(bincode_2::Encode, bincode_2::Decode, Serialize, Deserialize, Debug, PartialEq)]
#[bincode(crate = "bincode_2")]
pub struct FTXresponseFailure {
pub success: bool,
pub error: String,
}

#[derive(bincode_2::Encode, bincode_2::Decode, Serialize, Deserialize, Debug, PartialEq)]
#[bincode(crate = "bincode_2")]
pub enum TradeSide {
Buy,
Sell,
}

#[derive(bincode_2::Encode, bincode_2::Decode, Serialize, Deserialize, Debug, PartialEq)]
#[bincode(crate = "bincode_2")]
#[serde(rename_all = "camelCase")]
pub struct Trade {
pub id: u64,
pub liquidation: bool,
pub price: f64,
pub side: TradeSide,
pub size: f64,
pub time: String,
}

impl Trade {
fn random(rng: &mut impl Rng) -> Self {
Self {
id: rng.gen(),
liquidation: rng.gen(),
price: rng.gen(),
side: if rng.gen() {
TradeSide::Buy
} else {
TradeSide::Sell
},
size: rng.gen(),
time: crate::gen_string(rng),
}
}
}