Updated to virtue 0.0.6, added #[bincode(crate = other)] attribute (#494)
* Updated to virtue 0.0.6, added #[bincode(crate = other)] attribute * Simplified the ContainerAttributes and FieldAttributes
This commit is contained in:
parent
d90f501872
commit
d4e7915c17
|
|
@ -16,4 +16,4 @@ description = "Implementation of #[derive(Encode, Decode)] for bincode"
|
|||
proc-macro = true
|
||||
|
||||
[dependencies]
|
||||
virtue = "0.0.4"
|
||||
virtue = "0.0.6"
|
||||
|
|
|
|||
|
|
@ -0,0 +1,74 @@
|
|||
use virtue::prelude::*;
|
||||
use virtue::utils::{parse_tagged_attribute, ParsedAttribute};
|
||||
|
||||
pub struct ContainerAttributes {
|
||||
pub crate_name: String,
|
||||
}
|
||||
|
||||
impl Default for ContainerAttributes {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
crate_name: "::bincode".to_string(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl FromAttribute for ContainerAttributes {
|
||||
fn parse(group: &Group) -> Result<Option<Self>> {
|
||||
let attributes = match parse_tagged_attribute(group, "bincode")? {
|
||||
Some(body) => body,
|
||||
None => return Ok(None),
|
||||
};
|
||||
let mut result = Self::default();
|
||||
for attribute in attributes {
|
||||
match attribute {
|
||||
ParsedAttribute::Property(key, val) if key.to_string() == "crate" => {
|
||||
let val_string = val.to_string();
|
||||
if val_string.starts_with('"') && val_string.ends_with('"') {
|
||||
result.crate_name = val_string[1..val_string.len() - 1].to_string();
|
||||
} else {
|
||||
return Err(Error::custom_at("Should be a literal str", val.span()));
|
||||
}
|
||||
}
|
||||
ParsedAttribute::Tag(i) => {
|
||||
return Err(Error::custom_at("Unknown field attribute", i.span()))
|
||||
}
|
||||
ParsedAttribute::Property(key, _) => {
|
||||
return Err(Error::custom_at("Unknown field attribute", key.span()))
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
Ok(Some(result))
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct FieldAttributes {
|
||||
pub with_serde: bool,
|
||||
}
|
||||
|
||||
impl FromAttribute for FieldAttributes {
|
||||
fn parse(group: &Group) -> Result<Option<Self>> {
|
||||
let attributes = match parse_tagged_attribute(group, "bincode")? {
|
||||
Some(body) => body,
|
||||
None => return Ok(None),
|
||||
};
|
||||
let mut result = Self::default();
|
||||
for attribute in attributes {
|
||||
match attribute {
|
||||
ParsedAttribute::Tag(i) if i.to_string() == "with_serde" => {
|
||||
result.with_serde = true;
|
||||
}
|
||||
ParsedAttribute::Tag(i) => {
|
||||
return Err(Error::custom_at("Unknown field attribute", i.span()))
|
||||
}
|
||||
ParsedAttribute::Property(key, _) => {
|
||||
return Err(Error::custom_at("Unknown field attribute", key.span()))
|
||||
}
|
||||
_ => {}
|
||||
}
|
||||
}
|
||||
Ok(Some(result))
|
||||
}
|
||||
}
|
||||
|
|
@ -1,12 +1,11 @@
|
|||
use super::FieldAttribute;
|
||||
use virtue::generate::{FnSelfArg, Generator, StreamBuilder};
|
||||
use virtue::parse::{EnumVariant, Fields};
|
||||
use crate::attribute::{ContainerAttributes, FieldAttributes};
|
||||
use virtue::prelude::*;
|
||||
|
||||
const TUPLE_FIELD_PREFIX: &str = "field_";
|
||||
|
||||
pub struct DeriveEnum {
|
||||
pub(crate) struct DeriveEnum {
|
||||
pub variants: Vec<EnumVariant>,
|
||||
pub attributes: ContainerAttributes,
|
||||
}
|
||||
|
||||
impl DeriveEnum {
|
||||
|
|
@ -19,18 +18,24 @@ impl DeriveEnum {
|
|||
}
|
||||
|
||||
pub fn generate_encode(self, generator: &mut Generator) -> Result<()> {
|
||||
let crate_name = self.attributes.crate_name.as_str();
|
||||
generator
|
||||
.impl_for("bincode::Encode")?
|
||||
.impl_for(format!("{}::Encode", crate_name))?
|
||||
.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, format!("{}::Encode", crate_name))
|
||||
.unwrap();
|
||||
}
|
||||
})
|
||||
.generate_fn("encode")
|
||||
.with_generic("E", ["bincode::enc::Encoder"])
|
||||
.with_generic_deps("E", [format!("{}::enc::Encoder", crate_name)])
|
||||
.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>",
|
||||
crate_name
|
||||
))
|
||||
.body(|fn_body| {
|
||||
fn_body.ident_str("match");
|
||||
fn_body.ident_str("self");
|
||||
|
|
@ -76,7 +81,7 @@ 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", crate_name))?;
|
||||
body.group(Delimiter::Parenthesis, |args| {
|
||||
args.punct('&');
|
||||
args.group(Delimiter::Parenthesis, |num| {
|
||||
|
|
@ -91,17 +96,22 @@ 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)? {
|
||||
let attributes = field_name
|
||||
.attributes()
|
||||
.get_attribute::<FieldAttributes>()?
|
||||
.unwrap_or_default();
|
||||
if attributes.with_serde {
|
||||
body.push_parsed(format!(
|
||||
"bincode::Encode::encode(&bincode::serde::Compat({}), encoder)?;",
|
||||
"{0}::Encode::encode(&{0}::serde::Compat({1}), encoder)?;",
|
||||
crate_name,
|
||||
field_name.to_string_with_prefix(TUPLE_FIELD_PREFIX),
|
||||
))?;
|
||||
} else {
|
||||
body.push_parsed(format!(
|
||||
"bincode::Encode::encode({}, encoder)?;",
|
||||
"{0}::Encode::encode({1}, encoder)?;",
|
||||
crate_name,
|
||||
field_name.to_string_with_prefix(TUPLE_FIELD_PREFIX),
|
||||
))
|
||||
?;
|
||||
))?;
|
||||
}
|
||||
}
|
||||
body.push_parsed("Ok(())")?;
|
||||
|
|
@ -124,6 +134,8 @@ impl DeriveEnum {
|
|||
|
||||
/// Build the catch-all case for an int-to-enum decode implementation
|
||||
fn invalid_variant_case(&self, enum_name: &str, result: &mut StreamBuilder) -> Result {
|
||||
let crate_name = self.attributes.crate_name.as_str();
|
||||
|
||||
// we'll be generating:
|
||||
// variant => Err(
|
||||
// bincode::error::DecodeError::UnexpectedVariant {
|
||||
|
|
@ -142,7 +154,10 @@ 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(format!(
|
||||
"{}::error::DecodeError::UnexpectedVariant",
|
||||
crate_name
|
||||
))?;
|
||||
err_inner.group(Delimiter::Brace, |variant_inner| {
|
||||
variant_inner.ident_str("found");
|
||||
variant_inner.punct(':');
|
||||
|
|
@ -159,7 +174,10 @@ 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(format!(
|
||||
"{}::error::AllowedEnumVariants::Allowed",
|
||||
crate_name
|
||||
))?;
|
||||
variant_inner.group(Delimiter::Parenthesis, |allowed_inner| {
|
||||
allowed_inner.punct('&');
|
||||
allowed_inner.group(Delimiter::Bracket, |allowed_slice| {
|
||||
|
|
@ -176,7 +194,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} }}",
|
||||
crate_name,
|
||||
self.variants.len() - 1
|
||||
))?;
|
||||
}
|
||||
|
|
@ -188,29 +207,35 @@ impl DeriveEnum {
|
|||
}
|
||||
|
||||
pub fn generate_decode(&self, generator: &mut Generator) -> Result<()> {
|
||||
let crate_name = self.attributes.crate_name.as_str();
|
||||
|
||||
// Remember to keep this mostly in sync with generate_borrow_decode
|
||||
|
||||
let enum_name = generator.target_name().to_string();
|
||||
|
||||
generator
|
||||
.impl_for("bincode::Decode")?
|
||||
.impl_for(format!("{}::Decode", crate_name))?
|
||||
.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, format!("{}::Decode", crate_name)).unwrap();
|
||||
}
|
||||
})
|
||||
.generate_fn("decode")
|
||||
.with_generic("D", ["bincode::de::Decoder"])
|
||||
.with_generic_deps("D", [format!("{}::de::Decoder", crate_name)])
|
||||
.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))
|
||||
.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
|
||||
))?;
|
||||
} 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
|
||||
))?;
|
||||
fn_builder.push_parsed("match variant_index")?;
|
||||
fn_builder.group(Delimiter::Brace, |variant_case| {
|
||||
for (mut variant_index, variant) in self.iter_fields() {
|
||||
|
|
@ -240,12 +265,19 @@ impl DeriveEnum {
|
|||
variant_body.ident(field.unwrap_ident().clone());
|
||||
}
|
||||
variant_body.punct(':');
|
||||
if field.attributes().has_attribute(FieldAttribute::WithSerde)? {
|
||||
let attributes = field.attributes().get_attribute::<FieldAttributes>()?.unwrap_or_default();
|
||||
if attributes.with_serde {
|
||||
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,",
|
||||
crate_name
|
||||
))?;
|
||||
} else {
|
||||
variant_body
|
||||
.push_parsed("bincode::Decode::decode(decoder)?,")?;
|
||||
.push_parsed(format!(
|
||||
"{}::Decode::decode(decoder)?,",
|
||||
crate_name
|
||||
))?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
|
@ -265,26 +297,30 @@ 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.attributes.crate_name.clone();
|
||||
|
||||
// Remember to keep this mostly in sync with generate_decode
|
||||
let enum_name = generator.target_name().to_string();
|
||||
|
||||
generator.impl_for_with_lifetimes("bincode::BorrowDecode", &["__de"])?
|
||||
generator.impl_for_with_lifetimes(format!("{}::BorrowDecode", crate_name), ["__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, format!("{}::enc::BorrowDecode", crate_name)).unwrap();
|
||||
}
|
||||
})
|
||||
.generate_fn("borrow_decode")
|
||||
.with_generic("D", ["bincode::de::BorrowDecoder<'__de>"])
|
||||
.with_generic_deps("D", [format!("{}::de::BorrowDecoder<'__de>", crate_name)])
|
||||
.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))
|
||||
.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
|
||||
))?;
|
||||
} 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))?;
|
||||
fn_builder.push_parsed("match variant_index")?;
|
||||
fn_builder.group(Delimiter::Brace, |variant_case| {
|
||||
for (mut variant_index, variant) in self.iter_fields() {
|
||||
|
|
@ -314,11 +350,12 @@ impl DeriveEnum {
|
|||
variant_body.ident(field.unwrap_ident().clone());
|
||||
}
|
||||
variant_body.punct(':');
|
||||
if field.attributes().has_attribute(FieldAttribute::WithSerde)? {
|
||||
let attributes = field.attributes().get_attribute::<FieldAttributes>()?.unwrap_or_default();
|
||||
if attributes.with_serde {
|
||||
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))?;
|
||||
} else {
|
||||
variant_body.push_parsed("bincode::BorrowDecode::borrow_decode(decoder)?,")?;
|
||||
variant_body.push_parsed(format!("{}::BorrowDecode::borrow_decode(decoder)?,", crate_name))?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
|
|
|
|||
|
|
@ -1,44 +1,50 @@
|
|||
use super::FieldAttribute;
|
||||
use crate::attribute::{ContainerAttributes, FieldAttributes};
|
||||
use virtue::generate::Generator;
|
||||
use virtue::parse::Fields;
|
||||
use virtue::prelude::*;
|
||||
|
||||
pub struct DeriveStruct {
|
||||
pub(crate) struct DeriveStruct {
|
||||
pub fields: Fields,
|
||||
pub attributes: ContainerAttributes,
|
||||
}
|
||||
|
||||
impl DeriveStruct {
|
||||
pub fn generate_encode(self, generator: &mut Generator) -> Result<()> {
|
||||
let DeriveStruct { fields } = self;
|
||||
let DeriveStruct { fields, attributes } = self;
|
||||
let crate_name = attributes.crate_name;
|
||||
|
||||
generator
|
||||
.impl_for("bincode::Encode")?
|
||||
.impl_for(&format!("{}::Encode", crate_name))?
|
||||
.modify_generic_constraints(|generics, where_constraints| {
|
||||
for g in generics.iter_generics() {
|
||||
where_constraints
|
||||
.push_constraint(g, "bincode::Encode")
|
||||
.push_constraint(g, format!("{}::Encode", crate_name))
|
||||
.unwrap();
|
||||
}
|
||||
})
|
||||
.generate_fn("encode")
|
||||
.with_generic("E", ["bincode::enc::Encoder"])
|
||||
.with_generic_deps("E", [format!("{}::enc::Encoder", crate_name)])
|
||||
.with_self_arg(virtue::generate::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>",
|
||||
crate_name
|
||||
))
|
||||
.body(|fn_body| {
|
||||
for field in fields.names() {
|
||||
if field
|
||||
let attributes = field
|
||||
.attributes()
|
||||
.has_attribute(FieldAttribute::WithSerde)?
|
||||
{
|
||||
.get_attribute::<FieldAttributes>()?
|
||||
.unwrap_or_default();
|
||||
if attributes.with_serde {
|
||||
fn_body.push_parsed(format!(
|
||||
"bincode::Encode::encode(&bincode::serde::Compat(&self.{}), encoder)?;",
|
||||
field
|
||||
"{0}::Encode::encode(&{0}::serde::Compat(&self.{1}), encoder)?;",
|
||||
crate_name, field
|
||||
))?;
|
||||
} else {
|
||||
fn_body.push_parsed(format!(
|
||||
"bincode::Encode::encode(&self.{}, encoder)?;",
|
||||
field
|
||||
"{}::Encode::encode(&self.{}, encoder)?;",
|
||||
crate_name, field
|
||||
))?;
|
||||
}
|
||||
}
|
||||
|
|
@ -50,19 +56,20 @@ impl DeriveStruct {
|
|||
|
||||
pub fn generate_decode(self, generator: &mut Generator) -> Result<()> {
|
||||
// Remember to keep this mostly in sync with generate_borrow_decode
|
||||
let DeriveStruct { fields } = self;
|
||||
let DeriveStruct { fields, attributes } = self;
|
||||
let crate_name = attributes.crate_name;
|
||||
|
||||
generator
|
||||
.impl_for("bincode::Decode")?
|
||||
.impl_for(format!("{}::Decode", crate_name))?
|
||||
.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, format!("{}::Decode", crate_name)).unwrap();
|
||||
}
|
||||
})
|
||||
.generate_fn("decode")
|
||||
.with_generic("D", ["bincode::de::Decoder"])
|
||||
.with_generic_deps("D", [format!("{}::de::Decoder", crate_name)])
|
||||
.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))
|
||||
.body(|fn_body| {
|
||||
// Ok(Self {
|
||||
fn_body.ident_str("Ok");
|
||||
|
|
@ -76,16 +83,19 @@ impl DeriveStruct {
|
|||
// ...
|
||||
// }
|
||||
for field in fields.names() {
|
||||
if field.attributes().has_attribute(FieldAttribute::WithSerde)? {
|
||||
let attributes = field.attributes().get_attribute::<FieldAttributes>()?.unwrap_or_default();
|
||||
if attributes.with_serde {
|
||||
struct_body
|
||||
.push_parsed(format!(
|
||||
"{}: (<bincode::serde::Compat<_> as bincode::Decode>::decode(decoder)?).0,",
|
||||
"{1}: (<{0}::serde::Compat<_> as {0}::Decode>::decode(decoder)?).0,",
|
||||
crate_name,
|
||||
field
|
||||
))?;
|
||||
} else {
|
||||
struct_body
|
||||
.push_parsed(format!(
|
||||
"{}: bincode::Decode::decode(decoder)?,",
|
||||
"{1}: {0}::Decode::decode(decoder)?,",
|
||||
crate_name,
|
||||
field
|
||||
))?;
|
||||
}
|
||||
|
|
@ -101,19 +111,20 @@ impl DeriveStruct {
|
|||
|
||||
pub fn generate_borrow_decode(self, generator: &mut Generator) -> Result<()> {
|
||||
// Remember to keep this mostly in sync with generate_decode
|
||||
let DeriveStruct { fields } = self;
|
||||
let DeriveStruct { fields, attributes } = self;
|
||||
let crate_name = attributes.crate_name;
|
||||
|
||||
generator
|
||||
.impl_for_with_lifetimes("bincode::BorrowDecode", &["__de"])?
|
||||
.impl_for_with_lifetimes(format!("{}::BorrowDecode", crate_name), ["__de"])?
|
||||
.modify_generic_constraints(|generics, where_constraints| {
|
||||
for g in generics.iter_generics() {
|
||||
where_constraints.push_constraint(g, "bincode::BorrowDecode").unwrap();
|
||||
where_constraints.push_constraint(g, format!("{}::BorrowDecode", crate_name)).unwrap();
|
||||
}
|
||||
})
|
||||
.generate_fn("borrow_decode")
|
||||
.with_generic("D", ["bincode::de::BorrowDecoder<'__de>"])
|
||||
.with_generic_deps("D", [format!("{}::de::BorrowDecoder<'__de>", crate_name)])
|
||||
.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))
|
||||
.body(|fn_body| {
|
||||
// Ok(Self {
|
||||
fn_body.ident_str("Ok");
|
||||
|
|
@ -121,16 +132,19 @@ impl DeriveStruct {
|
|||
ok_group.ident_str("Self");
|
||||
ok_group.group(Delimiter::Brace, |struct_body| {
|
||||
for field in fields.names() {
|
||||
if field.attributes().has_attribute(FieldAttribute::WithSerde)? {
|
||||
let attributes = field.attributes().get_attribute::<FieldAttributes>()?.unwrap_or_default();
|
||||
if attributes.with_serde {
|
||||
struct_body
|
||||
.push_parsed(format!(
|
||||
"{}: (<bincode::serde::BorrowCompat<_> as bincode::BorrowDecode>::borrow_decode(decoder)?).0,",
|
||||
"{1}: (<{0}::serde::BorrowCompat<_> as {0}::BorrowDecode>::borrow_decode(decoder)?).0,",
|
||||
crate_name,
|
||||
field
|
||||
))?;
|
||||
} else {
|
||||
struct_body
|
||||
.push_parsed(format!(
|
||||
"{}: bincode::BorrowDecode::borrow_decode(decoder)?,",
|
||||
"{1}: {0}::BorrowDecode::borrow_decode(decoder)?,",
|
||||
crate_name,
|
||||
field
|
||||
))?;
|
||||
}
|
||||
|
|
@ -139,7 +153,7 @@ impl DeriveStruct {
|
|||
})?;
|
||||
Ok(())
|
||||
})?;
|
||||
Ok(())
|
||||
Ok(())
|
||||
})?;
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,8 @@
|
|||
mod attribute;
|
||||
mod derive_enum;
|
||||
mod derive_struct;
|
||||
|
||||
use attribute::ContainerAttributes;
|
||||
use virtue::prelude::*;
|
||||
|
||||
#[proc_macro_derive(Encode, attributes(bincode))]
|
||||
|
|
@ -10,27 +12,30 @@ pub fn derive_encode(input: proc_macro::TokenStream) -> proc_macro::TokenStream
|
|||
|
||||
fn derive_encode_inner(input: TokenStream) -> Result<TokenStream> {
|
||||
let parse = Parse::new(input)?;
|
||||
let (mut generator, body) = parse.into_generator();
|
||||
let (mut generator, attributes, body) = parse.into_generator();
|
||||
let attributes = attributes
|
||||
.get_attribute::<ContainerAttributes>()?
|
||||
.unwrap_or_default();
|
||||
|
||||
match body {
|
||||
Body::Struct(body) => {
|
||||
derive_struct::DeriveStruct {
|
||||
fields: body.fields,
|
||||
attributes,
|
||||
}
|
||||
.generate_encode(&mut generator)?;
|
||||
}
|
||||
Body::Enum(body) => {
|
||||
derive_enum::DeriveEnum {
|
||||
variants: body.variants,
|
||||
attributes,
|
||||
}
|
||||
.generate_encode(&mut generator)?;
|
||||
}
|
||||
}
|
||||
|
||||
let name = generator.target_name().clone();
|
||||
let stream = generator.finish()?;
|
||||
dump_output(name, "Encode", &stream);
|
||||
Ok(stream)
|
||||
generator.export_to_file("Encode");
|
||||
generator.finish()
|
||||
}
|
||||
|
||||
#[proc_macro_derive(Decode, attributes(bincode))]
|
||||
|
|
@ -40,93 +45,61 @@ pub fn derive_decode(input: proc_macro::TokenStream) -> proc_macro::TokenStream
|
|||
|
||||
fn derive_decode_inner(input: TokenStream) -> Result<TokenStream> {
|
||||
let parse = Parse::new(input)?;
|
||||
let (mut generator, body) = parse.into_generator();
|
||||
let (mut generator, attributes, body) = parse.into_generator();
|
||||
let attributes = attributes
|
||||
.get_attribute::<ContainerAttributes>()?
|
||||
.unwrap_or_default();
|
||||
|
||||
match body {
|
||||
Body::Struct(body) => {
|
||||
derive_struct::DeriveStruct {
|
||||
fields: body.fields,
|
||||
attributes,
|
||||
}
|
||||
.generate_decode(&mut generator)?;
|
||||
}
|
||||
Body::Enum(body) => {
|
||||
derive_enum::DeriveEnum {
|
||||
variants: body.variants,
|
||||
attributes,
|
||||
}
|
||||
.generate_decode(&mut generator)?;
|
||||
}
|
||||
}
|
||||
|
||||
let name = generator.target_name().clone();
|
||||
let stream = generator.finish()?;
|
||||
dump_output(name, "Decode", &stream);
|
||||
Ok(stream)
|
||||
generator.export_to_file("Decode");
|
||||
generator.finish()
|
||||
}
|
||||
|
||||
#[proc_macro_derive(BorrowDecode, attributes(bincode))]
|
||||
pub fn derive_brrow_decode(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
pub fn derive_borrow_decode(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||
derive_borrow_decode_inner(input).unwrap_or_else(|e| e.into_token_stream())
|
||||
}
|
||||
|
||||
fn derive_borrow_decode_inner(input: TokenStream) -> Result<TokenStream> {
|
||||
let parse = Parse::new(input)?;
|
||||
let (mut generator, body) = parse.into_generator();
|
||||
let (mut generator, attributes, body) = parse.into_generator();
|
||||
let attributes = attributes
|
||||
.get_attribute::<ContainerAttributes>()?
|
||||
.unwrap_or_default();
|
||||
|
||||
match body {
|
||||
Body::Struct(body) => {
|
||||
derive_struct::DeriveStruct {
|
||||
fields: body.fields,
|
||||
attributes,
|
||||
}
|
||||
.generate_borrow_decode(&mut generator)?;
|
||||
}
|
||||
Body::Enum(body) => {
|
||||
derive_enum::DeriveEnum {
|
||||
variants: body.variants,
|
||||
attributes,
|
||||
}
|
||||
.generate_borrow_decode(&mut generator)?;
|
||||
}
|
||||
}
|
||||
|
||||
let name = generator.target_name().clone();
|
||||
let stream = generator.finish()?;
|
||||
dump_output(name, "BorrowDecode", &stream);
|
||||
Ok(stream)
|
||||
}
|
||||
|
||||
fn dump_output(name: Ident, derive: &str, stream: &TokenStream) {
|
||||
use std::io::Write;
|
||||
|
||||
if let Ok(var) = std::env::var("CARGO_MANIFEST_DIR") {
|
||||
let mut path = std::path::PathBuf::from(var);
|
||||
path.push("target");
|
||||
if path.exists() {
|
||||
path.push(format!("{}_{}.rs", name, derive));
|
||||
if let Ok(mut file) = std::fs::File::create(path) {
|
||||
let _ = file.write_all(stream.to_string().as_bytes());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
enum FieldAttribute {
|
||||
WithSerde,
|
||||
}
|
||||
|
||||
impl FromAttribute for FieldAttribute {
|
||||
fn parse(group: &Group) -> Result<Option<Self>> {
|
||||
let body = match virtue::utils::parse_tagged_attribute(group, "bincode") {
|
||||
Some(body) => body,
|
||||
None => return Ok(None),
|
||||
};
|
||||
match body.into_iter().next() {
|
||||
Some(TokenTree::Ident(ident)) if ident.to_string() == "with_serde" => {
|
||||
Ok(Some(Self::WithSerde))
|
||||
}
|
||||
token => Err(virtue::Error::custom_at_opt_token(
|
||||
"Unknown attribute, expected one of: \"with_serde\"",
|
||||
token,
|
||||
)),
|
||||
}
|
||||
}
|
||||
generator.export_to_file("BorrowDecode");
|
||||
generator.finish()
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,13 @@
|
|||
#![cfg(feature = "derive")]
|
||||
|
||||
extern crate bincode as bincode_new;
|
||||
|
||||
// Make sure that the `bincode` crate exists, just symlink it to `core.
|
||||
extern crate core as bincode;
|
||||
|
||||
#[derive(bincode_new::Encode)]
|
||||
#[bincode(crate = "bincode_new")]
|
||||
struct DeriveRenameTest {
|
||||
a: u32,
|
||||
b: u32,
|
||||
}
|
||||
Loading…
Reference in New Issue