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

Decode context #710

Draft
wants to merge 10 commits into
base: trunk
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ unty = "0.0.3"

# Used for tests
[dev-dependencies]
ouroboros = "0.18.3"
serde_derive = "1.0"
serde_json = { version = "1.0", default-features = false }
tempfile = "3.2"
Expand All @@ -47,6 +48,7 @@ chrono = { version = "0.4", features = ["serde"] }
glam = { version = "0.25", features = ["serde"] }
bincode_1 = { version = "1.3", package = "bincode" }
serde = { version = "1.0", features = ["derive"] }
bumpalo = { version = "3.16.0", features = ["collections"] }

[[bench]]
name = "varint"
Expand Down
4 changes: 2 additions & 2 deletions compatibility/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ 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
+ bincode_2::Decode<()>
+ serde::Serialize
+ serde::de::DeserializeOwned
+ core::fmt::Debug
Expand Down Expand Up @@ -60,7 +60,7 @@ where
pub fn test_same<T>(t: T)
where
T: bincode_2::Encode
+ bincode_2::Decode
+ bincode_2::Decode<()>
+ serde::Serialize
+ serde::de::DeserializeOwned
+ core::fmt::Debug
Expand Down
1 change: 1 addition & 0 deletions compatibility/src/sway.rs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ pub enum FTXresponse<T> {
Error(FTXresponseFailure),
}


