rust/kernel/transmute.rs

Source file repositories/reference/linux-study-clean/rust/kernel/transmute.rs

File Facts

System
Linux kernel
Corpus path
rust/kernel/transmute.rs
Extension
.rs
Size
8182 bytes
Lines
230
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: GPL-2.0

//! Traits for transmuting types.

use core::mem::size_of;

/// Types for which any bit pattern is valid.
///
/// Not all types are valid for all values. For example, a `bool` must be either zero or one, so
/// reading arbitrary bytes into something that contains a `bool` is not okay.
///
/// It's okay for the type to have padding, as initializing those bytes has no effect.
///
/// # Examples
///
/// ```
/// use kernel::transmute::FromBytes;
///
/// # fn test() -> Option<()> {
/// let raw = [1, 2, 3, 4];
///
/// let result = u32::from_bytes(&raw)?;
///
/// #[cfg(target_endian = "little")]
/// assert_eq!(*result, 0x4030201);
///
/// #[cfg(target_endian = "big")]
/// assert_eq!(*result, 0x1020304);
///
/// # Some(()) }
/// # test().ok_or(EINVAL)?;
/// # Ok::<(), Error>(())
/// ```
///
/// # Safety
///
/// All bit-patterns must be valid for this type. This type must not have interior mutability.
pub unsafe trait FromBytes {
    /// Converts a slice of bytes to a reference to `Self`.
    ///
    /// Succeeds if the reference is properly aligned, and the size of `bytes` is equal to that of
    /// `T` and different from zero.
    ///
    /// Otherwise, returns [`None`].
    fn from_bytes(bytes: &[u8]) -> Option<&Self>
    where
        Self: Sized,
    {
        let slice_ptr = bytes.as_ptr().cast::<Self>();
        let size = size_of::<Self>();

        if bytes.len() == size && slice_ptr.is_aligned() {
            // SAFETY: Size and alignment were just checked.
            unsafe { Some(&*slice_ptr) }
        } else {
            None
        }
    }

    /// Converts the beginning of `bytes` to a reference to `Self`.
    ///
    /// This method is similar to [`Self::from_bytes`], with the difference that `bytes` does not
    /// need to be the same size of `Self` - the appropriate portion is cut from the beginning of
    /// `bytes`, and the remainder returned alongside `Self`.
    fn from_bytes_prefix(bytes: &[u8]) -> Option<(&Self, &[u8])>
    where
        Self: Sized,
    {
        let (prefix, remainder) = bytes.split_at_checked(size_of::<Self>())?;

        Self::from_bytes(prefix).map(|s| (s, remainder))
    }

    /// Converts a mutable slice of bytes to a reference to `Self`.
    ///
    /// Succeeds if the reference is properly aligned, and the size of `bytes` is equal to that of
    /// `T` and different from zero.
    ///
    /// Otherwise, returns [`None`].
    fn from_bytes_mut(bytes: &mut [u8]) -> Option<&mut Self>
    where
        Self: AsBytes + Sized,
    {
        let slice_ptr = bytes.as_mut_ptr().cast::<Self>();
        let size = size_of::<Self>();

        if bytes.len() == size && slice_ptr.is_aligned() {
            // SAFETY: Size and alignment were just checked.
            unsafe { Some(&mut *slice_ptr) }
        } else {

Annotation

Implementation Notes