mirror of
https://github.com/Lokathor/bytemuck.git
synced 2024-11-22 06:42:25 +00:00
Added custom crate path with tests (#209)
Co-authored-by: Andri <80914617+Shuray04@users.noreply.github.com>
This commit is contained in:
parent
fd27a5b018
commit
c705218630
@ -9,8 +9,8 @@ use quote::quote;
|
|||||||
use syn::{parse_macro_input, DeriveInput, Result};
|
use syn::{parse_macro_input, DeriveInput, Result};
|
||||||
|
|
||||||
use crate::traits::{
|
use crate::traits::{
|
||||||
AnyBitPattern, CheckedBitPattern, Contiguous, Derivable, NoUninit, Pod,
|
bytemuck_crate_name, AnyBitPattern, CheckedBitPattern, Contiguous, Derivable,
|
||||||
TransparentWrapper, Zeroable,
|
NoUninit, Pod, TransparentWrapper, Zeroable,
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Derive the `Pod` trait for a struct
|
/// Derive the `Pod` trait for a struct
|
||||||
@ -87,7 +87,7 @@ use crate::traits::{
|
|||||||
///
|
///
|
||||||
/// let _: u32 = bytemuck::cast(Generic { a: 4u32, b: PhantomData::<NotPod> });
|
/// let _: u32 = bytemuck::cast(Generic { a: 4u32, b: PhantomData::<NotPod> });
|
||||||
/// ```
|
/// ```
|
||||||
#[proc_macro_derive(Pod)]
|
#[proc_macro_derive(Pod, attributes(bytemuck))]
|
||||||
pub fn derive_pod(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
pub fn derive_pod(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
||||||
let expanded =
|
let expanded =
|
||||||
derive_marker_trait::<Pod>(parse_macro_input!(input as DeriveInput));
|
derive_marker_trait::<Pod>(parse_macro_input!(input as DeriveInput));
|
||||||
@ -103,7 +103,7 @@ pub fn derive_pod(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
|||||||
/// The following constraints need to be satisfied for the macro to succeed
|
/// The following constraints need to be satisfied for the macro to succeed
|
||||||
///
|
///
|
||||||
/// - All fields in the struct must to implement `AnyBitPattern`
|
/// - All fields in the struct must to implement `AnyBitPattern`
|
||||||
#[proc_macro_derive(AnyBitPattern)]
|
#[proc_macro_derive(AnyBitPattern, attributes(bytemuck))]
|
||||||
pub fn derive_anybitpattern(
|
pub fn derive_anybitpattern(
|
||||||
input: proc_macro::TokenStream,
|
input: proc_macro::TokenStream,
|
||||||
) -> proc_macro::TokenStream {
|
) -> proc_macro::TokenStream {
|
||||||
@ -192,7 +192,7 @@ pub fn derive_anybitpattern(
|
|||||||
/// # }
|
/// # }
|
||||||
/// ZeroableWhenTIsZeroable::<String>::zeroed();
|
/// ZeroableWhenTIsZeroable::<String>::zeroed();
|
||||||
/// ```
|
/// ```
|
||||||
#[proc_macro_derive(Zeroable, attributes(zeroable))]
|
#[proc_macro_derive(Zeroable, attributes(bytemuck, zeroable))]
|
||||||
pub fn derive_zeroable(
|
pub fn derive_zeroable(
|
||||||
input: proc_macro::TokenStream,
|
input: proc_macro::TokenStream,
|
||||||
) -> proc_macro::TokenStream {
|
) -> proc_macro::TokenStream {
|
||||||
@ -319,7 +319,7 @@ pub fn derive_maybe_pod(
|
|||||||
/// another_extra: NonTransparentSafeZST, // not `Zeroable`
|
/// another_extra: NonTransparentSafeZST, // not `Zeroable`
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
#[proc_macro_derive(TransparentWrapper, attributes(transparent))]
|
#[proc_macro_derive(TransparentWrapper, attributes(bytemuck, transparent))]
|
||||||
pub fn derive_transparent(
|
pub fn derive_transparent(
|
||||||
input: proc_macro::TokenStream,
|
input: proc_macro::TokenStream,
|
||||||
) -> proc_macro::TokenStream {
|
) -> proc_macro::TokenStream {
|
||||||
@ -394,6 +394,7 @@ pub fn derive_byte_eq(
|
|||||||
input: proc_macro::TokenStream,
|
input: proc_macro::TokenStream,
|
||||||
) -> proc_macro::TokenStream {
|
) -> proc_macro::TokenStream {
|
||||||
let input = parse_macro_input!(input as DeriveInput);
|
let input = parse_macro_input!(input as DeriveInput);
|
||||||
|
let crate_name = bytemuck_crate_name(&input);
|
||||||
let ident = input.ident;
|
let ident = input.ident;
|
||||||
|
|
||||||
proc_macro::TokenStream::from(quote! {
|
proc_macro::TokenStream::from(quote! {
|
||||||
@ -401,7 +402,7 @@ pub fn derive_byte_eq(
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[must_use]
|
#[must_use]
|
||||||
fn eq(&self, other: &Self) -> bool {
|
fn eq(&self, other: &Self) -> bool {
|
||||||
::bytemuck::bytes_of(self) == ::bytemuck::bytes_of(other)
|
#crate_name::bytes_of(self) == #crate_name::bytes_of(other)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
impl ::core::cmp::Eq for #ident { }
|
impl ::core::cmp::Eq for #ident { }
|
||||||
@ -434,18 +435,19 @@ pub fn derive_byte_hash(
|
|||||||
input: proc_macro::TokenStream,
|
input: proc_macro::TokenStream,
|
||||||
) -> proc_macro::TokenStream {
|
) -> proc_macro::TokenStream {
|
||||||
let input = parse_macro_input!(input as DeriveInput);
|
let input = parse_macro_input!(input as DeriveInput);
|
||||||
|
let crate_name = bytemuck_crate_name(&input);
|
||||||
let ident = input.ident;
|
let ident = input.ident;
|
||||||
|
|
||||||
proc_macro::TokenStream::from(quote! {
|
proc_macro::TokenStream::from(quote! {
|
||||||
impl ::core::hash::Hash for #ident {
|
impl ::core::hash::Hash for #ident {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn hash<H: ::core::hash::Hasher>(&self, state: &mut H) {
|
fn hash<H: ::core::hash::Hasher>(&self, state: &mut H) {
|
||||||
::core::hash::Hash::hash_slice(::bytemuck::bytes_of(self), state)
|
::core::hash::Hash::hash_slice(#crate_name::bytes_of(self), state)
|
||||||
}
|
}
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
fn hash_slice<H: ::core::hash::Hasher>(data: &[Self], state: &mut H) {
|
fn hash_slice<H: ::core::hash::Hasher>(data: &[Self], state: &mut H) {
|
||||||
::core::hash::Hash::hash_slice(::bytemuck::cast_slice::<_, u8>(data), state)
|
::core::hash::Hash::hash_slice(#crate_name::cast_slice::<_, u8>(data), state)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -518,7 +520,8 @@ fn find_and_parse_helper_attributes<P: syn::parse::Parser + Copy>(
|
|||||||
fn derive_marker_trait_inner<Trait: Derivable>(
|
fn derive_marker_trait_inner<Trait: Derivable>(
|
||||||
mut input: DeriveInput,
|
mut input: DeriveInput,
|
||||||
) -> Result<TokenStream> {
|
) -> Result<TokenStream> {
|
||||||
let trait_ = Trait::ident(&input)?;
|
let crate_name = bytemuck_crate_name(&input);
|
||||||
|
let trait_ = Trait::ident(&input, &crate_name)?;
|
||||||
// If this trait allows explicit bounds, and any explicit bounds were given,
|
// If this trait allows explicit bounds, and any explicit bounds were given,
|
||||||
// then use those explicit bounds. Else, apply the default bounds (bound
|
// then use those explicit bounds. Else, apply the default bounds (bound
|
||||||
// each generic type on this trait).
|
// each generic type on this trait).
|
||||||
@ -585,10 +588,12 @@ fn derive_marker_trait_inner<Trait: Derivable>(
|
|||||||
input.generics.split_for_impl();
|
input.generics.split_for_impl();
|
||||||
|
|
||||||
Trait::check_attributes(&input.data, &input.attrs)?;
|
Trait::check_attributes(&input.data, &input.attrs)?;
|
||||||
let asserts = Trait::asserts(&input)?;
|
let asserts = Trait::asserts(&input, &crate_name)?;
|
||||||
let (trait_impl_extras, trait_impl) = Trait::trait_impl(&input)?;
|
let (trait_impl_extras, trait_impl) = Trait::trait_impl(&input, &crate_name)?;
|
||||||
|
|
||||||
let implies_trait = if let Some(implies_trait) = Trait::implies_trait() {
|
let implies_trait = if let Some(implies_trait) =
|
||||||
|
Trait::implies_trait(&crate_name)
|
||||||
|
{
|
||||||
quote!(unsafe impl #impl_generics #implies_trait for #name #ty_generics #where_clause {})
|
quote!(unsafe impl #impl_generics #implies_trait for #name #ty_generics #where_clause {})
|
||||||
} else {
|
} else {
|
||||||
quote!()
|
quote!()
|
||||||
|
@ -21,17 +21,17 @@ macro_rules! bail {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub trait Derivable {
|
pub trait Derivable {
|
||||||
fn ident(input: &DeriveInput) -> Result<syn::Path>;
|
fn ident(input: &DeriveInput, crate_name: &TokenStream) -> Result<syn::Path>;
|
||||||
fn implies_trait() -> Option<TokenStream> {
|
fn implies_trait(_crate_name: &TokenStream) -> Option<TokenStream> {
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
fn asserts(_input: &DeriveInput) -> Result<TokenStream> {
|
fn asserts(_input: &DeriveInput, _crate_name: &TokenStream) -> Result<TokenStream> {
|
||||||
Ok(quote!())
|
Ok(quote!())
|
||||||
}
|
}
|
||||||
fn check_attributes(_ty: &Data, _attributes: &[Attribute]) -> Result<()> {
|
fn check_attributes(_ty: &Data, _attributes: &[Attribute]) -> Result<()> {
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
fn trait_impl(_input: &DeriveInput) -> Result<(TokenStream, TokenStream)> {
|
fn trait_impl(_input: &DeriveInput, _crate_name: &TokenStream) -> Result<(TokenStream, TokenStream)> {
|
||||||
Ok((quote!(), quote!()))
|
Ok((quote!(), quote!()))
|
||||||
}
|
}
|
||||||
fn requires_where_clause() -> bool {
|
fn requires_where_clause() -> bool {
|
||||||
@ -45,11 +45,11 @@ pub trait Derivable {
|
|||||||
pub struct Pod;
|
pub struct Pod;
|
||||||
|
|
||||||
impl Derivable for Pod {
|
impl Derivable for Pod {
|
||||||
fn ident(_: &DeriveInput) -> Result<syn::Path> {
|
fn ident(_: &DeriveInput, crate_name: &TokenStream) -> Result<syn::Path> {
|
||||||
Ok(syn::parse_quote!(::bytemuck::Pod))
|
Ok(syn::parse_quote!(#crate_name::Pod))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn asserts(input: &DeriveInput) -> Result<TokenStream> {
|
fn asserts(input: &DeriveInput, crate_name: &TokenStream) -> Result<TokenStream> {
|
||||||
let repr = get_repr(&input.attrs)?;
|
let repr = get_repr(&input.attrs)?;
|
||||||
|
|
||||||
let completly_packed =
|
let completly_packed =
|
||||||
@ -71,7 +71,7 @@ impl Derivable for Pod {
|
|||||||
None
|
None
|
||||||
};
|
};
|
||||||
let assert_fields_are_pod =
|
let assert_fields_are_pod =
|
||||||
generate_fields_are_trait(input, Self::ident(input)?)?;
|
generate_fields_are_trait(input, Self::ident(input, crate_name)?)?;
|
||||||
|
|
||||||
Ok(quote!(
|
Ok(quote!(
|
||||||
#assert_no_padding
|
#assert_no_padding
|
||||||
@ -98,18 +98,18 @@ impl Derivable for Pod {
|
|||||||
pub struct AnyBitPattern;
|
pub struct AnyBitPattern;
|
||||||
|
|
||||||
impl Derivable for AnyBitPattern {
|
impl Derivable for AnyBitPattern {
|
||||||
fn ident(_: &DeriveInput) -> Result<syn::Path> {
|
fn ident(_: &DeriveInput, crate_name: &TokenStream) -> Result<syn::Path> {
|
||||||
Ok(syn::parse_quote!(::bytemuck::AnyBitPattern))
|
Ok(syn::parse_quote!(#crate_name::AnyBitPattern))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn implies_trait() -> Option<TokenStream> {
|
fn implies_trait(crate_name: &TokenStream) -> Option<TokenStream> {
|
||||||
Some(quote!(::bytemuck::Zeroable))
|
Some(quote!(#crate_name::Zeroable))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn asserts(input: &DeriveInput) -> Result<TokenStream> {
|
fn asserts(input: &DeriveInput, crate_name: &TokenStream) -> Result<TokenStream> {
|
||||||
match &input.data {
|
match &input.data {
|
||||||
Data::Union(_) => Ok(quote!()), // unions are always `AnyBitPattern`
|
Data::Union(_) => Ok(quote!()), // unions are always `AnyBitPattern`
|
||||||
Data::Struct(_) => generate_fields_are_trait(input, Self::ident(input)?),
|
Data::Struct(_) => generate_fields_are_trait(input, Self::ident(input, crate_name)?),
|
||||||
Data::Enum(_) => {
|
Data::Enum(_) => {
|
||||||
bail!("Deriving AnyBitPattern is not supported for enums")
|
bail!("Deriving AnyBitPattern is not supported for enums")
|
||||||
}
|
}
|
||||||
@ -120,14 +120,14 @@ impl Derivable for AnyBitPattern {
|
|||||||
pub struct Zeroable;
|
pub struct Zeroable;
|
||||||
|
|
||||||
impl Derivable for Zeroable {
|
impl Derivable for Zeroable {
|
||||||
fn ident(_: &DeriveInput) -> Result<syn::Path> {
|
fn ident(_: &DeriveInput, crate_name: &TokenStream) -> Result<syn::Path> {
|
||||||
Ok(syn::parse_quote!(::bytemuck::Zeroable))
|
Ok(syn::parse_quote!(#crate_name::Zeroable))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn asserts(input: &DeriveInput) -> Result<TokenStream> {
|
fn asserts(input: &DeriveInput, crate_name: &TokenStream) -> Result<TokenStream> {
|
||||||
match &input.data {
|
match &input.data {
|
||||||
Data::Union(_) => Ok(quote!()), // unions are always `Zeroable`
|
Data::Union(_) => Ok(quote!()), // unions are always `Zeroable`
|
||||||
Data::Struct(_) => generate_fields_are_trait(input, Self::ident(input)?),
|
Data::Struct(_) => generate_fields_are_trait(input, Self::ident(input, crate_name)?),
|
||||||
Data::Enum(_) => bail!("Deriving Zeroable is not supported for enums"),
|
Data::Enum(_) => bail!("Deriving Zeroable is not supported for enums"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -140,8 +140,8 @@ impl Derivable for Zeroable {
|
|||||||
pub struct NoUninit;
|
pub struct NoUninit;
|
||||||
|
|
||||||
impl Derivable for NoUninit {
|
impl Derivable for NoUninit {
|
||||||
fn ident(_: &DeriveInput) -> Result<syn::Path> {
|
fn ident(_: &DeriveInput, crate_name: &TokenStream) -> Result<syn::Path> {
|
||||||
Ok(syn::parse_quote!(::bytemuck::NoUninit))
|
Ok(syn::parse_quote!(#crate_name::NoUninit))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_attributes(ty: &Data, attributes: &[Attribute]) -> Result<()> {
|
fn check_attributes(ty: &Data, attributes: &[Attribute]) -> Result<()> {
|
||||||
@ -160,7 +160,7 @@ impl Derivable for NoUninit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn asserts(input: &DeriveInput) -> Result<TokenStream> {
|
fn asserts(input: &DeriveInput, crate_name: &TokenStream) -> Result<TokenStream> {
|
||||||
if !input.generics.params.is_empty() {
|
if !input.generics.params.is_empty() {
|
||||||
bail!("NoUninit cannot be derived for structs containing generic parameters because the padding requirements can't be verified for generic structs");
|
bail!("NoUninit cannot be derived for structs containing generic parameters because the padding requirements can't be verified for generic structs");
|
||||||
}
|
}
|
||||||
@ -169,7 +169,7 @@ impl Derivable for NoUninit {
|
|||||||
Data::Struct(DataStruct { .. }) => {
|
Data::Struct(DataStruct { .. }) => {
|
||||||
let assert_no_padding = generate_assert_no_padding(&input)?;
|
let assert_no_padding = generate_assert_no_padding(&input)?;
|
||||||
let assert_fields_are_no_padding =
|
let assert_fields_are_no_padding =
|
||||||
generate_fields_are_trait(&input, Self::ident(input)?)?;
|
generate_fields_are_trait(&input, Self::ident(input, crate_name)?)?;
|
||||||
|
|
||||||
Ok(quote!(
|
Ok(quote!(
|
||||||
#assert_no_padding
|
#assert_no_padding
|
||||||
@ -187,7 +187,7 @@ impl Derivable for NoUninit {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trait_impl(_input: &DeriveInput) -> Result<(TokenStream, TokenStream)> {
|
fn trait_impl(_input: &DeriveInput, _crate_name: &TokenStream) -> Result<(TokenStream, TokenStream)> {
|
||||||
Ok((quote!(), quote!()))
|
Ok((quote!(), quote!()))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -195,8 +195,8 @@ impl Derivable for NoUninit {
|
|||||||
pub struct CheckedBitPattern;
|
pub struct CheckedBitPattern;
|
||||||
|
|
||||||
impl Derivable for CheckedBitPattern {
|
impl Derivable for CheckedBitPattern {
|
||||||
fn ident(_: &DeriveInput) -> Result<syn::Path> {
|
fn ident(_: &DeriveInput, crate_name: &TokenStream) -> Result<syn::Path> {
|
||||||
Ok(syn::parse_quote!(::bytemuck::CheckedBitPattern))
|
Ok(syn::parse_quote!(#crate_name::CheckedBitPattern))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_attributes(ty: &Data, attributes: &[Attribute]) -> Result<()> {
|
fn check_attributes(ty: &Data, attributes: &[Attribute]) -> Result<()> {
|
||||||
@ -223,7 +223,7 @@ impl Derivable for CheckedBitPattern {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn asserts(input: &DeriveInput) -> Result<TokenStream> {
|
fn asserts(input: &DeriveInput, crate_name: &TokenStream) -> Result<TokenStream> {
|
||||||
if !input.generics.params.is_empty() {
|
if !input.generics.params.is_empty() {
|
||||||
bail!("CheckedBitPattern cannot be derived for structs containing generic parameters");
|
bail!("CheckedBitPattern cannot be derived for structs containing generic parameters");
|
||||||
}
|
}
|
||||||
@ -231,7 +231,7 @@ impl Derivable for CheckedBitPattern {
|
|||||||
match &input.data {
|
match &input.data {
|
||||||
Data::Struct(DataStruct { .. }) => {
|
Data::Struct(DataStruct { .. }) => {
|
||||||
let assert_fields_are_maybe_pod =
|
let assert_fields_are_maybe_pod =
|
||||||
generate_fields_are_trait(&input, Self::ident(input)?)?;
|
generate_fields_are_trait(&input, Self::ident(input, crate_name)?)?;
|
||||||
|
|
||||||
Ok(assert_fields_are_maybe_pod)
|
Ok(assert_fields_are_maybe_pod)
|
||||||
}
|
}
|
||||||
@ -240,13 +240,13 @@ impl Derivable for CheckedBitPattern {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trait_impl(input: &DeriveInput) -> Result<(TokenStream, TokenStream)> {
|
fn trait_impl(input: &DeriveInput, crate_name: &TokenStream) -> Result<(TokenStream, TokenStream)> {
|
||||||
match &input.data {
|
match &input.data {
|
||||||
Data::Struct(DataStruct { fields, .. }) => {
|
Data::Struct(DataStruct { fields, .. }) => {
|
||||||
generate_checked_bit_pattern_struct(&input.ident, fields, &input.attrs)
|
generate_checked_bit_pattern_struct(&input.ident, fields, &input.attrs, crate_name)
|
||||||
}
|
}
|
||||||
Data::Enum(DataEnum { variants, .. }) => {
|
Data::Enum(DataEnum { variants, .. }) => {
|
||||||
generate_checked_bit_pattern_enum(input, variants)
|
generate_checked_bit_pattern_enum(input, variants, crate_name)
|
||||||
}
|
}
|
||||||
Data::Union(_) => bail!("Internal error in CheckedBitPattern derive"), /* shouldn't be possible since we already error in attribute check for this case */
|
Data::Union(_) => bail!("Internal error in CheckedBitPattern derive"), /* shouldn't be possible since we already error in attribute check for this case */
|
||||||
}
|
}
|
||||||
@ -274,7 +274,7 @@ impl TransparentWrapper {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl Derivable for TransparentWrapper {
|
impl Derivable for TransparentWrapper {
|
||||||
fn ident(input: &DeriveInput) -> Result<syn::Path> {
|
fn ident(input: &DeriveInput, crate_name: &TokenStream) -> Result<syn::Path> {
|
||||||
let fields = get_struct_fields(input)?;
|
let fields = get_struct_fields(input)?;
|
||||||
|
|
||||||
let ty = match Self::get_wrapper_type(&input.attrs, &fields) {
|
let ty = match Self::get_wrapper_type(&input.attrs, &fields) {
|
||||||
@ -287,10 +287,10 @@ impl Derivable for TransparentWrapper {
|
|||||||
),
|
),
|
||||||
};
|
};
|
||||||
|
|
||||||
Ok(syn::parse_quote!(::bytemuck::TransparentWrapper<#ty>))
|
Ok(syn::parse_quote!(#crate_name::TransparentWrapper<#ty>))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn asserts(input: &DeriveInput) -> Result<TokenStream> {
|
fn asserts(input: &DeriveInput, crate_name: &TokenStream) -> Result<TokenStream> {
|
||||||
let (impl_generics, _ty_generics, where_clause) =
|
let (impl_generics, _ty_generics, where_clause) =
|
||||||
input.generics.split_for_impl();
|
input.generics.split_for_impl();
|
||||||
let fields = get_struct_fields(input)?;
|
let fields = get_struct_fields(input)?;
|
||||||
@ -318,7 +318,7 @@ impl Derivable for TransparentWrapper {
|
|||||||
const _: () = {
|
const _: () = {
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
struct AssertWrappedIsWrapped #impl_generics((u8, ::core::marker::PhantomData<#wrapped_field_ty>), #(#nonwrapped_field_tys),*) #where_clause;
|
struct AssertWrappedIsWrapped #impl_generics((u8, ::core::marker::PhantomData<#wrapped_field_ty>), #(#nonwrapped_field_tys),*) #where_clause;
|
||||||
fn assert_zeroable<Z: ::bytemuck::Zeroable>() {}
|
fn assert_zeroable<Z: #crate_name::Zeroable>() {}
|
||||||
fn check #impl_generics () #where_clause {
|
fn check #impl_generics () #where_clause {
|
||||||
#(
|
#(
|
||||||
assert_zeroable::<#nonwrapped_field_tys>();
|
assert_zeroable::<#nonwrapped_field_tys>();
|
||||||
@ -352,11 +352,11 @@ impl Derivable for TransparentWrapper {
|
|||||||
pub struct Contiguous;
|
pub struct Contiguous;
|
||||||
|
|
||||||
impl Derivable for Contiguous {
|
impl Derivable for Contiguous {
|
||||||
fn ident(_: &DeriveInput) -> Result<syn::Path> {
|
fn ident(_: &DeriveInput, crate_name: &TokenStream) -> Result<syn::Path> {
|
||||||
Ok(syn::parse_quote!(::bytemuck::Contiguous))
|
Ok(syn::parse_quote!(#crate_name::Contiguous))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn trait_impl(input: &DeriveInput) -> Result<(TokenStream, TokenStream)> {
|
fn trait_impl(input: &DeriveInput, _crate_name: &TokenStream) -> Result<(TokenStream, TokenStream)> {
|
||||||
let repr = get_repr(&input.attrs)?;
|
let repr = get_repr(&input.attrs)?;
|
||||||
|
|
||||||
let integer_ty = if let Some(integer_ty) = repr.repr.as_integer() {
|
let integer_ty = if let Some(integer_ty) = repr.repr.as_integer() {
|
||||||
@ -460,7 +460,7 @@ fn get_field_types<'a>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn generate_checked_bit_pattern_struct(
|
fn generate_checked_bit_pattern_struct(
|
||||||
input_ident: &Ident, fields: &Fields, attrs: &[Attribute],
|
input_ident: &Ident, fields: &Fields, attrs: &[Attribute], crate_name: &TokenStream
|
||||||
) -> Result<(TokenStream, TokenStream)> {
|
) -> Result<(TokenStream, TokenStream)> {
|
||||||
let bits_ty = Ident::new(&format!("{}Bits", input_ident), input_ident.span());
|
let bits_ty = Ident::new(&format!("{}Bits", input_ident), input_ident.span());
|
||||||
|
|
||||||
@ -486,10 +486,10 @@ fn generate_checked_bit_pattern_struct(
|
|||||||
Ok((
|
Ok((
|
||||||
quote! {
|
quote! {
|
||||||
#repr
|
#repr
|
||||||
#[derive(Clone, Copy, ::bytemuck::AnyBitPattern)]
|
#[derive(Clone, Copy, #crate_name::AnyBitPattern)]
|
||||||
#derive_dbg
|
#derive_dbg
|
||||||
pub struct #bits_ty {
|
pub struct #bits_ty {
|
||||||
#(#field_name: <#field_ty as ::bytemuck::CheckedBitPattern>::Bits,)*
|
#(#field_name: <#field_ty as #crate_name::CheckedBitPattern>::Bits,)*
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
quote! {
|
quote! {
|
||||||
@ -498,17 +498,17 @@ fn generate_checked_bit_pattern_struct(
|
|||||||
#[inline]
|
#[inline]
|
||||||
#[allow(clippy::double_comparisons)]
|
#[allow(clippy::double_comparisons)]
|
||||||
fn is_valid_bit_pattern(bits: &#bits_ty) -> bool {
|
fn is_valid_bit_pattern(bits: &#bits_ty) -> bool {
|
||||||
#(<#field_ty as ::bytemuck::CheckedBitPattern>::is_valid_bit_pattern(&{ bits.#field_name }) && )* true
|
#(<#field_ty as #crate_name::CheckedBitPattern>::is_valid_bit_pattern(&{ bits.#field_name }) && )* true
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn generate_checked_bit_pattern_enum(
|
fn generate_checked_bit_pattern_enum(
|
||||||
input: &DeriveInput, variants: &Punctuated<Variant, Token![,]>,
|
input: &DeriveInput, variants: &Punctuated<Variant, Token![,]>, crate_name: &TokenStream
|
||||||
) -> Result<(TokenStream, TokenStream)> {
|
) -> Result<(TokenStream, TokenStream)> {
|
||||||
if enum_has_fields(variants.iter()) {
|
if enum_has_fields(variants.iter()) {
|
||||||
generate_checked_bit_pattern_enum_with_fields(input, variants)
|
generate_checked_bit_pattern_enum_with_fields(input, variants, crate_name)
|
||||||
} else {
|
} else {
|
||||||
generate_checked_bit_pattern_enum_without_fields(input, variants)
|
generate_checked_bit_pattern_enum_without_fields(input, variants)
|
||||||
}
|
}
|
||||||
@ -574,7 +574,7 @@ fn generate_checked_bit_pattern_enum_without_fields(
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn generate_checked_bit_pattern_enum_with_fields(
|
fn generate_checked_bit_pattern_enum_with_fields(
|
||||||
input: &DeriveInput, variants: &Punctuated<Variant, Token![,]>,
|
input: &DeriveInput, variants: &Punctuated<Variant, Token![,]>, crate_name: &TokenStream
|
||||||
) -> Result<(TokenStream, TokenStream)> {
|
) -> Result<(TokenStream, TokenStream)> {
|
||||||
let representation = get_repr(&input.attrs)?;
|
let representation = get_repr(&input.attrs)?;
|
||||||
let vis = &input.vis;
|
let vis = &input.vis;
|
||||||
@ -617,7 +617,7 @@ fn generate_checked_bit_pattern_enum_with_fields(
|
|||||||
let fields = v.fields.iter().map(|v| &v.ty);
|
let fields = v.fields.iter().map(|v| &v.ty);
|
||||||
|
|
||||||
quote! {
|
quote! {
|
||||||
#[derive(::core::clone::Clone, ::core::marker::Copy, ::bytemuck::CheckedBitPattern)]
|
#[derive(::core::clone::Clone, ::core::marker::Copy, #crate_name::CheckedBitPattern)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#vis struct #variant_struct_ident(#(#fields),*);
|
#vis struct #variant_struct_ident(#(#fields),*);
|
||||||
}
|
}
|
||||||
@ -644,7 +644,7 @@ fn generate_checked_bit_pattern_enum_with_fields(
|
|||||||
Ok(quote! {
|
Ok(quote! {
|
||||||
#discriminant => {
|
#discriminant => {
|
||||||
let payload = unsafe { &bits.payload.#ident };
|
let payload = unsafe { &bits.payload.#ident };
|
||||||
<#variant_struct_ident as ::bytemuck::CheckedBitPattern>::is_valid_bit_pattern(payload)
|
<#variant_struct_ident as #crate_name::CheckedBitPattern>::is_valid_bit_pattern(payload)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -652,7 +652,7 @@ fn generate_checked_bit_pattern_enum_with_fields(
|
|||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
quote! {
|
quote! {
|
||||||
#[derive(::core::clone::Clone, ::core::marker::Copy, ::bytemuck::AnyBitPattern)]
|
#[derive(::core::clone::Clone, ::core::marker::Copy, #crate_name::AnyBitPattern)]
|
||||||
#derive_dbg
|
#derive_dbg
|
||||||
#bits_repr
|
#bits_repr
|
||||||
#vis struct #bits_ty_ident {
|
#vis struct #bits_ty_ident {
|
||||||
@ -660,7 +660,7 @@ fn generate_checked_bit_pattern_enum_with_fields(
|
|||||||
payload: #variants_union_ident,
|
payload: #variants_union_ident,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(::core::clone::Clone, ::core::marker::Copy, ::bytemuck::AnyBitPattern)]
|
#[derive(::core::clone::Clone, ::core::marker::Copy, #crate_name::AnyBitPattern)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
#vis union #variants_union_ident {
|
#vis union #variants_union_ident {
|
||||||
@ -703,17 +703,17 @@ fn generate_checked_bit_pattern_enum_with_fields(
|
|||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
quote! {
|
quote! {
|
||||||
#[derive(::core::clone::Clone, ::core::marker::Copy, ::bytemuck::CheckedBitPattern)]
|
#[derive(::core::clone::Clone, ::core::marker::Copy, #crate_name::CheckedBitPattern)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#vis struct #bits_ty(#(#fields),*);
|
#vis struct #bits_ty(#(#fields),*);
|
||||||
},
|
},
|
||||||
quote! {
|
quote! {
|
||||||
type Bits = <#bits_ty as ::bytemuck::CheckedBitPattern>::Bits;
|
type Bits = <#bits_ty as #crate_name::CheckedBitPattern>::Bits;
|
||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
#[allow(clippy::double_comparisons)]
|
#[allow(clippy::double_comparisons)]
|
||||||
fn is_valid_bit_pattern(bits: &Self::Bits) -> bool {
|
fn is_valid_bit_pattern(bits: &Self::Bits) -> bool {
|
||||||
<#bits_ty as ::bytemuck::CheckedBitPattern>::is_valid_bit_pattern(bits)
|
<#bits_ty as #crate_name::CheckedBitPattern>::is_valid_bit_pattern(bits)
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
))
|
))
|
||||||
@ -740,7 +740,7 @@ fn generate_checked_bit_pattern_enum_with_fields(
|
|||||||
|
|
||||||
// adding the discriminant repr integer as first field, as described above
|
// adding the discriminant repr integer as first field, as described above
|
||||||
quote! {
|
quote! {
|
||||||
#[derive(::core::clone::Clone, ::core::marker::Copy, ::bytemuck::CheckedBitPattern)]
|
#[derive(::core::clone::Clone, ::core::marker::Copy, #crate_name::CheckedBitPattern)]
|
||||||
#[repr(C)]
|
#[repr(C)]
|
||||||
#vis struct #variant_struct_ident(#integer, #(#fields),*);
|
#vis struct #variant_struct_ident(#integer, #(#fields),*);
|
||||||
}
|
}
|
||||||
@ -767,7 +767,7 @@ fn generate_checked_bit_pattern_enum_with_fields(
|
|||||||
Ok(quote! {
|
Ok(quote! {
|
||||||
#discriminant => {
|
#discriminant => {
|
||||||
let payload = unsafe { &bits.#ident };
|
let payload = unsafe { &bits.#ident };
|
||||||
<#variant_struct_ident as ::bytemuck::CheckedBitPattern>::is_valid_bit_pattern(payload)
|
<#variant_struct_ident as #crate_name::CheckedBitPattern>::is_valid_bit_pattern(payload)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
@ -775,7 +775,7 @@ fn generate_checked_bit_pattern_enum_with_fields(
|
|||||||
|
|
||||||
Ok((
|
Ok((
|
||||||
quote! {
|
quote! {
|
||||||
#[derive(::core::clone::Clone, ::core::marker::Copy, ::bytemuck::AnyBitPattern)]
|
#[derive(::core::clone::Clone, ::core::marker::Copy, #crate_name::AnyBitPattern)]
|
||||||
#bits_repr
|
#bits_repr
|
||||||
#[allow(non_snake_case)]
|
#[allow(non_snake_case)]
|
||||||
#vis union #bits_ty_ident {
|
#vis union #bits_ty_ident {
|
||||||
@ -1219,3 +1219,47 @@ mod tests {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn bytemuck_crate_name(input: &DeriveInput) -> TokenStream {
|
||||||
|
const ATTR_NAME: &'static str = "crate";
|
||||||
|
|
||||||
|
let mut crate_name = quote!(::bytemuck);
|
||||||
|
for attr in &input.attrs {
|
||||||
|
if !attr.path().is_ident("bytemuck") {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
attr.parse_nested_meta(|meta| {
|
||||||
|
if meta.path.is_ident(ATTR_NAME) {
|
||||||
|
let expr: syn::Expr = meta.value()?.parse()?;
|
||||||
|
let mut value = &expr;
|
||||||
|
while let syn::Expr::Group(e) = value {
|
||||||
|
value = &e.expr;
|
||||||
|
}
|
||||||
|
if let syn::Expr::Lit(syn::ExprLit {
|
||||||
|
lit: syn::Lit::Str(lit), ..
|
||||||
|
}) = value
|
||||||
|
{
|
||||||
|
let suffix = lit.suffix();
|
||||||
|
if !suffix.is_empty() {
|
||||||
|
bail!(format!("Unexpected suffix `{}` on string literal", suffix))
|
||||||
|
}
|
||||||
|
let path: syn::Path = match lit.parse() {
|
||||||
|
Ok(path) => path,
|
||||||
|
Err(_) => {
|
||||||
|
bail!(format!("Failed to parse path: {:?}", lit.value()))
|
||||||
|
}
|
||||||
|
};
|
||||||
|
crate_name = path.into_token_stream();
|
||||||
|
} else {
|
||||||
|
bail!(
|
||||||
|
"Expected bytemuck `crate` attribute to be a string: `crate = \"...\"`",
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
return crate_name;
|
||||||
|
}
|
||||||
|
@ -443,3 +443,10 @@ fn checkedbitpattern_transparent_enum_with_fields() {
|
|||||||
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable)]
|
||||||
#[repr(C, align(16))]
|
#[repr(C, align(16))]
|
||||||
struct Issue127 {}
|
struct Issue127 {}
|
||||||
|
|
||||||
|
use bytemuck as reexport_name;
|
||||||
|
#[derive(Copy, Clone, bytemuck::Pod, bytemuck::Zeroable, bytemuck::ByteEq)]
|
||||||
|
#[bytemuck(crate = "reexport_name")]
|
||||||
|
#[repr(C)]
|
||||||
|
struct Issue93 {}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user