blob: b8aabdb518aa9ca6387bc098f8a37435d75eb316 [file] [log] [blame]
// Copyright 2024 The Fuchsia Authors
//
// Licensed under a BSD-style license <LICENSE-BSD>, Apache License, Version 2.0
// <LICENSE-APACHE or https://www.apache.org/licenses/LICENSE-2.0>, or the MIT
// license <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your option.
// This file may not be copied, modified, or distributed except according to
// those terms.
use crate::IntoTokenStream;
use dissimilar::Chunk;
use proc_macro2::TokenStream;
macro_rules! use_as_trait_name {
($($alias:ident => $derive:ident),* $(,)?) => {
$(use super::$derive as $alias;)*
};
}
// This permits invocations of `test!` to be more ergonomic, passing the name of
// the trait under test rather than the name of the inner derive function.
use_as_trait_name!(
KnownLayout => derive_known_layout_inner,
Immutable => derive_no_cell_inner,
TryFromBytes => derive_try_from_bytes_inner,
FromZeros => derive_from_zeros_inner,
FromBytes => derive_from_bytes_inner,
IntoBytes => derive_into_bytes_inner,
Unaligned => derive_unaligned_inner,
ByteHash => derive_hash_inner,
ByteEq => derive_eq_inner,
);
/// Test that the given derive input expands to the expected output.
///
/// Equality is tested by formatting both token streams using `prettyplease` and
/// performing string equality on the results. This has the effect of making the
/// tests less brittle and robust against meaningless formatting changes.
// Adapted from https://github.com/joshlf/synstructure/blob/400499aaf54840056ff56718beb7810540e6be59/src/macros.rs#L212-L317
macro_rules! test {
($name:ident { $($i:tt)* } expands to { $($o:tt)* }) => {
{
#[allow(dead_code)]
fn ensure_compiles() {
$($i)*
$($o)*
}
test!($name { $($i)* } expands to { $($o)* } no_build);
}
};
($name:ident { $($i:tt)* } expands to { $($o:tt)* } no_build) => {
{
let ts: proc_macro2::TokenStream = quote::quote!( $($i)* );
let ast = syn::parse2::<syn::DeriveInput>(ts).unwrap();
let res = $name(&ast, crate::Trait::$name);
let expected_toks = quote::quote!( $($o)* );
assert_eq_streams(expected_toks.into(), res.into_ts().into());
}
};
}
#[track_caller]
fn assert_eq_streams(expect: TokenStream, res: TokenStream) {
let pretty =
|ts: TokenStream| prettyplease::unparse(&syn::parse_file(&ts.to_string()).unwrap());
let expect = pretty(expect.clone());
let res = pretty(res.clone());
if expect != res {
let diff = dissimilar::diff(&expect, &res)
.into_iter()
.flat_map(|chunk| {
let (prefix, chunk) = match chunk {
Chunk::Equal(chunk) => (" ", chunk),
Chunk::Delete(chunk) => ("-", chunk),
Chunk::Insert(chunk) => ("+", chunk),
};
[prefix, chunk, "\n"]
})
.collect::<String>();
panic!(
"\
test failed:
got:
```
{}
```
diff (expected vs got):
```
{}
```\n",
res, diff
);
}
}
#[test]
fn test_known_layout() {
test! {
KnownLayout {
struct Foo;
} expands to {
#[allow(deprecated)]
#[automatically_derived]
unsafe impl ::zerocopy::KnownLayout for Foo
where
Self: ::zerocopy::util::macro_util::core_reexport::marker::Sized,
{
fn only_derive_is_allowed_to_implement_this_trait() {}
type PointerMetadata = ();
type MaybeUninit = ::zerocopy::util::macro_util::core_reexport::mem::MaybeUninit<Self>;
const LAYOUT: ::zerocopy::DstLayout = ::zerocopy::DstLayout::for_type::<Self>();
#[inline(always)]
fn raw_from_ptr_len(
bytes: ::zerocopy::util::macro_util::core_reexport::ptr::NonNull<u8>,
_meta: (),
) -> ::zerocopy::util::macro_util::core_reexport::ptr::NonNull<Self> {
bytes.cast::<Self>()
}
#[inline(always)]
fn pointer_to_metadata(_ptr: *mut Self) -> () {}
}
} no_build
}
test! {
KnownLayout {
#[repr(C, align(2))]
struct Foo<T, U>(T, U);
}
expands to {
const _: () = {
#[allow(deprecated)]
#[automatically_derived]
unsafe impl<T, U> ::zerocopy::KnownLayout for Foo<T, U>
where
U: ::zerocopy::KnownLayout,
{
fn only_derive_is_allowed_to_implement_this_trait() {}
type PointerMetadata = <U as ::zerocopy::KnownLayout>::PointerMetadata;
type MaybeUninit = __ZerocopyKnownLayoutMaybeUninit<T, U>;
const LAYOUT: ::zerocopy::DstLayout = {
use ::zerocopy::util::macro_util::core_reexport::num::NonZeroUsize;
use ::zerocopy::{DstLayout, KnownLayout};
let repr_align = ::zerocopy::util::macro_util::core_reexport::num::NonZeroUsize::new(
2u32 as usize,
);
let repr_packed = ::zerocopy::util::macro_util::core_reexport::option::Option::None;
DstLayout::new_zst(repr_align)
.extend(DstLayout::for_type::<T>(), repr_packed)
.extend(<U as KnownLayout>::LAYOUT, repr_packed)
.pad_to_align()
};
#[inline(always)]
fn raw_from_ptr_len(
bytes: ::zerocopy::util::macro_util::core_reexport::ptr::NonNull<u8>,
meta: Self::PointerMetadata,
) -> ::zerocopy::util::macro_util::core_reexport::ptr::NonNull<Self> {
use ::zerocopy::KnownLayout;
let trailing = <U as KnownLayout>::raw_from_ptr_len(bytes, meta);
let slf = trailing.as_ptr() as *mut Self;
unsafe {
::zerocopy::util::macro_util::core_reexport::ptr::NonNull::new_unchecked(
slf,
)
}
}
#[inline(always)]
fn pointer_to_metadata(ptr: *mut Self) -> Self::PointerMetadata {
<U>::pointer_to_metadata(ptr as *mut _)
}
}
#[allow(non_camel_case_types)]
struct __Zerocopy_Field_0;
#[allow(non_camel_case_types)]
struct __Zerocopy_Field_1;
unsafe impl<T, U> ::zerocopy::util::macro_util::Field<__Zerocopy_Field_0>
for Foo<T, U> {
type Type = T;
}
unsafe impl<T, U> ::zerocopy::util::macro_util::Field<__Zerocopy_Field_1>
for Foo<T, U> {
type Type = U;
}
#[repr(C)]
#[repr(align(2))]
#[doc(hidden)]
#[allow(private_bounds)]
struct __ZerocopyKnownLayoutMaybeUninit<T, U>(
::zerocopy::util::macro_util::core_reexport::mem::MaybeUninit<
<Foo<T, U> as ::zerocopy::util::macro_util::Field<__Zerocopy_Field_0>>::Type,
>,
::zerocopy::util::macro_util::core_reexport::mem::ManuallyDrop<
<<Foo<
T,
U,
> as ::zerocopy::util::macro_util::Field<
__Zerocopy_Field_1,
>>::Type as ::zerocopy::KnownLayout>::MaybeUninit
>,
)
where
<Foo<
T,
U,
> as ::zerocopy::util::macro_util::Field<
__Zerocopy_Field_1,
>>::Type: ::zerocopy::KnownLayout;
unsafe impl<T, U> ::zerocopy::KnownLayout for __ZerocopyKnownLayoutMaybeUninit<T, U>
where
<Foo<
T,
U,
> as ::zerocopy::util::macro_util::Field<
__Zerocopy_Field_1,
>>::Type: ::zerocopy::KnownLayout,
{
#[allow(clippy::missing_inline_in_public_items)]
fn only_derive_is_allowed_to_implement_this_trait() {}
type PointerMetadata = <Foo<T, U> as ::zerocopy::KnownLayout>::PointerMetadata;
type MaybeUninit = Self;
const LAYOUT: ::zerocopy::DstLayout = <Foo<
T,
U,
> as ::zerocopy::KnownLayout>::LAYOUT;
#[inline(always)]
fn raw_from_ptr_len(
bytes: ::zerocopy::util::macro_util::core_reexport::ptr::NonNull<u8>,
meta: Self::PointerMetadata,
) -> ::zerocopy::util::macro_util::core_reexport::ptr::NonNull<Self> {
use ::zerocopy::KnownLayout;
let trailing = <<<Foo<
T,
U,
> as ::zerocopy::util::macro_util::Field<
__Zerocopy_Field_1,
>>::Type as ::zerocopy::KnownLayout>::MaybeUninit as KnownLayout>::raw_from_ptr_len(
bytes,
meta,
);
let slf = trailing.as_ptr() as *mut Self;
unsafe {
::zerocopy::util::macro_util::core_reexport::ptr::NonNull::new_unchecked(
slf,
)
}
}
#[inline(always)]
fn pointer_to_metadata(ptr: *mut Self) -> Self::PointerMetadata {
<<<Foo<
T,
U,
> as ::zerocopy::util::macro_util::Field<
__Zerocopy_Field_1,
>>::Type as ::zerocopy::KnownLayout>::MaybeUninit>::pointer_to_metadata(
ptr as *mut _,
)
}
}
};
} no_build
}
}
#[test]
fn test_immutable() {
test! {
Immutable {
struct Foo;
} expands to {
#[allow(deprecated)]
#[automatically_derived]
unsafe impl ::zerocopy::Immutable for Foo {
fn only_derive_is_allowed_to_implement_this_trait() {}
}
} no_build
}
}
#[test]
fn test_try_from_bytes() {
test! {
TryFromBytes {
struct Foo;
} expands to {
#[allow(deprecated)]
#[automatically_derived]
unsafe impl ::zerocopy::TryFromBytes for Foo {
fn only_derive_is_allowed_to_implement_this_trait() {}
fn is_bit_valid<___ZerocopyAliasing>(
mut candidate: ::zerocopy::Maybe<Self, ___ZerocopyAliasing>,
) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool
where
___ZerocopyAliasing: ::zerocopy::pointer::invariant::Reference,
{
true
}
}
} no_build
}
}
#[test]
fn test_from_zeros() {
test! {
FromZeros {
struct Foo;
} expands to {
#[allow(deprecated)]
#[automatically_derived]
unsafe impl ::zerocopy::TryFromBytes for Foo {
fn only_derive_is_allowed_to_implement_this_trait() {}
fn is_bit_valid<___ZerocopyAliasing>(
mut candidate: ::zerocopy::Maybe<Self, ___ZerocopyAliasing>,
) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool
where
___ZerocopyAliasing: ::zerocopy::pointer::invariant::Reference,
{
true
}
}
#[allow(deprecated)]
#[automatically_derived]
unsafe impl ::zerocopy::FromZeros for Foo {
fn only_derive_is_allowed_to_implement_this_trait() {}
}
} no_build
}
}
#[test]
fn test_from_bytes_struct() {
test! {
FromBytes {
struct Foo;
} expands to {
#[allow(deprecated)]
#[automatically_derived]
unsafe impl ::zerocopy::TryFromBytes for Foo {
fn only_derive_is_allowed_to_implement_this_trait() {}
fn is_bit_valid<___ZerocopyAliasing>(
_candidate: ::zerocopy::Maybe<Self, ___ZerocopyAliasing>,
) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool
where
___ZerocopyAliasing: ::zerocopy::pointer::invariant::Reference,
{
if false {
fn assert_is_from_bytes<T>()
where
T: ::zerocopy::FromBytes,
T: ?::zerocopy::util::macro_util::core_reexport::marker::Sized,
{}
assert_is_from_bytes::<Self>();
}
true
}
}
#[allow(deprecated)]
#[automatically_derived]
unsafe impl ::zerocopy::FromZeros for Foo {
fn only_derive_is_allowed_to_implement_this_trait() {}
}
#[allow(deprecated)]
#[automatically_derived]
unsafe impl ::zerocopy::FromBytes for Foo {
fn only_derive_is_allowed_to_implement_this_trait() {}
}
} no_build
}
}
#[test]
fn test_from_bytes_union() {
test! {
FromBytes {
union Foo {
a: u8,
}
} expands to {
#[allow(deprecated)]
#[automatically_derived]
unsafe impl ::zerocopy::TryFromBytes for Foo
where
u8: ::zerocopy::TryFromBytes + ::zerocopy::Immutable,
{
fn only_derive_is_allowed_to_implement_this_trait() {}
fn is_bit_valid<___ZerocopyAliasing>(
_candidate: ::zerocopy::Maybe<Self, ___ZerocopyAliasing>,
) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool
where
___ZerocopyAliasing: ::zerocopy::pointer::invariant::Reference,
{
if false {
fn assert_is_from_bytes<T>()
where
T: ::zerocopy::FromBytes,
T: ?::zerocopy::util::macro_util::core_reexport::marker::Sized,
{}
assert_is_from_bytes::<Self>();
}
true
}
}
#[allow(deprecated)]
#[automatically_derived]
unsafe impl ::zerocopy::FromZeros for Foo
where
u8: ::zerocopy::FromZeros + ::zerocopy::Immutable,
{
fn only_derive_is_allowed_to_implement_this_trait() {}
}
#[allow(deprecated)]
#[automatically_derived]
unsafe impl ::zerocopy::FromBytes for Foo
where
u8: ::zerocopy::FromBytes + ::zerocopy::Immutable,
{
fn only_derive_is_allowed_to_implement_this_trait() {}
}
} no_build
}
}
#[test]
fn test_into_bytes() {
test! {
IntoBytes {
#[repr(C)]
struct Foo;
} expands to {
#[allow(deprecated)]
#[automatically_derived]
unsafe impl ::zerocopy::IntoBytes for Foo {
fn only_derive_is_allowed_to_implement_this_trait() {}
}
} no_build
}
test! {
IntoBytes {
#[repr(C)]
struct Foo {
a: u8,
b: u8,
}
} expands to {
#[allow(deprecated)]
#[automatically_derived]
unsafe impl ::zerocopy::IntoBytes for Foo
where
u8: ::zerocopy::IntoBytes,
u8: ::zerocopy::IntoBytes,
(): ::zerocopy::util::macro_util::PaddingFree<
Self,
{ ::zerocopy::struct_has_padding!(Self, [u8, u8]) },
>,
{
fn only_derive_is_allowed_to_implement_this_trait() {}
}
} no_build
}
}
#[test]
fn test_unaligned() {
test! {
Unaligned {
#[repr(C)]
struct Foo;
} expands to {
#[allow(deprecated)]
#[automatically_derived]
unsafe impl ::zerocopy::Unaligned for Foo {
fn only_derive_is_allowed_to_implement_this_trait() {}
}
} no_build
}
}
#[test]
fn test_try_from_bytes_enum() {
test! {
TryFromBytes {
#[repr(u8)]
enum ComplexWithGenerics<'a: 'static, const N: usize, X, Y: Deref>
where
X: Deref<Target = &'a [(X, Y); N]>,
{
UnitLike,
StructLike { a: u8, b: X, c: X::Target, d: Y::Target, e: [(X, Y); N] },
TupleLike(bool, Y, PhantomData<&'a [(X, Y); N]>),
}
} expands to {
#[allow(deprecated)]
#[automatically_derived]
unsafe impl<'a: 'static, const N: usize, X, Y: Deref> ::zerocopy::TryFromBytes
for ComplexWithGenerics<'a, { N }, X, Y>
where
X: Deref<Target = &'a [(X, Y); N]>,
u8: ::zerocopy::TryFromBytes,
X: ::zerocopy::TryFromBytes,
X::Target: ::zerocopy::TryFromBytes,
Y::Target: ::zerocopy::TryFromBytes,
[(X, Y); N]: ::zerocopy::TryFromBytes,
bool: ::zerocopy::TryFromBytes,
Y: ::zerocopy::TryFromBytes,
PhantomData<&'a [(X, Y); N]>: ::zerocopy::TryFromBytes,
{
fn only_derive_is_allowed_to_implement_this_trait() {}
fn is_bit_valid<___ZerocopyAliasing>(
mut candidate: ::zerocopy::Maybe<'_, Self, ___ZerocopyAliasing>,
) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool
where
___ZerocopyAliasing: ::zerocopy::pointer::invariant::Reference,
{
use ::zerocopy::util::macro_util::core_reexport;
#[repr(u8)]
#[allow(dead_code, non_camel_case_types)]
enum ___ZerocopyTag {
UnitLike,
StructLike,
TupleLike,
}
type ___ZerocopyTagPrimitive = ::zerocopy::util::macro_util::SizeToTag<
{ core_reexport::mem::size_of::<___ZerocopyTag>() },
>;
#[allow(non_upper_case_globals)]
const ___ZEROCOPY_TAG_UnitLike: ___ZerocopyTagPrimitive =
___ZerocopyTag::UnitLike as ___ZerocopyTagPrimitive;
#[allow(non_upper_case_globals)]
const ___ZEROCOPY_TAG_StructLike: ___ZerocopyTagPrimitive =
___ZerocopyTag::StructLike as ___ZerocopyTagPrimitive;
#[allow(non_upper_case_globals)]
const ___ZEROCOPY_TAG_TupleLike: ___ZerocopyTagPrimitive =
___ZerocopyTag::TupleLike as ___ZerocopyTagPrimitive;
type ___ZerocopyOuterTag = ();
type ___ZerocopyInnerTag = ___ZerocopyTag;
#[repr(C)]
#[allow(non_snake_case)]
struct ___ZerocopyVariantStruct_StructLike<'a: 'static, const N: usize, X, Y: Deref>(
core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>,
u8,
X,
X::Target,
Y::Target,
[(X, Y); N],
core_reexport::marker::PhantomData<ComplexWithGenerics<'a, N, X, Y>>,
)
where
X: Deref<Target = &'a [(X, Y); N]>;
#[allow(deprecated)]
#[automatically_derived]
unsafe impl<'a: 'static, const N: usize, X, Y: Deref> ::zerocopy::TryFromBytes
for ___ZerocopyVariantStruct_StructLike<'a, { N }, X, Y>
where
X: Deref<Target = &'a [(X, Y); N]>,
core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>: ::zerocopy::TryFromBytes,
u8: ::zerocopy::TryFromBytes,
X: ::zerocopy::TryFromBytes,
X::Target: ::zerocopy::TryFromBytes,
Y::Target: ::zerocopy::TryFromBytes,
[(X, Y); N]: ::zerocopy::TryFromBytes,
core_reexport::marker::PhantomData<ComplexWithGenerics<'a, N, X, Y>>:
::zerocopy::TryFromBytes,
{
fn only_derive_is_allowed_to_implement_this_trait() {}
fn is_bit_valid<___ZerocopyAliasing>(
mut candidate: ::zerocopy::Maybe<Self, ___ZerocopyAliasing>,
) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool
where
___ZerocopyAliasing: ::zerocopy::pointer::invariant::Reference,
{
true && {
let field_candidate = unsafe {
let project = |slf: *mut Self| {
::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).0)
};
candidate.reborrow().cast_unsized_unchecked(project)
};
<core_reexport::mem::MaybeUninit<
___ZerocopyInnerTag,
> as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate)
} && {
let field_candidate = unsafe {
let project = |slf: *mut Self| {
::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).1)
};
candidate.reborrow().cast_unsized_unchecked(project)
};
<u8 as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate)
} && {
let field_candidate = unsafe {
let project = |slf: *mut Self| {
::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).2)
};
candidate.reborrow().cast_unsized_unchecked(project)
};
<X as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate)
} && {
let field_candidate = unsafe {
let project = |slf: *mut Self| {
::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).3)
};
candidate.reborrow().cast_unsized_unchecked(project)
};
<X::Target as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate)
} && {
let field_candidate = unsafe {
let project = |slf: *mut Self| {
::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).4)
};
candidate.reborrow().cast_unsized_unchecked(project)
};
<Y::Target as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate)
} && {
let field_candidate = unsafe {
let project = |slf: *mut Self| {
::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).5)
};
candidate.reborrow().cast_unsized_unchecked(project)
};
<[(X, Y); N] as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate)
} && {
let field_candidate = unsafe {
let project = |slf: *mut Self| {
::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).6)
};
candidate.reborrow().cast_unsized_unchecked(project)
};
<core_reexport::marker::PhantomData<
ComplexWithGenerics<'a, N, X, Y>,
> as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate)
}
}
}
#[repr(C)]
#[allow(non_snake_case)]
struct ___ZerocopyVariantStruct_TupleLike<'a: 'static, const N: usize, X, Y: Deref>(
core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>,
bool,
Y,
PhantomData<&'a [(X, Y); N]>,
core_reexport::marker::PhantomData<ComplexWithGenerics<'a, N, X, Y>>,
)
where
X: Deref<Target = &'a [(X, Y); N]>;
#[allow(deprecated)]
#[automatically_derived]
unsafe impl<'a: 'static, const N: usize, X, Y: Deref> ::zerocopy::TryFromBytes
for ___ZerocopyVariantStruct_TupleLike<'a, { N }, X, Y>
where
X: Deref<Target = &'a [(X, Y); N]>,
core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>: ::zerocopy::TryFromBytes,
bool: ::zerocopy::TryFromBytes,
Y: ::zerocopy::TryFromBytes,
PhantomData<&'a [(X, Y); N]>: ::zerocopy::TryFromBytes,
core_reexport::marker::PhantomData<ComplexWithGenerics<'a, N, X, Y>>:
::zerocopy::TryFromBytes,
{
fn only_derive_is_allowed_to_implement_this_trait() {}
fn is_bit_valid<___ZerocopyAliasing>(
mut candidate: ::zerocopy::Maybe<Self, ___ZerocopyAliasing>,
) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool
where
___ZerocopyAliasing: ::zerocopy::pointer::invariant::Reference,
{
true && {
let field_candidate = unsafe {
let project = |slf: *mut Self| {
::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).0)
};
candidate.reborrow().cast_unsized_unchecked(project)
};
<core_reexport::mem::MaybeUninit<
___ZerocopyInnerTag,
> as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate)
} && {
let field_candidate = unsafe {
let project = |slf: *mut Self| {
::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).1)
};
candidate.reborrow().cast_unsized_unchecked(project)
};
<bool as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate)
} && {
let field_candidate = unsafe {
let project = |slf: *mut Self| {
::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).2)
};
candidate.reborrow().cast_unsized_unchecked(project)
};
<Y as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate)
} && {
let field_candidate = unsafe {
let project = |slf: *mut Self| {
::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).3)
};
candidate.reborrow().cast_unsized_unchecked(project)
};
<PhantomData<&'a [(X, Y); N]> as ::zerocopy::TryFromBytes>::is_bit_valid(
field_candidate,
)
} && {
let field_candidate = unsafe {
let project = |slf: *mut Self| {
::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).4)
};
candidate.reborrow().cast_unsized_unchecked(project)
};
<core_reexport::marker::PhantomData<
ComplexWithGenerics<'a, N, X, Y>,
> as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate)
}
}
}
#[repr(C)]
#[allow(non_snake_case)]
union ___ZerocopyVariants<'a: 'static, const N: usize, X, Y: Deref> {
__field_StructLike:
core_reexport::mem::ManuallyDrop<___ZerocopyVariantStruct_StructLike<'a, N, X, Y>>,
__field_TupleLike:
core_reexport::mem::ManuallyDrop<___ZerocopyVariantStruct_TupleLike<'a, N, X, Y>>,
__nonempty: (),
}
#[repr(C)]
struct ___ZerocopyRawEnum<'a: 'static, const N: usize, X, Y: Deref> {
tag: ___ZerocopyOuterTag,
variants: ___ZerocopyVariants<'a, N, X, Y>,
}
let tag = {
let tag_ptr = unsafe {
candidate.reborrow().cast_unsized_unchecked(|p: *mut Self| { p as *mut ___ZerocopyTagPrimitive })
};
let tag_ptr = unsafe { tag_ptr.assume_initialized() };
tag_ptr.bikeshed_recall_valid().read_unaligned::<::zerocopy::BecauseImmutable>()
};
let raw_enum = unsafe {
candidate.cast_unsized_unchecked(|p: *mut Self| { p as *mut ___ZerocopyRawEnum<'a, N, X, Y> })
};
let raw_enum = unsafe { raw_enum.assume_initialized() };
let variants = unsafe {
raw_enum.cast_unsized_unchecked(|p: *mut ___ZerocopyRawEnum<'a, N, X, Y>| {
core_reexport::ptr::addr_of_mut!((*p).variants)
})
};
#[allow(non_upper_case_globals)]
match tag {
___ZEROCOPY_TAG_UnitLike => true,
___ZEROCOPY_TAG_StructLike => {
let variant = unsafe {
variants.cast_unsized_unchecked(|p: *mut ___ZerocopyVariants<'a, N, X, Y>| {
p as *mut ___ZerocopyVariantStruct_StructLike<'a, N, X, Y>
})
};
let variant = unsafe { variant.assume_initialized() };
<___ZerocopyVariantStruct_StructLike<'a, N, X, Y> as ::zerocopy ::TryFromBytes>::is_bit_valid (
variant)
}
___ZEROCOPY_TAG_TupleLike => {
let variant = unsafe {
variants.cast_unsized_unchecked(|p: *mut ___ZerocopyVariants<'a, N, X, Y>| {
p as *mut ___ZerocopyVariantStruct_TupleLike<'a, N, X, Y>
})
};
let variant = unsafe { variant.assume_initialized() };
<___ZerocopyVariantStruct_TupleLike<'a, N, X, Y> as ::zerocopy ::TryFromBytes>::is_bit_valid (
variant)
}
_ => false,
}
}
}
} no_build
}
test! {
TryFromBytes {
#[repr(u32)]
enum ComplexWithGenerics<'a: 'static, const N: usize, X, Y: Deref>
where
X: Deref<Target = &'a [(X, Y); N]>,
{
UnitLike,
StructLike { a: u8, b: X, c: X::Target, d: Y::Target, e: [(X, Y); N] },
TupleLike(bool, Y, PhantomData<&'a [(X, Y); N]>),
}
} expands to {
#[allow(deprecated)]
#[automatically_derived]
unsafe impl<'a: 'static, const N: usize, X, Y: Deref> ::zerocopy::TryFromBytes
for ComplexWithGenerics<'a, { N }, X, Y>
where
X: Deref<Target = &'a [(X, Y); N]>,
u8: ::zerocopy::TryFromBytes,
X: ::zerocopy::TryFromBytes,
X::Target: ::zerocopy::TryFromBytes,
Y::Target: ::zerocopy::TryFromBytes,
[(X, Y); N]: ::zerocopy::TryFromBytes,
bool: ::zerocopy::TryFromBytes,
Y: ::zerocopy::TryFromBytes,
PhantomData<&'a [(X, Y); N]>: ::zerocopy::TryFromBytes,
{
fn only_derive_is_allowed_to_implement_this_trait() {}
fn is_bit_valid<___ZerocopyAliasing>(
mut candidate: ::zerocopy::Maybe<'_, Self, ___ZerocopyAliasing>,
) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool
where
___ZerocopyAliasing: ::zerocopy::pointer::invariant::Reference,
{
use ::zerocopy::util::macro_util::core_reexport;
#[repr(u32)]
#[allow(dead_code, non_camel_case_types)]
enum ___ZerocopyTag {
UnitLike,
StructLike,
TupleLike,
}
type ___ZerocopyTagPrimitive = ::zerocopy::util::macro_util::SizeToTag<
{ core_reexport::mem::size_of::<___ZerocopyTag>() },
>;
#[allow(non_upper_case_globals)]
const ___ZEROCOPY_TAG_UnitLike: ___ZerocopyTagPrimitive =
___ZerocopyTag::UnitLike as ___ZerocopyTagPrimitive;
#[allow(non_upper_case_globals)]
const ___ZEROCOPY_TAG_StructLike: ___ZerocopyTagPrimitive =
___ZerocopyTag::StructLike as ___ZerocopyTagPrimitive;
#[allow(non_upper_case_globals)]
const ___ZEROCOPY_TAG_TupleLike: ___ZerocopyTagPrimitive =
___ZerocopyTag::TupleLike as ___ZerocopyTagPrimitive;
type ___ZerocopyOuterTag = ();
type ___ZerocopyInnerTag = ___ZerocopyTag;
#[repr(C)]
#[allow(non_snake_case)]
struct ___ZerocopyVariantStruct_StructLike<'a: 'static, const N: usize, X, Y: Deref>(
core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>,
u8,
X,
X::Target,
Y::Target,
[(X, Y); N],
core_reexport::marker::PhantomData<ComplexWithGenerics<'a, N, X, Y>>,
)
where
X: Deref<Target = &'a [(X, Y); N]>;
#[allow(deprecated)]
#[automatically_derived]
unsafe impl<'a: 'static, const N: usize, X, Y: Deref> ::zerocopy::TryFromBytes
for ___ZerocopyVariantStruct_StructLike<'a, { N }, X, Y>
where
X: Deref<Target = &'a [(X, Y); N]>,
core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>: ::zerocopy::TryFromBytes,
u8: ::zerocopy::TryFromBytes,
X: ::zerocopy::TryFromBytes,
X::Target: ::zerocopy::TryFromBytes,
Y::Target: ::zerocopy::TryFromBytes,
[(X, Y); N]: ::zerocopy::TryFromBytes,
core_reexport::marker::PhantomData<ComplexWithGenerics<'a, N, X, Y>>:
::zerocopy::TryFromBytes,
{
fn only_derive_is_allowed_to_implement_this_trait() {}
fn is_bit_valid<___ZerocopyAliasing>(
mut candidate: ::zerocopy::Maybe<Self, ___ZerocopyAliasing>,
) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool
where
___ZerocopyAliasing: ::zerocopy::pointer::invariant::Reference,
{
true && {
let field_candidate = unsafe {
let project = |slf: *mut Self| {
::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).0)
};
candidate.reborrow().cast_unsized_unchecked(project)
};
<core_reexport::mem::MaybeUninit<
___ZerocopyInnerTag,
> as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate)
} && {
let field_candidate = unsafe {
let project = |slf: *mut Self| {
::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).1)
};
candidate.reborrow().cast_unsized_unchecked(project)
};
<u8 as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate)
} && {
let field_candidate = unsafe {
let project = |slf: *mut Self| {
::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).2)
};
candidate.reborrow().cast_unsized_unchecked(project)
};
<X as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate)
} && {
let field_candidate = unsafe {
let project = |slf: *mut Self| {
::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).3)
};
candidate.reborrow().cast_unsized_unchecked(project)
};
<X::Target as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate)
} && {
let field_candidate = unsafe {
let project = |slf: *mut Self| {
::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).4)
};
candidate.reborrow().cast_unsized_unchecked(project)
};
<Y::Target as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate)
} && {
let field_candidate = unsafe {
let project = |slf: *mut Self| {
::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).5)
};
candidate.reborrow().cast_unsized_unchecked(project)
};
<[(X, Y); N] as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate)
} && {
let field_candidate = unsafe {
let project = |slf: *mut Self| {
::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).6)
};
candidate.reborrow().cast_unsized_unchecked(project)
};
<core_reexport::marker::PhantomData<
ComplexWithGenerics<'a, N, X, Y>,
> as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate)
}
}
}
#[repr(C)]
#[allow(non_snake_case)]
struct ___ZerocopyVariantStruct_TupleLike<'a: 'static, const N: usize, X, Y: Deref>(
core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>,
bool,
Y,
PhantomData<&'a [(X, Y); N]>,
core_reexport::marker::PhantomData<ComplexWithGenerics<'a, N, X, Y>>,
)
where
X: Deref<Target = &'a [(X, Y); N]>;
#[allow(deprecated)]
#[automatically_derived]
unsafe impl<'a: 'static, const N: usize, X, Y: Deref> ::zerocopy::TryFromBytes
for ___ZerocopyVariantStruct_TupleLike<'a, { N }, X, Y>
where
X: Deref<Target = &'a [(X, Y); N]>,
core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>: ::zerocopy::TryFromBytes,
bool: ::zerocopy::TryFromBytes,
Y: ::zerocopy::TryFromBytes,
PhantomData<&'a [(X, Y); N]>: ::zerocopy::TryFromBytes,
core_reexport::marker::PhantomData<ComplexWithGenerics<'a, N, X, Y>>:
::zerocopy::TryFromBytes,
{
fn only_derive_is_allowed_to_implement_this_trait() {}
fn is_bit_valid<___ZerocopyAliasing>(
mut candidate: ::zerocopy::Maybe<Self, ___ZerocopyAliasing>,
) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool
where
___ZerocopyAliasing: ::zerocopy::pointer::invariant::Reference,
{
true && {
let field_candidate = unsafe {
let project = |slf: *mut Self| {
::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).0)
};
candidate.reborrow().cast_unsized_unchecked(project)
};
<core_reexport::mem::MaybeUninit<
___ZerocopyInnerTag,
> as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate)
} && {
let field_candidate = unsafe {
let project = |slf: *mut Self| {
::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).1)
};
candidate.reborrow().cast_unsized_unchecked(project)
};
<bool as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate)
} && {
let field_candidate = unsafe {
let project = |slf: *mut Self| {
::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).2)
};
candidate.reborrow().cast_unsized_unchecked(project)
};
<Y as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate)
} && {
let field_candidate = unsafe {
let project = |slf: *mut Self| {
::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).3)
};
candidate.reborrow().cast_unsized_unchecked(project)
};
<PhantomData<&'a [(X, Y); N]> as ::zerocopy::TryFromBytes>::is_bit_valid(
field_candidate,
)
} && {
let field_candidate = unsafe {
let project = |slf: *mut Self| {
::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).4)
};
candidate.reborrow().cast_unsized_unchecked(project)
};
<core_reexport::marker::PhantomData<
ComplexWithGenerics<'a, N, X, Y>,
> as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate)
}
}
}
#[repr(C)]
#[allow(non_snake_case)]
union ___ZerocopyVariants<'a: 'static, const N: usize, X, Y: Deref> {
__field_StructLike:
core_reexport::mem::ManuallyDrop<___ZerocopyVariantStruct_StructLike<'a, N, X, Y>>,
__field_TupleLike:
core_reexport::mem::ManuallyDrop<___ZerocopyVariantStruct_TupleLike<'a, N, X, Y>>,
__nonempty: (),
}
#[repr(C)]
struct ___ZerocopyRawEnum<'a: 'static, const N: usize, X, Y: Deref> {
tag: ___ZerocopyOuterTag,
variants: ___ZerocopyVariants<'a, N, X, Y>,
}
let tag = {
let tag_ptr = unsafe {
candidate.reborrow().cast_unsized_unchecked(|p: *mut Self| { p as *mut ___ZerocopyTagPrimitive })
};
let tag_ptr = unsafe { tag_ptr.assume_initialized() };
tag_ptr.bikeshed_recall_valid().read_unaligned::<::zerocopy::BecauseImmutable>()
};
let raw_enum = unsafe {
candidate.cast_unsized_unchecked(|p: *mut Self| { p as *mut ___ZerocopyRawEnum<'a, N, X, Y> })
};
let raw_enum = unsafe { raw_enum.assume_initialized() };
let variants = unsafe {
raw_enum.cast_unsized_unchecked(|p: *mut ___ZerocopyRawEnum<'a, N, X, Y>| {
core_reexport::ptr::addr_of_mut!((*p).variants)
})
};
#[allow(non_upper_case_globals)]
match tag {
___ZEROCOPY_TAG_UnitLike => true,
___ZEROCOPY_TAG_StructLike => {
let variant = unsafe {
variants.cast_unsized_unchecked(|p: *mut ___ZerocopyVariants<'a, N, X, Y>| {
p as *mut ___ZerocopyVariantStruct_StructLike<'a, N, X, Y>
})
};
let variant = unsafe { variant.assume_initialized() };
<___ZerocopyVariantStruct_StructLike<'a, N, X, Y> as ::zerocopy ::TryFromBytes>::is_bit_valid (
variant)
}
___ZEROCOPY_TAG_TupleLike => {
let variant = unsafe {
variants.cast_unsized_unchecked(|p: *mut ___ZerocopyVariants<'a, N, X, Y>| {
p as *mut ___ZerocopyVariantStruct_TupleLike<'a, N, X, Y>
})
};
let variant = unsafe { variant.assume_initialized() };
<___ZerocopyVariantStruct_TupleLike<'a, N, X, Y> as ::zerocopy ::TryFromBytes>::is_bit_valid (
variant)
}
_ => false,
}
}
}
} no_build
}
test! {
TryFromBytes {
#[repr(C)]
enum ComplexWithGenerics<'a: 'static, const N: usize, X, Y: Deref>
where
X: Deref<Target = &'a [(X, Y); N]>,
{
UnitLike,
StructLike { a: u8, b: X, c: X::Target, d: Y::Target, e: [(X, Y); N] },
TupleLike(bool, Y, PhantomData<&'a [(X, Y); N]>),
}
} expands to {
#[allow(deprecated)]
#[automatically_derived]
unsafe impl<'a: 'static, const N: usize, X, Y: Deref> ::zerocopy::TryFromBytes
for ComplexWithGenerics<'a, { N }, X, Y>
where
X: Deref<Target = &'a [(X, Y); N]>,
u8: ::zerocopy::TryFromBytes,
X: ::zerocopy::TryFromBytes,
X::Target: ::zerocopy::TryFromBytes,
Y::Target: ::zerocopy::TryFromBytes,
[(X, Y); N]: ::zerocopy::TryFromBytes,
bool: ::zerocopy::TryFromBytes,
Y: ::zerocopy::TryFromBytes,
PhantomData<&'a [(X, Y); N]>: ::zerocopy::TryFromBytes,
{
fn only_derive_is_allowed_to_implement_this_trait() {}
fn is_bit_valid<___ZerocopyAliasing>(
mut candidate: ::zerocopy::Maybe<'_, Self, ___ZerocopyAliasing>,
) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool
where
___ZerocopyAliasing: ::zerocopy::pointer::invariant::Reference,
{
use ::zerocopy::util::macro_util::core_reexport;
#[repr(C)]
#[allow(dead_code, non_camel_case_types)]
enum ___ZerocopyTag {
UnitLike,
StructLike,
TupleLike,
}
type ___ZerocopyTagPrimitive = ::zerocopy::util::macro_util::SizeToTag<
{ core_reexport::mem::size_of::<___ZerocopyTag>() },
>;
#[allow(non_upper_case_globals)]
const ___ZEROCOPY_TAG_UnitLike: ___ZerocopyTagPrimitive =
___ZerocopyTag::UnitLike as ___ZerocopyTagPrimitive;
#[allow(non_upper_case_globals)]
const ___ZEROCOPY_TAG_StructLike: ___ZerocopyTagPrimitive =
___ZerocopyTag::StructLike as ___ZerocopyTagPrimitive;
#[allow(non_upper_case_globals)]
const ___ZEROCOPY_TAG_TupleLike: ___ZerocopyTagPrimitive =
___ZerocopyTag::TupleLike as ___ZerocopyTagPrimitive;
type ___ZerocopyOuterTag = ___ZerocopyTag;
type ___ZerocopyInnerTag = ();
#[repr(C)]
#[allow(non_snake_case)]
struct ___ZerocopyVariantStruct_StructLike<'a: 'static, const N: usize, X, Y: Deref>(
core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>,
u8,
X,
X::Target,
Y::Target,
[(X, Y); N],
core_reexport::marker::PhantomData<ComplexWithGenerics<'a, N, X, Y>>,
)
where
X: Deref<Target = &'a [(X, Y); N]>;
#[allow(deprecated)]
#[automatically_derived]
unsafe impl<'a: 'static, const N: usize, X, Y: Deref> ::zerocopy::TryFromBytes
for ___ZerocopyVariantStruct_StructLike<'a, { N }, X, Y>
where
X: Deref<Target = &'a [(X, Y); N]>,
core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>: ::zerocopy::TryFromBytes,
u8: ::zerocopy::TryFromBytes,
X: ::zerocopy::TryFromBytes,
X::Target: ::zerocopy::TryFromBytes,
Y::Target: ::zerocopy::TryFromBytes,
[(X, Y); N]: ::zerocopy::TryFromBytes,
core_reexport::marker::PhantomData<ComplexWithGenerics<'a, N, X, Y>>:
::zerocopy::TryFromBytes,
{
fn only_derive_is_allowed_to_implement_this_trait() {}
fn is_bit_valid<___ZerocopyAliasing>(
mut candidate: ::zerocopy::Maybe<Self, ___ZerocopyAliasing>,
) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool
where
___ZerocopyAliasing: ::zerocopy::pointer::invariant::Reference,
{
true && {
let field_candidate = unsafe {
let project = |slf: *mut Self| {
::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).0)
};
candidate.reborrow().cast_unsized_unchecked(project)
};
<core_reexport::mem::MaybeUninit<
___ZerocopyInnerTag,
> as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate)
} && {
let field_candidate = unsafe {
let project = |slf: *mut Self| {
::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).1)
};
candidate.reborrow().cast_unsized_unchecked(project)
};
<u8 as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate)
} && {
let field_candidate = unsafe {
let project = |slf: *mut Self| {
::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).2)
};
candidate.reborrow().cast_unsized_unchecked(project)
};
<X as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate)
} && {
let field_candidate = unsafe {
let project = |slf: *mut Self| {
::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).3)
};
candidate.reborrow().cast_unsized_unchecked(project)
};
<X::Target as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate)
} && {
let field_candidate = unsafe {
let project = |slf: *mut Self| {
::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).4)
};
candidate.reborrow().cast_unsized_unchecked(project)
};
<Y::Target as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate)
} && {
let field_candidate = unsafe {
let project = |slf: *mut Self| {
::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).5)
};
candidate.reborrow().cast_unsized_unchecked(project)
};
<[(X, Y); N] as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate)
} && {
let field_candidate = unsafe {
let project = |slf: *mut Self| {
::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).6)
};
candidate.reborrow().cast_unsized_unchecked(project)
};
<core_reexport::marker::PhantomData<
ComplexWithGenerics<'a, N, X, Y>,
> as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate)
}
}
}
#[repr(C)]
#[allow(non_snake_case)]
struct ___ZerocopyVariantStruct_TupleLike<'a: 'static, const N: usize, X, Y: Deref>(
core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>,
bool,
Y,
PhantomData<&'a [(X, Y); N]>,
core_reexport::marker::PhantomData<ComplexWithGenerics<'a, N, X, Y>>,
)
where
X: Deref<Target = &'a [(X, Y); N]>;
#[allow(deprecated)]
#[automatically_derived]
unsafe impl<'a: 'static, const N: usize, X, Y: Deref> ::zerocopy::TryFromBytes
for ___ZerocopyVariantStruct_TupleLike<'a, { N }, X, Y>
where
X: Deref<Target = &'a [(X, Y); N]>,
core_reexport::mem::MaybeUninit<___ZerocopyInnerTag>: ::zerocopy::TryFromBytes,
bool: ::zerocopy::TryFromBytes,
Y: ::zerocopy::TryFromBytes,
PhantomData<&'a [(X, Y); N]>: ::zerocopy::TryFromBytes,
core_reexport::marker::PhantomData<ComplexWithGenerics<'a, N, X, Y>>:
::zerocopy::TryFromBytes,
{
fn only_derive_is_allowed_to_implement_this_trait() {}
fn is_bit_valid<___ZerocopyAliasing>(
mut candidate: ::zerocopy::Maybe<Self, ___ZerocopyAliasing>,
) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool
where
___ZerocopyAliasing: ::zerocopy::pointer::invariant::Reference,
{
true && {
let field_candidate = unsafe {
let project = |slf: *mut Self| {
::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).0)
};
candidate.reborrow().cast_unsized_unchecked(project)
};
<core_reexport::mem::MaybeUninit<
___ZerocopyInnerTag,
> as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate)
} && {
let field_candidate = unsafe {
let project = |slf: *mut Self| {
::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).1)
};
candidate.reborrow().cast_unsized_unchecked(project)
};
<bool as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate)
} && {
let field_candidate = unsafe {
let project = |slf: *mut Self| {
::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).2)
};
candidate.reborrow().cast_unsized_unchecked(project)
};
<Y as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate)
} && {
let field_candidate = unsafe {
let project = |slf: *mut Self| {
::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).3)
};
candidate.reborrow().cast_unsized_unchecked(project)
};
<PhantomData<&'a [(X, Y); N]> as ::zerocopy::TryFromBytes>::is_bit_valid(
field_candidate,
)
} && {
let field_candidate = unsafe {
let project = |slf: *mut Self| {
::zerocopy::util::macro_util::core_reexport::ptr::addr_of_mut!((*slf).4)
};
candidate.reborrow().cast_unsized_unchecked(project)
};
<core_reexport::marker::PhantomData<
ComplexWithGenerics<'a, N, X, Y>,
> as ::zerocopy::TryFromBytes>::is_bit_valid(field_candidate)
}
}
}
#[repr(C)]
#[allow(non_snake_case)]
union ___ZerocopyVariants<'a: 'static, const N: usize, X, Y: Deref> {
__field_StructLike:
core_reexport::mem::ManuallyDrop<___ZerocopyVariantStruct_StructLike<'a, N, X, Y>>,
__field_TupleLike:
core_reexport::mem::ManuallyDrop<___ZerocopyVariantStruct_TupleLike<'a, N, X, Y>>,
__nonempty: (),
}
#[repr(C)]
struct ___ZerocopyRawEnum<'a: 'static, const N: usize, X, Y: Deref> {
tag: ___ZerocopyOuterTag,
variants: ___ZerocopyVariants<'a, N, X, Y>,
}
let tag = {
let tag_ptr = unsafe {
candidate.reborrow().cast_unsized_unchecked(|p: *mut Self| { p as *mut ___ZerocopyTagPrimitive })
};
let tag_ptr = unsafe { tag_ptr.assume_initialized() };
tag_ptr.bikeshed_recall_valid().read_unaligned::<::zerocopy::BecauseImmutable>()
};
let raw_enum = unsafe {
candidate.cast_unsized_unchecked(|p: *mut Self| { p as *mut ___ZerocopyRawEnum<'a, N, X, Y> })
};
let raw_enum = unsafe { raw_enum.assume_initialized() };
let variants = unsafe {
raw_enum.cast_unsized_unchecked(|p: *mut ___ZerocopyRawEnum<'a, N, X, Y>| {
core_reexport::ptr::addr_of_mut!((*p).variants)
})
};
#[allow(non_upper_case_globals)]
match tag {
___ZEROCOPY_TAG_UnitLike => true,
___ZEROCOPY_TAG_StructLike => {
let variant = unsafe {
variants.cast_unsized_unchecked(|p: *mut ___ZerocopyVariants<'a, N, X, Y>| {
p as *mut ___ZerocopyVariantStruct_StructLike<'a, N, X, Y>
})
};
let variant = unsafe { variant.assume_initialized() };
<___ZerocopyVariantStruct_StructLike<'a, N, X, Y> as ::zerocopy ::TryFromBytes>::is_bit_valid (
variant)
}
___ZEROCOPY_TAG_TupleLike => {
let variant = unsafe {
variants.cast_unsized_unchecked(|p: *mut ___ZerocopyVariants<'a, N, X, Y>| {
p as *mut ___ZerocopyVariantStruct_TupleLike<'a, N, X, Y>
})
};
let variant = unsafe { variant.assume_initialized() };
<___ZerocopyVariantStruct_TupleLike<'a, N, X, Y> as ::zerocopy ::TryFromBytes>::is_bit_valid (
variant)
}
_ => false,
}
}
}
} no_build
}
}
// This goes at the bottom because it's so verbose and it makes scrolling past
// other code a pain.
#[test]
fn test_from_bytes_enum() {
test! {
FromBytes {
#[repr(u8)]
enum Foo {
Variant0,
Variant1,
Variant2,
Variant3,
Variant4,
Variant5,
Variant6,
Variant7,
Variant8,
Variant9,
Variant10,
Variant11,
Variant12,
Variant13,
Variant14,
Variant15,
Variant16,
Variant17,
Variant18,
Variant19,
Variant20,
Variant21,
Variant22,
Variant23,
Variant24,
Variant25,
Variant26,
Variant27,
Variant28,
Variant29,
Variant30,
Variant31,
Variant32,
Variant33,
Variant34,
Variant35,
Variant36,
Variant37,
Variant38,
Variant39,
Variant40,
Variant41,
Variant42,
Variant43,
Variant44,
Variant45,
Variant46,
Variant47,
Variant48,
Variant49,
Variant50,
Variant51,
Variant52,
Variant53,
Variant54,
Variant55,
Variant56,
Variant57,
Variant58,
Variant59,
Variant60,
Variant61,
Variant62,
Variant63,
Variant64,
Variant65,
Variant66,
Variant67,
Variant68,
Variant69,
Variant70,
Variant71,
Variant72,
Variant73,
Variant74,
Variant75,
Variant76,
Variant77,
Variant78,
Variant79,
Variant80,
Variant81,
Variant82,
Variant83,
Variant84,
Variant85,
Variant86,
Variant87,
Variant88,
Variant89,
Variant90,
Variant91,
Variant92,
Variant93,
Variant94,
Variant95,
Variant96,
Variant97,
Variant98,
Variant99,
Variant100,
Variant101,
Variant102,
Variant103,
Variant104,
Variant105,
Variant106,
Variant107,
Variant108,
Variant109,
Variant110,
Variant111,
Variant112,
Variant113,
Variant114,
Variant115,
Variant116,
Variant117,
Variant118,
Variant119,
Variant120,
Variant121,
Variant122,
Variant123,
Variant124,
Variant125,
Variant126,
Variant127,
Variant128,
Variant129,
Variant130,
Variant131,
Variant132,
Variant133,
Variant134,
Variant135,
Variant136,
Variant137,
Variant138,
Variant139,
Variant140,
Variant141,
Variant142,
Variant143,
Variant144,
Variant145,
Variant146,
Variant147,
Variant148,
Variant149,
Variant150,
Variant151,
Variant152,
Variant153,
Variant154,
Variant155,
Variant156,
Variant157,
Variant158,
Variant159,
Variant160,
Variant161,
Variant162,
Variant163,
Variant164,
Variant165,
Variant166,
Variant167,
Variant168,
Variant169,
Variant170,
Variant171,
Variant172,
Variant173,
Variant174,
Variant175,
Variant176,
Variant177,
Variant178,
Variant179,
Variant180,
Variant181,
Variant182,
Variant183,
Variant184,
Variant185,
Variant186,
Variant187,
Variant188,
Variant189,
Variant190,
Variant191,
Variant192,
Variant193,
Variant194,
Variant195,
Variant196,
Variant197,
Variant198,
Variant199,
Variant200,
Variant201,
Variant202,
Variant203,
Variant204,
Variant205,
Variant206,
Variant207,
Variant208,
Variant209,
Variant210,
Variant211,
Variant212,
Variant213,
Variant214,
Variant215,
Variant216,
Variant217,
Variant218,
Variant219,
Variant220,
Variant221,
Variant222,
Variant223,
Variant224,
Variant225,
Variant226,
Variant227,
Variant228,
Variant229,
Variant230,
Variant231,
Variant232,
Variant233,
Variant234,
Variant235,
Variant236,
Variant237,
Variant238,
Variant239,
Variant240,
Variant241,
Variant242,
Variant243,
Variant244,
Variant245,
Variant246,
Variant247,
Variant248,
Variant249,
Variant250,
Variant251,
Variant252,
Variant253,
Variant254,
Variant255,
}
} expands to {
#[allow(deprecated)]
#[automatically_derived]
unsafe impl ::zerocopy::TryFromBytes for Foo {
fn only_derive_is_allowed_to_implement_this_trait() {}
fn is_bit_valid<___ZerocopyAliasing>(
_candidate: ::zerocopy::Maybe<Self, ___ZerocopyAliasing>,
) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool
where
___ZerocopyAliasing: ::zerocopy::pointer::invariant::Reference,
{
if false {
fn assert_is_from_bytes<T>()
where
T: ::zerocopy::FromBytes,
T: ?::zerocopy::util::macro_util::core_reexport::marker::Sized,
{}
assert_is_from_bytes::<Self>();
}
true
}
}
#[allow(deprecated)]
#[automatically_derived]
unsafe impl ::zerocopy::FromZeros for Foo {
fn only_derive_is_allowed_to_implement_this_trait() {}
}
#[allow(deprecated)]
#[automatically_derived]
unsafe impl ::zerocopy::FromBytes for Foo {
fn only_derive_is_allowed_to_implement_this_trait() {}
}
} no_build
}
}
#[test]
fn test_try_from_bytes_trivial_is_bit_valid_enum() {
// Even when we aren't deriving `FromBytes` as the top-level trait,
// `TryFromBytes` on enums still detects whether we *could* derive
// `FromBytes`, and if so, performs the same "trivial `is_bit_valid`"
// optimization.
test! {
TryFromBytes {
#[repr(u8)]
enum Foo {
Variant0,
Variant1,
Variant2,
Variant3,
Variant4,
Variant5,
Variant6,
Variant7,
Variant8,
Variant9,
Variant10,
Variant11,
Variant12,
Variant13,
Variant14,
Variant15,
Variant16,
Variant17,
Variant18,
Variant19,
Variant20,
Variant21,
Variant22,
Variant23,
Variant24,
Variant25,
Variant26,
Variant27,
Variant28,
Variant29,
Variant30,
Variant31,
Variant32,
Variant33,
Variant34,
Variant35,
Variant36,
Variant37,
Variant38,
Variant39,
Variant40,
Variant41,
Variant42,
Variant43,
Variant44,
Variant45,
Variant46,
Variant47,
Variant48,
Variant49,
Variant50,
Variant51,
Variant52,
Variant53,
Variant54,
Variant55,
Variant56,
Variant57,
Variant58,
Variant59,
Variant60,
Variant61,
Variant62,
Variant63,
Variant64,
Variant65,
Variant66,
Variant67,
Variant68,
Variant69,
Variant70,
Variant71,
Variant72,
Variant73,
Variant74,
Variant75,
Variant76,
Variant77,
Variant78,
Variant79,
Variant80,
Variant81,
Variant82,
Variant83,
Variant84,
Variant85,
Variant86,
Variant87,
Variant88,
Variant89,
Variant90,
Variant91,
Variant92,
Variant93,
Variant94,
Variant95,
Variant96,
Variant97,
Variant98,
Variant99,
Variant100,
Variant101,
Variant102,
Variant103,
Variant104,
Variant105,
Variant106,
Variant107,
Variant108,
Variant109,
Variant110,
Variant111,
Variant112,
Variant113,
Variant114,
Variant115,
Variant116,
Variant117,
Variant118,
Variant119,
Variant120,
Variant121,
Variant122,
Variant123,
Variant124,
Variant125,
Variant126,
Variant127,
Variant128,
Variant129,
Variant130,
Variant131,
Variant132,
Variant133,
Variant134,
Variant135,
Variant136,
Variant137,
Variant138,
Variant139,
Variant140,
Variant141,
Variant142,
Variant143,
Variant144,
Variant145,
Variant146,
Variant147,
Variant148,
Variant149,
Variant150,
Variant151,
Variant152,
Variant153,
Variant154,
Variant155,
Variant156,
Variant157,
Variant158,
Variant159,
Variant160,
Variant161,
Variant162,
Variant163,
Variant164,
Variant165,
Variant166,
Variant167,
Variant168,
Variant169,
Variant170,
Variant171,
Variant172,
Variant173,
Variant174,
Variant175,
Variant176,
Variant177,
Variant178,
Variant179,
Variant180,
Variant181,
Variant182,
Variant183,
Variant184,
Variant185,
Variant186,
Variant187,
Variant188,
Variant189,
Variant190,
Variant191,
Variant192,
Variant193,
Variant194,
Variant195,
Variant196,
Variant197,
Variant198,
Variant199,
Variant200,
Variant201,
Variant202,
Variant203,
Variant204,
Variant205,
Variant206,
Variant207,
Variant208,
Variant209,
Variant210,
Variant211,
Variant212,
Variant213,
Variant214,
Variant215,
Variant216,
Variant217,
Variant218,
Variant219,
Variant220,
Variant221,
Variant222,
Variant223,
Variant224,
Variant225,
Variant226,
Variant227,
Variant228,
Variant229,
Variant230,
Variant231,
Variant232,
Variant233,
Variant234,
Variant235,
Variant236,
Variant237,
Variant238,
Variant239,
Variant240,
Variant241,
Variant242,
Variant243,
Variant244,
Variant245,
Variant246,
Variant247,
Variant248,
Variant249,
Variant250,
Variant251,
Variant252,
Variant253,
Variant254,
Variant255,
}
} expands to {
#[allow(deprecated)]
#[automatically_derived]
unsafe impl ::zerocopy::TryFromBytes for Foo {
fn only_derive_is_allowed_to_implement_this_trait() {}
fn is_bit_valid<___ZerocopyAliasing>(
_candidate: ::zerocopy::Maybe<Self, ___ZerocopyAliasing>,
) -> ::zerocopy::util::macro_util::core_reexport::primitive::bool
where
___ZerocopyAliasing: ::zerocopy::pointer::invariant::Reference,
{
true
}
}
} no_build
}
}
#[test]
fn test_hash() {
test! {
ByteHash {
struct Foo<T: Clone>(T) where Self: Sized;
} expands to {
#[allow(deprecated)]
#[automatically_derived]
impl<T: Clone> ::zerocopy::util::macro_util::core_reexport::hash::Hash for Foo<T>
where
Self: ::zerocopy::IntoBytes + ::zerocopy::Immutable,
Self: Sized,
{
fn hash<H>(&self, state: &mut H)
where
H: ::zerocopy::util::macro_util::core_reexport::hash::Hasher,
{
::zerocopy::util::macro_util::core_reexport::hash::Hasher::write(
state,
::zerocopy::IntoBytes::as_bytes(self)
)
}
fn hash_slice<H>(data: &[Self], state: &mut H)
where
H: ::zerocopy::util::macro_util::core_reexport::hash::Hasher,
{
::zerocopy::util::macro_util::core_reexport::hash::Hasher::write(
state,
::zerocopy::IntoBytes::as_bytes(data)
)
}
}
} no_build
}
}
#[test]
fn test_eq() {
test! {
ByteEq {
struct Foo<T: Clone>(T) where Self: Sized;
} expands to {
#[allow(deprecated)]
#[automatically_derived]
impl<T: Clone> ::zerocopy::util::macro_util::core_reexport::cmp::PartialEq for Foo<T>
where
Self: ::zerocopy::IntoBytes + ::zerocopy::Immutable,
Self: Sized,
{
fn eq(&self, other: &Self) -> bool {
::zerocopy::util::macro_util::core_reexport::cmp::PartialEq::eq(
::zerocopy::IntoBytes::as_bytes(self),
::zerocopy::IntoBytes::as_bytes(other),
)
}
}
#[allow(deprecated)]
#[automatically_derived]
impl<T: Clone> ::zerocopy::util::macro_util::core_reexport::cmp::Eq for Foo<T>
where
Self: ::zerocopy::IntoBytes + ::zerocopy::Immutable,
Self: Sized,
{
}
} no_build
}
}