rust/zerocopy-derive/derive/from_bytes.rs

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

File Facts

System
Linux kernel
Corpus path
rust/zerocopy-derive/derive/from_bytes.rs
Extension
.rs
Size
8656 bytes
Lines
193
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

for (i, v) in enm.variants.iter().enumerate() {
        match v.discriminant.as_ref() {
            // Implicit discriminant
            None => {
                match next_negative_discriminant.as_mut() {
                    Some(0) => return Ok(i),
                    // n is nonzero so subtraction is always safe
                    Some(n) => *n -= 1,
                    None => (),
                }
            }
            // Explicit positive discriminant
            Some((_, Expr::Lit(ExprLit { lit: Lit::Int(int), .. }))) => {
                match int.base10_parse::<u128>().ok() {
                    Some(0) => return Ok(i),
                    Some(_) => next_negative_discriminant = None,
                    None => {
                        // Numbers should never fail to parse, but just in case:
                        has_unknown_discriminants = true;
                        next_negative_discriminant = None;
                    }
                }
            }
            // Explicit negative discriminant
            Some((_, Expr::Unary(ExprUnary { op: UnOp::Neg(_), expr, .. }))) => match &**expr {
                Expr::Lit(ExprLit { lit: Lit::Int(int), .. }) => {
                    match int.base10_parse::<u128>().ok() {
                        Some(0) => return Ok(i),
                        // x is nonzero so subtraction is always safe
                        Some(x) => next_negative_discriminant = Some(x - 1),
                        None => {
                            // Numbers should never fail to parse, but just in
                            // case:
                            has_unknown_discriminants = true;
                            next_negative_discriminant = None;
                        }
                    }
                }
                // Unknown negative discriminant (e.g. const repr)
                _ => {
                    has_unknown_discriminants = true;
                    next_negative_discriminant = None;
                }
            },
            // Unknown discriminant (e.g. const expr)
            _ => {
                has_unknown_discriminants = true;
                next_negative_discriminant = None;
            }
        }
    }

    Err(has_unknown_discriminants)
}
pub(crate) fn derive_from_zeros(ctx: &Ctx, top_level: Trait) -> Result<TokenStream, Error> {
    let try_from_bytes = derive_try_from_bytes(ctx, top_level)?;
    let from_zeros = match &ctx.ast.data {
        Data::Struct(strct) => derive_from_zeros_struct(ctx, strct),
        Data::Enum(enm) => derive_from_zeros_enum(ctx, enm)?,
        Data::Union(unn) => derive_from_zeros_union(ctx, unn),
    };
    Ok(IntoIterator::into_iter([try_from_bytes, from_zeros]).collect())
}
pub(crate) fn derive_from_bytes(ctx: &Ctx, top_level: Trait) -> Result<TokenStream, Error> {
    let from_zeros = derive_from_zeros(ctx, top_level)?;
    let from_bytes = match &ctx.ast.data {
        Data::Struct(strct) => derive_from_bytes_struct(ctx, strct),
        Data::Enum(enm) => derive_from_bytes_enum(ctx, enm)?,
        Data::Union(unn) => derive_from_bytes_union(ctx, unn),
    };

    Ok(IntoIterator::into_iter([from_zeros, from_bytes]).collect())
}
fn derive_from_zeros_struct(ctx: &Ctx, strct: &DataStruct) -> TokenStream {
    ImplBlockBuilder::new(ctx, strct, Trait::FromZeros, FieldBounds::ALL_SELF).build()
}
fn derive_from_zeros_enum(ctx: &Ctx, enm: &DataEnum) -> Result<TokenStream, Error> {
    let repr = EnumRepr::from_attrs(&ctx.ast.attrs)?;

    // We don't actually care what the repr is; we just care that it's one of
    // the allowed ones.
    match repr {
        Repr::Compound(Spanned { t: CompoundRepr::C | CompoundRepr::Primitive(_), span: _ }, _) => {
        }
        Repr::Transparent(_) | Repr::Compound(Spanned { t: CompoundRepr::Rust, span: _ }, _) => {
            return ctx.error_or_skip(
                Error::new(
                    Span::call_site(),
                    "must have #[repr(C)] or #[repr(Int)] attribute in order to guarantee this type's memory layout",
                ),

Annotation

Implementation Notes