zerocopy_derive/derive/
unaligned.rs1use proc_macro2::{Span, TokenStream};
2use syn::{Data, DataEnum, DataStruct, DataUnion, Error};
3
4use crate::{
5 repr::{EnumRepr, StructUnionRepr},
6 util::{Ctx, FieldBounds, ImplBlockBuilder, Trait},
7};
8
9pub(crate) fn derive_unaligned(ctx: &Ctx, _top_level: Trait) -> Result<TokenStream, Error> {
10 match &ctx.ast.data {
11 Data::Struct(strct) => derive_unaligned_struct(ctx, strct),
12 Data::Enum(enm) => derive_unaligned_enum(ctx, enm),
13 Data::Union(unn) => derive_unaligned_union(ctx, unn),
14 }
15}
16
17fn derive_unaligned_struct(ctx: &Ctx, strct: &DataStruct) -> Result<TokenStream, Error> {
23 let repr = StructUnionRepr::from_attrs(&ctx.ast.attrs)?;
24 repr.unaligned_validate_no_align_gt_1()?;
25
26 let field_bounds = if repr.is_packed_1() {
27 FieldBounds::None
28 } else if repr.is_c() || repr.is_transparent() {
29 FieldBounds::ALL_SELF
30 } else {
31 return ctx.error_or_skip(Error::new(
32 Span::call_site(),
33 "must have #[repr(C)], #[repr(transparent)], or #[repr(packed)] attribute in order to guarantee this type's alignment",
34 ));
35 };
36
37 Ok(ImplBlockBuilder::new(ctx, strct, Trait::Unaligned, field_bounds).build())
38}
39
40fn derive_unaligned_enum(ctx: &Ctx, enm: &DataEnum) -> Result<TokenStream, Error> {
44 let repr = EnumRepr::from_attrs(&ctx.ast.attrs)?;
45 repr.unaligned_validate_no_align_gt_1()?;
46
47 if !repr.is_u8() && !repr.is_i8() {
48 return ctx.error_or_skip(Error::new(
49 Span::call_site(),
50 "must have #[repr(u8)] or #[repr(i8)] attribute in order to guarantee this type's alignment",
51 ));
52 }
53
54 Ok(ImplBlockBuilder::new(ctx, enm, Trait::Unaligned, FieldBounds::ALL_SELF).build())
55}
56
57fn derive_unaligned_union(ctx: &Ctx, unn: &DataUnion) -> Result<TokenStream, Error> {
63 let repr = StructUnionRepr::from_attrs(&ctx.ast.attrs)?;
64 repr.unaligned_validate_no_align_gt_1()?;
65
66 let field_type_trait_bounds = if repr.is_packed_1() {
67 FieldBounds::None
68 } else if repr.is_c() || repr.is_transparent() {
69 FieldBounds::ALL_SELF
70 } else {
71 return ctx.error_or_skip(Error::new(
72 Span::call_site(),
73 "must have #[repr(C)], #[repr(transparent)], or #[repr(packed)] attribute in order to guarantee this type's alignment",
74 ));
75 };
76
77 Ok(ImplBlockBuilder::new(ctx, unn, Trait::Unaligned, field_type_trait_bounds).build())
78}