Files
linux/rust/zerocopy-derive/derive/unaligned.rs
Miguel Ojeda 5f85604cf0 rust: zerocopy-derive: add SPDX License Identifiers
Originally, when the Rust upstream `alloc` standard library crate was
vendored, the SPDX License Identifiers were added to every file so that
the license on those was clear. The same happened with the vendoring of
`proc_macro2`, `quote` and `syn`. Please see:

  commit 057b8d2571 ("rust: adapt `alloc` crate to the kernel")
  commit 69942c0a89 ("rust: syn: add SPDX License Identifiers")
  commit ddfa1b279d ("rust: quote: add SPDX License Identifiers")
  commit a9acfceb96 ("rust: proc-macro2: add SPDX License Identifiers")

Thus do the same for the `zerocopy-derive` crate.

This makes `scripts/spdxcheck.py` pass: use parentheses like commit
06e9bfc1e5 ("ionic: make spdxcheck.py happy") did since we have two
`OR` operators in the expression (three licenses).

Finally, as requested, I filed an issue [1] with upstream about it.

Cc: Joshua Liebow-Feeser <joshlf@google.com>
Cc: Jack Wrenn <jswrenn@google.com>
Link: https://github.com/google/zerocopy/issues/3428 [1]
Link: https://patch.msgid.link/20260608141439.182634-15-ojeda@kernel.org
Signed-off-by: Miguel Ojeda <ojeda@kernel.org>
2026-06-09 04:13:22 +02:00

81 lines
2.9 KiB
Rust

// SPDX-License-Identifier: (BSD-2-Clause OR Apache-2.0) OR MIT
use proc_macro2::{Span, TokenStream};
use syn::{Data, DataEnum, DataStruct, DataUnion, Error};
use crate::{
repr::{EnumRepr, StructUnionRepr},
util::{Ctx, FieldBounds, ImplBlockBuilder, Trait},
};
pub(crate) fn derive_unaligned(ctx: &Ctx, _top_level: Trait) -> Result<TokenStream, Error> {
match &ctx.ast.data {
Data::Struct(strct) => derive_unaligned_struct(ctx, strct),
Data::Enum(enm) => derive_unaligned_enum(ctx, enm),
Data::Union(unn) => derive_unaligned_union(ctx, unn),
}
}
/// A struct is `Unaligned` if:
/// - `repr(align)` is no more than 1 and either
/// - `repr(C)` or `repr(transparent)` and
/// - all fields `Unaligned`
/// - `repr(packed)`
fn derive_unaligned_struct(ctx: &Ctx, strct: &DataStruct) -> Result<TokenStream, Error> {
let repr = StructUnionRepr::from_attrs(&ctx.ast.attrs)?;
repr.unaligned_validate_no_align_gt_1()?;
let field_bounds = if repr.is_packed_1() {
FieldBounds::None
} else if repr.is_c() || repr.is_transparent() {
FieldBounds::ALL_SELF
} else {
return ctx.error_or_skip(Error::new(
Span::call_site(),
"must have #[repr(C)], #[repr(transparent)], or #[repr(packed)] attribute in order to guarantee this type's alignment",
));
};
Ok(ImplBlockBuilder::new(ctx, strct, Trait::Unaligned, field_bounds).build())
}
/// An enum is `Unaligned` if:
/// - No `repr(align(N > 1))`
/// - `repr(u8)` or `repr(i8)`
fn derive_unaligned_enum(ctx: &Ctx, enm: &DataEnum) -> Result<TokenStream, Error> {
let repr = EnumRepr::from_attrs(&ctx.ast.attrs)?;
repr.unaligned_validate_no_align_gt_1()?;
if !repr.is_u8() && !repr.is_i8() {
return ctx.error_or_skip(Error::new(
Span::call_site(),
"must have #[repr(u8)] or #[repr(i8)] attribute in order to guarantee this type's alignment",
));
}
Ok(ImplBlockBuilder::new(ctx, enm, Trait::Unaligned, FieldBounds::ALL_SELF).build())
}
/// Like structs, a union is `Unaligned` if:
/// - `repr(align)` is no more than 1 and either
/// - `repr(C)` or `repr(transparent)` and
/// - all fields `Unaligned`
/// - `repr(packed)`
fn derive_unaligned_union(ctx: &Ctx, unn: &DataUnion) -> Result<TokenStream, Error> {
let repr = StructUnionRepr::from_attrs(&ctx.ast.attrs)?;
repr.unaligned_validate_no_align_gt_1()?;
let field_type_trait_bounds = if repr.is_packed_1() {
FieldBounds::None
} else if repr.is_c() || repr.is_transparent() {
FieldBounds::ALL_SELF
} else {
return ctx.error_or_skip(Error::new(
Span::call_site(),
"must have #[repr(C)], #[repr(transparent)], or #[repr(packed)] attribute in order to guarantee this type's alignment",
));
};
Ok(ImplBlockBuilder::new(ctx, unn, Trait::Unaligned, field_type_trait_bounds).build())
}