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

feat: add #[bitcode(crate = "...")] for crate alias #28

Merged
merged 2 commits into from
Jul 14, 2024
Merged
Show file tree
Hide file tree
Changes from 1 commit
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
32 changes: 31 additions & 1 deletion bitcode_derive/src/attribute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use syn::{parse2, Attribute, Expr, ExprLit, Lit, Meta, Path, Result, Token, Type

enum BitcodeAttr {
BoundType(Type),
CrateAlias(Path),
}

impl BitcodeAttr {
Expand All @@ -30,6 +31,22 @@ impl BitcodeAttr {
}
_ => err(&nested, "expected name value"),
},
"crate" => match nested {
Meta::NameValue(name_value) => {
let expr = &name_value.value;
let str_lit = match expr {
Expr::Lit(ExprLit {
lit: Lit::Str(v), ..
}) => v,
_ => return err(&expr, "expected path string e.g. \"my_crate::bitcode\""),
};

let path = syn::parse_str(&str_lit.value())
.map_err(|e| error(str_lit, &e.to_string()))?;
Ok(Self::CrateAlias(path))
}
_ => err(&nested, "expected name value"),
},
_ => err(&nested, "unknown attribute"),
}
}
Expand All @@ -47,13 +64,23 @@ impl BitcodeAttr {
err(nested, "can only apply bound to fields")
}
}
Self::CrateAlias(crate_name) => {
if let AttrType::Derive = attrs.attr_type {
attrs.crate_name = crate_name;
Ok(())
} else {
err(nested, "can only apply crate rename to derives")
}
}
}
}
}

#[derive(Clone)]
pub struct BitcodeAttrs {
attr_type: AttrType,
/// The crate name to use for the generated code, defaults to "bitcode".
pub crate_name: Path,
}

