rust/zerocopy-derive/derive/mod.rs

Source file repositories/reference/linux-study-clean/rust/zerocopy-derive/derive/mod.rs

File Facts

System
Linux kernel
Corpus path
rust/zerocopy-derive/derive/mod.rs
Extension
.rs
Size
5291 bytes
Lines
133
Domain
Rust Kernel Layer
Bucket
Rust API Membrane
Inferred role
Rust Kernel Layer: implementation source
Status
source implementation candidate

Why This File Exists

Rust-side wrappers and abstractions around kernel C APIs, ownership contracts, allocation, synchronization, and module integration.

Dependency Surface

Detected Declarations

Annotated Snippet

// SPDX-License-Identifier: (BSD-2-Clause OR Apache-2.0) OR MIT

pub mod from_bytes;
pub mod into_bytes;
pub mod known_layout;
pub mod try_from_bytes;
pub mod unaligned;

use proc_macro2::{Span, TokenStream};
use quote::quote;
use syn::{Data, Error};

use crate::{
    repr::StructUnionRepr,
    util::{Ctx, DataExt, FieldBounds, ImplBlockBuilder, Trait},
};

pub(crate) fn derive_immutable(ctx: &Ctx, _top_level: Trait) -> TokenStream {
    match &ctx.ast.data {
        Data::Struct(strct) => {
            ImplBlockBuilder::new(ctx, strct, Trait::Immutable, FieldBounds::ALL_SELF).build()
        }
        Data::Enum(enm) => {
            ImplBlockBuilder::new(ctx, enm, Trait::Immutable, FieldBounds::ALL_SELF).build()
        }
        Data::Union(unn) => {
            ImplBlockBuilder::new(ctx, unn, Trait::Immutable, FieldBounds::ALL_SELF).build()
        }
    }
}

pub(crate) fn derive_hash(ctx: &Ctx, _top_level: Trait) -> Result<TokenStream, Error> {
    // This doesn't delegate to `impl_block` because `impl_block` assumes it is
    // deriving a `zerocopy`-defined trait, and these trait impls share a common
    // shape that `Hash` does not. In particular, `zerocopy` traits contain a
    // method that only `zerocopy_derive` macros are supposed to implement, and
    // `impl_block` generating this trait method is incompatible with `Hash`.
    let type_ident = &ctx.ast.ident;
    let (impl_generics, ty_generics, where_clause) = ctx.ast.generics.split_for_impl();
    let where_predicates = where_clause.map(|clause| &clause.predicates);
    let zerocopy_crate = &ctx.zerocopy_crate;
    let core = ctx.core_path();
    Ok(quote! {
        impl #impl_generics #core::hash::Hash for #type_ident #ty_generics
        where
            Self: #zerocopy_crate::IntoBytes + #zerocopy_crate::Immutable,
            #where_predicates
        {
            fn hash<H: #core::hash::Hasher>(&self, state: &mut H) {
                #core::hash::Hasher::write(state, #zerocopy_crate::IntoBytes::as_bytes(self))
            }

            fn hash_slice<H: #core::hash::Hasher>(data: &[Self], state: &mut H) {
                #core::hash::Hasher::write(state, #zerocopy_crate::IntoBytes::as_bytes(data))
            }
        }
    })
}

pub(crate) fn derive_eq(ctx: &Ctx, _top_level: Trait) -> Result<TokenStream, Error> {
    // This doesn't delegate to `impl_block` because `impl_block` assumes it is
    // deriving a `zerocopy`-defined trait, and these trait impls share a common
    // shape that `Eq` does not. In particular, `zerocopy` traits contain a
    // method that only `zerocopy_derive` macros are supposed to implement, and
    // `impl_block` generating this trait method is incompatible with `Eq`.
    let type_ident = &ctx.ast.ident;
    let (impl_generics, ty_generics, where_clause) = ctx.ast.generics.split_for_impl();
    let where_predicates = where_clause.map(|clause| &clause.predicates);
    let zerocopy_crate = &ctx.zerocopy_crate;
    let core = ctx.core_path();
    Ok(quote! {
        impl #impl_generics #core::cmp::PartialEq for #type_ident #ty_generics
        where
            Self: #zerocopy_crate::IntoBytes + #zerocopy_crate::Immutable,
            #where_predicates
        {
            fn eq(&self, other: &Self) -> bool {
                #core::cmp::PartialEq::eq(
                    #zerocopy_crate::IntoBytes::as_bytes(self),
                    #zerocopy_crate::IntoBytes::as_bytes(other),
                )
            }
        }

        impl #impl_generics #core::cmp::Eq for #type_ident #ty_generics
        where
            Self: #zerocopy_crate::IntoBytes + #zerocopy_crate::Immutable,
            #where_predicates
        {
        }

Annotation

Implementation Notes