From: Alexandre Courbot Date: Tue, 28 Oct 2025 15:07:36 +0000 (+0900) Subject: rust: transmute: add `from_bytes_prefix` family of methods X-Git-Tag: v6.19-rc1~157^2~8^2~47 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e4ead68a390511384d6af7bc9d00835dd6185e3b;p=thirdparty%2Fkernel%2Flinux.git rust: transmute: add `from_bytes_prefix` family of methods The `from_bytes*` family of functions expect a slice of the exact same size as the requested type. This can be sometimes cumbersome for callers that deal with dynamic stream of data that needs to be manually cut before each invocation of `from_bytes`. To simplify such callers, introduce a new `from_bytes*_prefix` family of methods, which split the input slice at the index required for the equivalent `from_bytes` method to succeed, and return its result alongside with the remainder of the slice. This design is inspired by zerocopy's `try_*_from_prefix` family of methods. Reviewed-by: Joel Fernandes Reviewed-by: Danilo Krummrich Reviewed-by: Alice Ryhl Acked-by: Danilo Krummrich Signed-off-by: Alexandre Courbot Message-ID: <20251029-nova-vbios-frombytes-v1-1-ac441ebc1de3@nvidia.com> Message-ID: <20251101-b4-frombytes-prefix-v1-1-0d9c1fd63b34@nvidia.com> --- diff --git a/rust/kernel/transmute.rs b/rust/kernel/transmute.rs index cfc37d81adf2e..be5dbf3829e25 100644 --- a/rust/kernel/transmute.rs +++ b/rust/kernel/transmute.rs @@ -58,6 +58,27 @@ pub unsafe trait FromBytes { } } + /// 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, + { + if bytes.len() < size_of::() { + None + } else { + // PANIC: We checked that `bytes.len() >= size_of::`, thus `split_at` cannot + // panic. + // TODO: replace with `split_at_checked` once the MSRV is >= 1.80. + let (prefix, remainder) = bytes.split_at(size_of::()); + + 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 @@ -80,6 +101,27 @@ pub unsafe trait FromBytes { } } + /// Converts the beginning of `bytes` to a mutable reference to `Self`. + /// + /// This method is similar to [`Self::from_bytes_mut`], 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_mut_prefix(bytes: &mut [u8]) -> Option<(&mut Self, &mut [u8])> + where + Self: AsBytes + Sized, + { + if bytes.len() < size_of::() { + None + } else { + // PANIC: We checked that `bytes.len() >= size_of::`, thus `split_at_mut` cannot + // panic. + // TODO: replace with `split_at_mut_checked` once the MSRV is >= 1.80. + let (prefix, remainder) = bytes.split_at_mut(size_of::()); + + Self::from_bytes_mut(prefix).map(|s| (s, remainder)) + } + } + /// Creates an owned instance of `Self` by copying `bytes`. /// /// Unlike [`FromBytes::from_bytes`], which requires aligned input, this method can be used on @@ -97,6 +139,27 @@ pub unsafe trait FromBytes { None } } + + /// Creates an owned instance of `Self` from the beginning of `bytes`. + /// + /// This method is similar to [`Self::from_bytes_copy`], 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_copy_prefix(bytes: &[u8]) -> Option<(Self, &[u8])> + where + Self: Sized, + { + if bytes.len() < size_of::() { + None + } else { + // PANIC: We checked that `bytes.len() >= size_of::`, thus `split_at` cannot + // panic. + // TODO: replace with `split_at_checked` once the MSRV is >= 1.80. + let (prefix, remainder) = bytes.split_at(size_of::()); + + Self::from_bytes_copy(prefix).map(|s| (s, remainder)) + } + } } macro_rules! impl_frombytes {