#[derive(Clone)]
Expand All @@ -65,7 +92,10 @@ enum AttrType {

impl BitcodeAttrs {
fn new(attr_type: AttrType) -> Self {
Self { attr_type }
Self {
attr_type,
crate_name: syn::parse_str("bitcode").expect("invalid crate name"),
}
}

pub fn bound_type(&self) -> Option<Type> {
Expand Down
17 changes: 10 additions & 7 deletions bitcode_derive/src/decode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ impl Item {
impl crate::shared::Item for Item {
fn field_impl(
self,
crate_name: &Path,
field_name: TokenStream,
global_field_name: TokenStream,
real_field_name: TokenStream,
Expand All @@ -43,7 +44,7 @@ impl crate::shared::Item for Item {
match self {
Self::Type => {
let de_type = replace_lifetimes(field_type, DE_LIFETIME);
let private = private();
let private = private(crate_name);
let de = de_lifetime();
quote! {
#global_field_name: <#de_type as #private::Decode<#de>>::Decoder,
Expand All @@ -61,7 +62,7 @@ impl crate::shared::Item for Item {
},
Self::DecodeInPlace => {
let de_type = replace_lifetimes(field_type, DE_LIFETIME);
let private = private();
let private = private(crate_name);
quote! {
self.#global_field_name.decode_in_place(#private::uninit_field!(out.#real_field_name: #de_type));
}
Expand All @@ -83,6 +84,7 @@ impl crate::shared::Item for Item {

fn enum_impl(
self,
crate_name: &Path,
variant_count: usize,
pattern: impl Fn(usize) -> TokenStream,
inner: impl Fn(Self, usize) -> TokenStream,
Expand All @@ -97,7 +99,7 @@ impl crate::shared::Item for Item {
let inners: TokenStream = (0..variant_count).map(|i| inner(self, i)).collect();
let variants = decode_variants
.then(|| {
let private = private();
let private = private(crate_name);
let c_style = inners.is_empty();
quote! { variants: #private::VariantDecoder<#de, #variant_count, #c_style>, }
})
Expand All @@ -119,7 +121,7 @@ impl crate::shared::Item for Item {
}
Self::Populate => {
if never {
let private = private();
let private = private(crate_name);
return quote! {
if __length != 0 {
return #private::invalid_enum_variant();
Expand Down Expand Up @@ -220,14 +222,15 @@ impl crate::shared::Derive<{ Item::COUNT }> for Decode {
type Item = Item;
const ALL: [Self::Item; Item::COUNT] = Item::ALL;

fn bound(&self) -> Path {
let private = private();
fn bound(&self, crate_name: &Path) -> Path {
let private = private(crate_name);
let de = de_lifetime();
parse_quote!(#private::Decode<#de>)
}

fn derive_impl(
&self,
crate_name: &Path,
output: [TokenStream; Item::COUNT],
ident: Ident,
mut generics: Generics,
Expand Down Expand Up @@ -281,7 +284,7 @@ impl crate::shared::Derive<{ Item::COUNT }> for Decode {

let decoder_ident = Ident::new(&format!("{ident}Decoder"), Span::call_site());
let decoder_ty = quote! { #decoder_ident #decoder_generics };
let private = private();
let private = private(crate_name);

quote! {
const _: () = {
Expand Down
13 changes: 8 additions & 5 deletions bitcode_derive/src/encode.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,7 @@ impl Item {
impl crate::shared::Item for Item {
fn field_impl(
self,
crate_name: &Path,
field_name: TokenStream,
global_field_name: TokenStream,
real_field_name: TokenStream,
Expand All @@ -35,7 +36,7 @@ impl crate::shared::Item for Item {
match self {
Self::Type => {
let static_type = replace_lifetimes(field_type, "static");
let private = private();
let private = private(crate_name);
quote! {
#global_field_name: <#static_type as #private::Encode>::Encoder,
}
Expand Down Expand Up @@ -99,6 +100,7 @@ impl crate::shared::Item for Item {

fn enum_impl(
self,
crate_name: &Path,
variant_count: usize,
pattern: impl Fn(usize) -> TokenStream,
inner: impl Fn(Self, usize) -> TokenStream,
Expand All @@ -109,7 +111,7 @@ impl crate::shared::Item for Item {
Self::Type => {
let variants = encode_variants
.then(|| {
let private = private();
let private = private(crate_name);
quote! { variants: #private::VariantEncoder<#variant_count>, }
})
.unwrap_or_default();
Expand Down Expand Up @@ -224,13 +226,14 @@ impl crate::shared::Derive<{ Item::COUNT }> for Encode {
type Item = Item;
const ALL: [Self::Item; Item::COUNT] = Item::ALL;

fn bound(&self) -> Path {
let private = private();
fn bound(&self, crate_name: &Path) -> Path {
let private = private(crate_name);
parse_quote!(#private::Encode)
}

fn derive_impl(
&self,
crate_name: &Path,
output: [TokenStream; Item::COUNT],
ident: Ident,
mut generics: Generics,
Expand All @@ -248,7 +251,7 @@ impl crate::shared::Derive<{ Item::COUNT }> for Encode {
output;
let encoder_ident = Ident::new(&format!("{ident}Encoder"), Span::call_site());
let encoder_ty = quote! { #encoder_ident #encoder_generics };
let private = private();
let private = private(crate_name);

quote! {
const _: () = {
Expand Down
4 changes: 2 additions & 2 deletions bitcode_derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,6 @@ pub(crate) fn err<T>(spanned: &impl Spanned, s: &str) -> Result<T, Error> {
Err(error(spanned, s))
}

pub(crate) fn private() -> proc_macro2::TokenStream {
quote! { bitcode::__private }
finnbear marked this conversation as resolved.
Show resolved Hide resolved
pub(crate) fn private(crate_name: &syn::Path) -> proc_macro2::TokenStream {
quote! { ::#crate_name::__private }
}
38 changes: 29 additions & 9 deletions bitcode_derive/src/shared.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ pub fn variant_index(i: usize) -> VariantIndex {
pub trait Item: Copy + Sized {
fn field_impl(
self,
crate_name: &Path,
field_name: TokenStream,
global_field_name: TokenStream,
real_field_name: TokenStream,
Expand All @@ -32,12 +33,18 @@ pub trait Item: Copy + Sized {

fn enum_impl(
self,
crate_name: &Path,
variant_count: usize,
pattern: impl Fn(usize) -> TokenStream,
inner: impl Fn(Self, usize) -> TokenStream,
) -> TokenStream;

fn field_impls(self, global_prefix: Option<&str>, fields: &Fields) -> TokenStream {
fn field_impls(
self,
crate_name: &Path,
global_prefix: Option<&str>,
fields: &Fields,
) -> TokenStream {
fields
.iter()
.enumerate()
Expand All @@ -52,7 +59,7 @@ pub trait Item: Copy + Sized {
})
.unwrap_or_else(|| name.clone());

self.field_impl(name, global_name, real_name, &field.ty)
self.field_impl(crate_name, name, global_name, real_name, &field.ty)
})
.collect()
}
Expand All @@ -63,18 +70,20 @@ pub trait Derive<const ITEM_COUNT: usize> {
const ALL: [Self::Item; ITEM_COUNT];

/// `Encode` in `T: Encode`.
fn bound(&self) -> Path;
fn bound(&self, crate_name: &Path) -> Path;

/// Generates the derive implementation.
fn derive_impl(
&self,
crate_name: &Path,
output: [TokenStream; ITEM_COUNT],
ident: Ident,
generics: Generics,
) -> TokenStream;

fn field_attrs(
&self,
crate_name: &Path,
fields: &Fields,
attrs: &BitcodeAttrs,
bounds: &mut FieldBounds,
Expand All @@ -83,7 +92,7 @@ pub trait Derive<const ITEM_COUNT: usize> {
.iter()
.map(|field| {
let field_attrs = BitcodeAttrs::parse_field(&field.attrs, attrs)?;
bounds.add_bound_type(field.clone(), &field_attrs, self.bound());
bounds.add_bound_type(field.clone(), &field_attrs, self.bound(crate_name));
Ok(field_attrs)
})
.collect()
Expand All @@ -98,12 +107,13 @@ pub trait Derive<const ITEM_COUNT: usize> {
let output = match input.data {
Data::Struct(DataStruct { ref fields, .. }) => {
// Only used for adding `bounds`. Would be used by `#[bitcode(with_serde)]`.
let field_attrs = self.field_attrs(fields, &attrs, &mut bounds)?;
let field_attrs =
self.field_attrs(&attrs.crate_name, fields, &attrs, &mut bounds)?;
let _ = field_attrs;

let destructure_fields = &destructure_fields(fields);
Self::ALL.map(|item| {
let field_impls = item.field_impls(None, fields);
let field_impls = item.field_impls(&attrs.crate_name, None, fields);
item.struct_impl(&ident, destructure_fields, &field_impls)
})
}
Expand All @@ -122,13 +132,14 @@ pub trait Derive<const ITEM_COUNT: usize> {
.iter()
.map(|variant| {
let attrs = BitcodeAttrs::parse_variant(&variant.attrs, &attrs)?;
self.field_attrs(&variant.fields, &attrs, &mut bounds)
self.field_attrs(&attrs.crate_name, &variant.fields, &attrs, &mut bounds)
})
.collect::<Result<Vec<_>>>()?;
let _ = variant_attrs;

Self::ALL.map(|item| {
item.enum_impl(
&attrs.crate_name,
data_enum.variants.len(),
|i| {
let variant = &data_enum.variants[i];
Expand All @@ -141,14 +152,23 @@ pub trait Derive<const ITEM_COUNT: usize> {
|item, i| {
let variant = &data_enum.variants[i];
let global_prefix = format!("{}_", &variant.ident);
item.field_impls(Some(&global_prefix), &variant.fields)
item.field_impls(
&attrs.crate_name,
Some(&global_prefix),
&variant.fields,
)
},
)
})
}
Data::Union(_) => err(&ident, "unions are not supported")?,
};
Ok(self.derive_impl(output, ident, bounds.added_to(input.generics)))
Ok(self.derive_impl(
&attrs.crate_name,
output,
ident,
bounds.added_to(input.generics),
))
}
}

Expand Down
Loading