Skip to content

Commit

Permalink
Moved compatibility to the /compatibility/ crate, made bincode-derive…
Browse files Browse the repository at this point in the history
… support `#[bincode(crate = "bincode_2")]`
  • Loading branch information
VictorKoenders committed Jan 23, 2022
1 parent 3cb6061 commit 077fc7f
Show file tree
Hide file tree
Showing 10 changed files with 340 additions and 127 deletions.
4 changes: 2 additions & 2 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
[workspace]
members = [
"derive"
"derive",
"compatibility"
]

[package]
Expand Down Expand Up @@ -51,7 +52,6 @@ criterion = "0.3"
rand = "0.8"
uuid = { version = "0.8", features = ["serde"] }
chrono = { version = "0.4", features = ["serde"] }
bincode1 = { version = "1.0", package = "bincode" }

[[bench]]
name = "varint"
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"
64 changes: 64 additions & 0 deletions compatibility/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#![cfg(test)]

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 + serde::Serialize + core::fmt::Debug,
C: bincode_2::config::Config + Clone,
O: bincode_1::Options + Clone,
{
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
);
}

pub fn test_same<T>(t: T)
where
T: bincode_2::Encode + serde::Serialize + core::fmt::Debug,
{
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(),
);
}
22 changes: 22 additions & 0 deletions compatibility/src/rand.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
// Simplified case, taken from:
// https://github.com/rust-random/rand/blob/19404d68764ed08513131f82157e2ccad69dcf83/rand_pcg/src/pcg64.rs#L37-L40

use rand::Rng;

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

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

use serde::{Deserialize, Serialize};

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

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

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

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

#[derive(bincode_2::Encode, bincode_2::Decode, Serialize, Deserialize, Debug)]
#[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,
}
2 changes: 1 addition & 1 deletion derive/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -16,4 +16,4 @@ description = "Implementation of #[derive(Encode, Decode)] for bincode"
proc-macro = true

[dependencies]
virtue = "0.0.4"
virtue = "0.0.5"
94 changes: 62 additions & 32 deletions derive/src/derive_enum.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
use super::FieldAttribute;
use crate::CrateNameAttribute;
use virtue::generate::{FnSelfArg, Generator, StreamBuilder};
use virtue::parse::{EnumVariant, Fields};
use virtue::prelude::*;

const TUPLE_FIELD_PREFIX: &str = "field_";