#[derive(
bincode_2::Encode, bincode_2::Decode, serde::Serialize, serde::Deserialize, Debug, PartialEq, Eq,
)]
Expand Down
11 changes: 11 additions & 0 deletions derive/src/attribute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ pub struct ContainerAttributes {
pub crate_name: String,
pub bounds: Option<(String, Literal)>,
pub decode_bounds: Option<(String, Literal)>,
pub decode_context: Option<(String, Literal)>,
pub borrow_decode_bounds: Option<(String, Literal)>,
pub encode_bounds: Option<(String, Literal)>,
}
Expand All @@ -15,6 +16,7 @@ impl Default for ContainerAttributes {
crate_name: "::bincode".to_string(),
bounds: None,
decode_bounds: None,
decode_context: None,
encode_bounds: None,
borrow_decode_bounds: None,
}
Expand Down Expand Up @@ -56,6 +58,15 @@ impl FromAttribute for ContainerAttributes {
return Err(Error::custom_at("Should be a literal str", val.span()));
}
}
ParsedAttribute::Property(key, val) if key.to_string() == "decode_context" => {
let val_string = val.to_string();
if val_string.starts_with('"') && val_string.ends_with('"') {
result.decode_context =
Some((val_string[1..val_string.len() - 1].to_string(), val));
} else {
return Err(Error::custom_at("Should be a literal str", val.span()));
}
}
ParsedAttribute::Property(key, val) if key.to_string() == "encode_bounds" => {
let val_string = val.to_string();
if val_string.starts_with('"') && val_string.ends_with('"') {
Expand Down
50 changes: 37 additions & 13 deletions derive/src/derive_enum.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,25 +219,36 @@ impl DeriveEnum {
pub fn generate_decode(self, generator: &mut Generator) -> Result<()> {
let crate_name = self.attributes.crate_name.as_str();

let decode_context = if let Some((decode_context, _)) = &self.attributes.decode_context {
decode_context.as_str()
} else {
"__Context"
};
// Remember to keep this mostly in sync with generate_borrow_decode

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

generator
.impl_for(format!("{}::Decode", crate_name))
let mut impl_for = generator.impl_for(format!("{}::Decode", crate_name));

if self.attributes.decode_context.is_none() {
impl_for = impl_for.with_impl_generics(["__Context"]);
}

impl_for
.with_trait_generics([decode_context])
.modify_generic_constraints(|generics, where_constraints| {
if let Some((bounds, lit)) = (self.attributes.decode_bounds.as_ref()).or(self.attributes.bounds.as_ref()) {
where_constraints.clear();
where_constraints.push_parsed_constraint(bounds).map_err(|e| e.with_span(lit.span()))?;
} else {
for g in generics.iter_generics() {
where_constraints.push_constraint(g, format!("{}::Decode", crate_name))?;
where_constraints.push_constraint(g, format!("{}::Decode<__Context>", crate_name))?;
}
}
Ok(())
})?
.generate_fn("decode")
.with_generic_deps("__D", [format!("{}::de::Decoder", crate_name)])
.with_generic_deps("__D", [format!("{}::de::Decoder<Context = {}>", crate_name, decode_context)])
.with_arg("decoder", "&mut __D")
.with_return_type(format!("core::result::Result<Self, {}::error::DecodeError>", crate_name))
.body(|fn_builder| {
Expand All @@ -249,7 +260,7 @@ impl DeriveEnum {
} else {
fn_builder
.push_parsed(format!(
"let variant_index = <u32 as {}::Decode>::decode(decoder)?;",
"let variant_index = <u32 as {}::Decode::<__D::Context>>::decode(decoder)?;",
crate_name
))?;
fn_builder.push_parsed("match variant_index")?;
Expand Down Expand Up @@ -286,13 +297,13 @@ impl DeriveEnum {
if attributes.with_serde {
variant_body
.push_parsed(format!(
"<{0}::serde::Compat<_> as {0}::Decode>::decode(decoder)?.0,",
"<{0}::serde::Compat<_> as {0}::Decode::<__D::Context>>::decode(decoder)?.0,",
crate_name
))?;
} else {
variant_body
.push_parsed(format!(
"{}::Decode::decode(decoder)?,",
"{}::Decode::<__D::Context>::decode(decoder)?,",
crate_name
))?;
}
Expand All @@ -318,17 +329,30 @@ impl DeriveEnum {
pub fn generate_borrow_decode(self, generator: &mut Generator) -> Result<()> {
let crate_name = &self.attributes.crate_name;

let decode_context = if let Some((decode_context, _)) = &self.attributes.decode_context {
decode_context.as_str()
} else {
"__Context"
};

// Remember to keep this mostly in sync with generate_decode
let enum_name = generator.target_name().to_string();

generator.impl_for_with_lifetimes(format!("{}::BorrowDecode", crate_name), ["__de"])
let mut impl_for = generator
.impl_for_with_lifetimes(format!("{}::BorrowDecode", crate_name), ["__de"])
.with_trait_generics([decode_context]);
if self.attributes.decode_context.is_none() {
impl_for = impl_for.with_impl_generics(["__Context"]);
}

impl_for
.modify_generic_constraints(|generics, where_constraints| {
if let Some((bounds, lit)) = (self.attributes.borrow_decode_bounds.as_ref()).or(self.attributes.bounds.as_ref()) {
where_constraints.clear();
where_constraints.push_parsed_constraint(bounds).map_err(|e| e.with_span(lit.span()))?;
} else {
for g in generics.iter_generics() {
where_constraints.push_constraint(g, format!("{}::de::BorrowDecode<'__de>", crate_name)).unwrap();
where_constraints.push_constraint(g, format!("{}::de::BorrowDecode<'__de, {}>", crate_name, decode_context)).unwrap();
}
for lt in generics.iter_lifetimes() {
where_constraints.push_parsed_constraint(format!("'__de: '{}", lt.ident))?;
Expand All @@ -337,7 +361,7 @@ impl DeriveEnum {
Ok(())
})?
.generate_fn("borrow_decode")
.with_generic_deps("__D", [format!("{}::de::BorrowDecoder<'__de>", crate_name)])
.with_generic_deps("__D", [format!("{}::de::BorrowDecoder<'__de, Context = {}>", crate_name, decode_context)])
.with_arg("decoder", "&mut __D")
.with_return_type(format!("core::result::Result<Self, {}::error::DecodeError>", crate_name))
.body(|fn_builder| {
Expand All @@ -348,7 +372,7 @@ impl DeriveEnum {
))?;
} else {
fn_builder
.push_parsed(format!("let variant_index = <u32 as {}::Decode>::decode(decoder)?;", crate_name))?;
.push_parsed(format!("let variant_index = <u32 as {}::Decode::<__D::Context>>::decode(decoder)?;", crate_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 @@ -382,9 +406,9 @@ impl DeriveEnum {
let attributes = field.attributes().get_attribute::<FieldAttributes>()?.unwrap_or_default();
if attributes.with_serde {
variant_body
.push_parsed(format!("<{0}::serde::BorrowCompat<_> as {0}::BorrowDecode>::borrow_decode(decoder)?.0,", crate_name))?;
.push_parsed(format!("<{0}::serde::BorrowCompat<_> as {0}::BorrowDecode::<__D::Context>>::borrow_decode(decoder)?.0,", crate_name))?;
} else {
variant_body.push_parsed(format!("{}::BorrowDecode::borrow_decode(decoder)?,", crate_name))?;
variant_body.push_parsed(format!("{}::BorrowDecode::<__D::Context>::borrow_decode(decoder)?,", crate_name))?;
}
}
}
Expand Down
55 changes: 39 additions & 16 deletions derive/src/derive_struct.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,4 @@
use crate::attribute::{ContainerAttributes, FieldAttributes};
use virtue::generate::Generator;
use virtue::parse::Fields;
use virtue::prelude::*;

pub(crate) struct DeriveStruct {
Expand Down Expand Up @@ -67,22 +65,32 @@ impl DeriveStruct {
pub fn generate_decode(self, generator: &mut Generator) -> Result<()> {
// Remember to keep this mostly in sync with generate_borrow_decode
let crate_name = &self.attributes.crate_name;
let decode_context = if let Some((decode_context, _)) = &self.attributes.decode_context {
decode_context.as_str()
} else {
"__Context"
};

generator
.impl_for(format!("{}::Decode", crate_name))
let mut impl_for = generator.impl_for(format!("{}::Decode", crate_name));
if self.attributes.decode_context.is_none() {
impl_for = impl_for.with_impl_generics(["__Context"]);
}

impl_for
.with_trait_generics([decode_context])
.modify_generic_constraints(|generics, where_constraints| {
if let Some((bounds, lit)) = (self.attributes.decode_bounds.as_ref()).or(self.attributes.bounds.as_ref()) {
where_constraints.clear();
where_constraints.push_parsed_constraint(bounds).map_err(|e| e.with_span(lit.span()))?;
} else {
for g in generics.iter_generics() {
where_constraints.push_constraint(g, format!("{}::Decode", crate_name)).unwrap();
where_constraints.push_constraint(g, format!("{}::Decode<{}>", crate_name, decode_context)).unwrap();
}
}
Ok(())
})?
.generate_fn("decode")
.with_generic_deps("__D", [format!("{}::de::Decoder", crate_name)])
.with_generic_deps("__D", [format!("{}::de::Decoder<Context = {}>", crate_name, decode_context)])
.with_arg("decoder", "&mut __D")
.with_return_type(format!("core::result::Result<Self, {}::error::DecodeError>", crate_name))
.body(|fn_body| {
Expand All @@ -103,9 +111,10 @@ impl DeriveStruct {
if attributes.with_serde {
struct_body
.push_parsed(format!(
"{1}: (<{0}::serde::Compat<_> as {0}::Decode>::decode(decoder)?).0,",
"{1}: (<{0}::serde::Compat<_> as {0}::Decode::<{2}>>::decode(decoder)?).0,",
crate_name,
field
field,
decode_context,
))?;
} else {
struct_body
Expand All @@ -131,15 +140,27 @@ impl DeriveStruct {
// Remember to keep this mostly in sync with generate_decode
let crate_name = self.attributes.crate_name;

generator
.impl_for_with_lifetimes(format!("{}::BorrowDecode", crate_name), ["__de"])
let decode_context = if let Some((decode_context, _)) = &self.attributes.decode_context {
decode_context.as_str()
} else {
"__Context"
};

let mut impl_for =
generator.impl_for_with_lifetimes(format!("{}::BorrowDecode", crate_name), ["__de"]).with_trait_generics([decode_context]);
if self.attributes.decode_context.is_none() {
impl_for = impl_for.with_impl_generics(["__Context"]);
}

impl_for

.modify_generic_constraints(|generics, where_constraints| {
if let Some((bounds, lit)) = (self.attributes.borrow_decode_bounds.as_ref()).or(self.attributes.bounds.as_ref()) {
where_constraints.clear();
where_constraints.push_parsed_constraint(bounds).map_err(|e| e.with_span(lit.span()))?;
} else {
for g in generics.iter_generics() {
where_constraints.push_constraint(g, format!("{}::de::BorrowDecode<'__de>", crate_name)).unwrap();
where_constraints.push_constraint(g, format!("{}::de::BorrowDecode<'__de, {}>", crate_name, decode_context)).unwrap();
}
for lt in generics.iter_lifetimes() {
where_constraints.push_parsed_constraint(format!("'__de: '{}", lt.ident))?;
Expand All @@ -148,7 +169,7 @@ impl DeriveStruct {
Ok(())
})?
.generate_fn("borrow_decode")
.with_generic_deps("__D", [format!("{}::de::BorrowDecoder<'__de>", crate_name)])
.with_generic_deps("__D", [format!("{}::de::BorrowDecoder<'__de, Context = {}>", crate_name, decode_context)])
.with_arg("decoder", "&mut __D")
.with_return_type(format!("core::result::Result<Self, {}::error::DecodeError>", crate_name))
.body(|fn_body| {
Expand All @@ -163,16 +184,18 @@ impl DeriveStruct {
if attributes.with_serde {
struct_body
.push_parsed(format!(
"{1}: (<{0}::serde::BorrowCompat<_> as {0}::BorrowDecode>::borrow_decode(decoder)?).0,",
"{1}: (<{0}::serde::BorrowCompat<_> as {0}::BorrowDecode::<'_, {2}>>::borrow_decode(decoder)?).0,",
crate_name,
field
field,
decode_context,
))?;
} else {
struct_body
.push_parsed(format!(
"{1}: {0}::BorrowDecode::borrow_decode(decoder)?,",
"{1}: {0}::BorrowDecode::<'_, {2}>::borrow_decode(decoder)?,",
crate_name,
field
field,
decode_context,
))?;
}
}
Expand Down
Loading