pub struct DeriveEnum {
pub(crate) struct DeriveEnum {
pub variants: Vec<EnumVariant>,
pub crate_name: CrateNameAttribute,
}

impl DeriveEnum {
Expand All @@ -20,17 +22,22 @@ impl DeriveEnum {

pub fn generate_encode(self, generator: &mut Generator) -> Result<()> {
generator
.impl_for("bincode::Encode")?
.impl_for(self.crate_name.ty("Encode"))?
.modify_generic_constraints(|generics, where_constraints| {
for g in generics.iter_generics() {
where_constraints.push_constraint(g, "bincode::Encode").unwrap();
where_constraints
.push_constraint(g, self.crate_name.ty("Encode"))
.unwrap();
}
})
.generate_fn("encode")
.with_generic("E", ["bincode::enc::Encoder"])
.with_generic_deps("E", [self.crate_name.ty("enc::Encoder")])
.with_self_arg(FnSelfArg::RefSelf)
.with_arg("encoder", "&mut E")
.with_return_type("core::result::Result<(), bincode::error::EncodeError>")
.with_return_type(format!(
"core::result::Result<(), {}::error::EncodeError>",
self.crate_name.name
))
.body(|fn_body| {
fn_body.ident_str("match");
fn_body.ident_str("self");
Expand Down Expand Up @@ -76,7 +83,10 @@ impl DeriveEnum {
// }
match_body.group(Delimiter::Brace, |body| {
// variant index
body.push_parsed("<u32 as bincode::Encode>::encode")?;
body.push_parsed(format!(
"<u32 as {}::Encode>::encode",
self.crate_name.name
))?;
body.group(Delimiter::Parenthesis, |args| {
args.punct('&');
args.group(Delimiter::Parenthesis, |num| {
Expand All @@ -91,17 +101,21 @@ impl DeriveEnum {
body.punct(';');
// If we have any fields, encode them all one by one
for field_name in variant.fields.names() {
if field_name.attributes().has_attribute(FieldAttribute::WithSerde)? {
if field_name
.attributes()
.has_attribute(FieldAttribute::WithSerde)?
{
body.push_parsed(format!(
"bincode::Encode::encode(&bincode::serde::Compat({}), encoder)?;",
"{0}::Encode::encode(&{0}::serde::Compat({1}), encoder)?;",
self.crate_name.name,
field_name.to_string_with_prefix(TUPLE_FIELD_PREFIX),
))?;
} else {
body.push_parsed(format!(
"bincode::Encode::encode({}, encoder)?;",
"{0}::Encode::encode({1}, encoder)?;",
self.crate_name.name,
field_name.to_string_with_prefix(TUPLE_FIELD_PREFIX),
))
?;
))?;
}
}
body.push_parsed("Ok(())")?;
Expand Down Expand Up @@ -142,7 +156,7 @@ impl DeriveEnum {
result.puncts("=>");
result.ident_str("Err");
result.group(Delimiter::Parenthesis, |err_inner| {
err_inner.push_parsed("bincode::error::DecodeError::UnexpectedVariant")?;
err_inner.push_parsed(self.crate_name.ty("error::DecodeError::UnexpectedVariant"))?;
err_inner.group(Delimiter::Brace, |variant_inner| {
variant_inner.ident_str("found");
variant_inner.punct(':');
Expand All @@ -159,7 +173,8 @@ impl DeriveEnum {

if self.variants.iter().any(|i| i.has_fixed_value()) {
// we have fixed values, implement AllowedEnumVariants::Allowed
variant_inner.push_parsed("bincode::error::AllowedEnumVariants::Allowed")?;
variant_inner
.push_parsed(self.crate_name.ty("error::AllowedEnumVariants::Allowed"))?;
variant_inner.group(Delimiter::Parenthesis, |allowed_inner| {
allowed_inner.punct('&');
allowed_inner.group(Delimiter::Bracket, |allowed_slice| {
Expand All @@ -176,7 +191,8 @@ impl DeriveEnum {
} else {
// no fixed values, implement a range
variant_inner.push_parsed(format!(
"bincode::error::AllowedEnumVariants::Range {{ min: 0, max: {} }}",
"{0}::error::AllowedEnumVariants::Range {{ min: 0, max: {1} }}",
self.crate_name.name,
self.variants.len() - 1
))?;
}
Expand All @@ -193,24 +209,28 @@ impl DeriveEnum {
let enum_name = generator.target_name().to_string();

generator
.impl_for("bincode::Decode")?
.impl_for(self.crate_name.ty("Decode"))?
.modify_generic_constraints(|generics, where_constraints| {
for g in generics.iter_generics() {
where_constraints.push_constraint(g, "bincode::Decode").unwrap();
where_constraints.push_constraint(g, self.crate_name.ty("Decode")).unwrap();
}
})
.generate_fn("decode")
.with_generic("D", ["bincode::de::Decoder"])
.with_generic_deps("D", [self.crate_name.ty("de::Decoder")])
.with_arg("decoder", "&mut D")
.with_return_type("core::result::Result<Self, bincode::error::DecodeError>")
.with_return_type(format!("core::result::Result<Self, {}::error::DecodeError>", self.crate_name.name))
.body(|fn_builder| {
if self.variants.is_empty() {
fn_builder.push_parsed("core::result::Result::Err(bincode::error::DecodeError::EmptyEnum { type_name: core::any::type_name::<Self>() })")?;
fn_builder.push_parsed(format!(
"core::result::Result::Err({}::error::DecodeError::EmptyEnum {{ type_name: core::any::type_name::<Self>() }})",
self.crate_name.name
))?;
} else {
fn_builder
.push_parsed(
"let variant_index = <u32 as bincode::Decode>::decode(decoder)?;",
)?;
.push_parsed(format!(
"let variant_index = <u32 as {}::Decode>::decode(decoder)?;",
self.crate_name.name
))?;
fn_builder.push_parsed("match variant_index")?;
fn_builder.group(Delimiter::Brace, |variant_case| {
for (mut variant_index, variant) in self.iter_fields() {
Expand Down Expand Up @@ -242,10 +262,16 @@ impl DeriveEnum {
variant_body.punct(':');
if field.attributes().has_attribute(FieldAttribute::WithSerde)? {
variant_body
.push_parsed("<bincode::serde::Compat<_> as bincode::Decode>::decode(decoder)?.0,")?;
.push_parsed(format!(
"<{0}::serde::Compat<_> as {0}::Decode>::decode(decoder)?.0,",
self.crate_name.name
))?;
} else {
variant_body
.push_parsed("bincode::Decode::decode(decoder)?,")?;
.push_parsed(format!(
"{}::Decode::decode(decoder)?,",
self.crate_name.name
))?;
}
}
Ok(())
Expand All @@ -266,25 +292,29 @@ impl DeriveEnum {

pub fn generate_borrow_decode(self, generator: &mut Generator) -> Result<()> {
// Remember to keep this mostly in sync with generate_decode
let crate_name = &self.crate_name;

let enum_name = generator.target_name().to_string();

generator.impl_for_with_lifetimes("bincode::BorrowDecode", &["__de"])?
generator.impl_for_with_lifetimes(crate_name.ty("BorrowDecode"), ["__de"])?
.modify_generic_constraints(|generics, where_constraints| {
for g in generics.iter_generics() {
where_constraints.push_constraint(g, "bincode::enc::BorrowDecode").unwrap();
where_constraints.push_constraint(g, crate_name.ty("enc::BorrowDecode")).unwrap();
}
})
.generate_fn("borrow_decode")
.with_generic("D", ["bincode::de::BorrowDecoder<'__de>"])
.with_generic_deps("D", [crate_name.ty("de::BorrowDecoder<'__de>")])
.with_arg("decoder", "&mut D")
.with_return_type("core::result::Result<Self, bincode::error::DecodeError>")
.with_return_type(format!("core::result::Result<Self, {}::error::DecodeError>", crate_name.name))
.body(|fn_builder| {
if self.variants.is_empty() {
fn_builder.push_parsed("core::result::Result::Err(bincode::error::DecodeError::EmptyEnum { type_name: core::any::type_name::<Self>() })")?;
fn_builder.push_parsed(format!(
"core::result::Result::Err({}::error::DecodeError::EmptyEnum {{ type_name: core::any::type_name::<Self>() }})",
crate_name.name
))?;
} else {
fn_builder
.push_parsed("let variant_index = <u32 as bincode::Decode>::decode(decoder)?;")?;
.push_parsed(format!("let variant_index = <u32 as {}::Decode>::decode(decoder)?;", crate_name.name))?;
fn_builder.push_parsed("match variant_index")?;
fn_builder.group(Delimiter::Brace, |variant_case| {
for (mut variant_index, variant) in self.iter_fields() {
Expand Down Expand Up @@ -316,9 +346,9 @@ impl DeriveEnum {
variant_body.punct(':');
if field.attributes().has_attribute(FieldAttribute::WithSerde)? {
variant_body
.push_parsed("<bincode::serde::BorrowCompat<_> as bincode::BorrowDecode>::borrow_decode(decoder)?.0,")?;
.push_parsed(format!("<{0}::serde::BorrowCompat<_> as {0}::BorrowDecode>::borrow_decode(decoder)?.0,", crate_name.name))?;
} else {
variant_body.push_parsed("bincode::BorrowDecode::borrow_decode(decoder)?,")?;
variant_body.push_parsed(format!("{}::BorrowDecode::borrow_decode(decoder)?,", crate_name.name))?;
}
}
Ok(())
Expand Down
Loading

0 comments on commit 077fc7f

Please sign in to comment.