Currently, we support either transmuting a byte slice of the exact size
of the target type or a single element from a prefix of a byte slice.
This adds support for transmuting from a byte slice to a slice of
elements, assuming appropriate traits are implemented.
Signed-off-by: Matthew Maurer <mmaurer@google.com>
---
rust/kernel/transmute.rs | 72 ++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 72 insertions(+)
diff --git a/rust/kernel/transmute.rs b/rust/kernel/transmute.rs
index be5dbf3829e25c92f85083cc0f4940f35bb7baec..5cc5f4fde4c31cea3c51ab078b4d68f3a0a2caa1 100644
--- a/rust/kernel/transmute.rs
+++ b/rust/kernel/transmute.rs
@@ -122,6 +122,78 @@ fn from_bytes_mut_prefix(bytes: &mut [u8]) -> Option<(&mut Self, &mut [u8])>
}
}
+ /// Converts a slice of bytes to a slice of `Self`.
+ ///
+ /// Succeeds if the reference is properly aligned, and the size of `bytes` is a multiple of that
+ /// of `Self`.
+ ///
+ /// Otherwise, returns [`None`].
+ fn from_bytes_to_slice(bytes: &[u8]) -> Option<&[Self]>
+ where
+ Self: Sized,
+ {
+ let size = size_of::<Self>();
+ if size == 0 {
+ return None;
+ }
+ if bytes.len() % size != 0 {
+ return None;
+ }
+ let len = bytes.len() / size;
+ let ptr = bytes.as_ptr().cast::<Self>();
+
+ #[allow(clippy::incompatible_msrv)]
+ if ptr.is_aligned() {
+ // SAFETY:
+ // - `ptr` is valid for reads of `bytes.len()` bytes, which is
+ // `len * size_of::<Self>()`.
+ // - `ptr` is aligned for `Self`.
+ // - `ptr` points to `len` consecutive properly initialized values of type `Self`
+ // because `Self` implements `FromBytes` (any bit pattern is valid).
+ // - The lifetime of the returned slice is bound to the input `bytes`.
+ unsafe { Some(core::slice::from_raw_parts(ptr, len)) }
+ } else {
+ None
+ }
+ }
+
+ /// Converts a mutable slice of bytes to a mutable slice of `Self`.
+ ///
+ /// Succeeds if the reference is properly aligned, and the size of `bytes` is a multiple of that
+ /// of `Self`.
+ ///
+ /// Otherwise, returns [`None`].
+ fn from_bytes_to_mut_slice(bytes: &mut [u8]) -> Option<&mut [Self]>
+ where
+ Self: AsBytes + Sized,
+ {
+ let size = size_of::<Self>();
+ if size == 0 {
+ return None;
+ }
+ if bytes.len() % size != 0 {
+ return None;
+ }
+ let len = bytes.len() / size;
+ let ptr = bytes.as_mut_ptr().cast::<Self>();
+
+ #[allow(clippy::incompatible_msrv)]
+ if ptr.is_aligned() {
+ // SAFETY:
+ // - `ptr` is valid for reads and writes of `bytes.len()` bytes, which is
+ // `len * size_of::<Self>()`.
+ // - `ptr` is aligned for `Self`.
+ // - `ptr` points to `len` consecutive properly initialized values of type `Self`
+ // because `Self` implements `FromBytes`.
+ // - `AsBytes` guarantees that writing a new `Self` to the resulting slice can safely
+ // be reflected as bytes in the original slice.
+ // - The lifetime of the returned slice is bound to the input `bytes`.
+ unsafe { Some(core::slice::from_raw_parts_mut(ptr, len)) }
+ } else {
+ None
+ }
+ }
+
/// Creates an owned instance of `Self` by copying `bytes`.
///
/// Unlike [`FromBytes::from_bytes`], which requires aligned input, this method can be used on
--
2.52.0.305.g3fc767764a-goog
Hi Matthew,
> On 15 Dec 2025, at 21:44, Matthew Maurer <mmaurer@google.com> wrote:
>
> Currently, we support either transmuting a byte slice of the exact size
> of the target type or a single element from a prefix of a byte slice.
>
> This adds support for transmuting from a byte slice to a slice of
> elements, assuming appropriate traits are implemented.
>
> Signed-off-by: Matthew Maurer <mmaurer@google.com>
> ---
> rust/kernel/transmute.rs | 72 ++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 72 insertions(+)
>
> diff --git a/rust/kernel/transmute.rs b/rust/kernel/transmute.rs
> index be5dbf3829e25c92f85083cc0f4940f35bb7baec..5cc5f4fde4c31cea3c51ab078b4d68f3a0a2caa1 100644
> --- a/rust/kernel/transmute.rs
> +++ b/rust/kernel/transmute.rs
> @@ -122,6 +122,78 @@ fn from_bytes_mut_prefix(bytes: &mut [u8]) -> Option<(&mut Self, &mut [u8])>
> }
> }
>
> + /// Converts a slice of bytes to a slice of `Self`.
> + ///
> + /// Succeeds if the reference is properly aligned, and the size of `bytes` is a multiple of that
> + /// of `Self`.
> + ///
> + /// Otherwise, returns [`None`].
> + fn from_bytes_to_slice(bytes: &[u8]) -> Option<&[Self]>
> + where
> + Self: Sized,
> + {
> + let size = size_of::<Self>();
> + if size == 0 {
> + return None;
> + }
> + if bytes.len() % size != 0 {
> + return None;
> + }
> + let len = bytes.len() / size;
> + let ptr = bytes.as_ptr().cast::<Self>();
> +
> + #[allow(clippy::incompatible_msrv)]
> + if ptr.is_aligned() {
> + // SAFETY:
> + // - `ptr` is valid for reads of `bytes.len()` bytes, which is
> + // `len * size_of::<Self>()`.
> + // - `ptr` is aligned for `Self`.
> + // - `ptr` points to `len` consecutive properly initialized values of type `Self`
> + // because `Self` implements `FromBytes` (any bit pattern is valid).
> + // - The lifetime of the returned slice is bound to the input `bytes`.
> + unsafe { Some(core::slice::from_raw_parts(ptr, len)) }
> + } else {
> + None
> + }
Nit: I’d rewrite this as
if !ptr.is_aligned() {
return None;
}
unsafe { Some(core::slice::from_raw_parts(ptr, len)) }
This saves one indentation level.
> + }
> +
> + /// Converts a mutable slice of bytes to a mutable slice of `Self`.
> + ///
> + /// Succeeds if the reference is properly aligned, and the size of `bytes` is a multiple of that
> + /// of `Self`.
> + ///
> + /// Otherwise, returns [`None`].
> + fn from_bytes_to_mut_slice(bytes: &mut [u8]) -> Option<&mut [Self]>
> + where
> + Self: AsBytes + Sized,
> + {
> + let size = size_of::<Self>();
> + if size == 0 {
> + return None;
> + }
> + if bytes.len() % size != 0 {
> + return None;
> + }
> + let len = bytes.len() / size;
> + let ptr = bytes.as_mut_ptr().cast::<Self>();
> +
> + #[allow(clippy::incompatible_msrv)]
> + if ptr.is_aligned() {
> + // SAFETY:
> + // - `ptr` is valid for reads and writes of `bytes.len()` bytes, which is
> + // `len * size_of::<Self>()`.
> + // - `ptr` is aligned for `Self`.
> + // - `ptr` points to `len` consecutive properly initialized values of type `Self`
> + // because `Self` implements `FromBytes`.
> + // - `AsBytes` guarantees that writing a new `Self` to the resulting slice can safely
> + // be reflected as bytes in the original slice.
> + // - The lifetime of the returned slice is bound to the input `bytes`.
> + unsafe { Some(core::slice::from_raw_parts_mut(ptr, len)) }
> + } else {
> + None
> + }
Same here.
> + }
> +
> /// Creates an owned instance of `Self` by copying `bytes`.
> ///
> /// Unlike [`FromBytes::from_bytes`], which requires aligned input, this method can be used on
>
> --
> 2.52.0.305.g3fc767764a-goog
>
>
Reviewed-by: Daniel Almeida <daniel.almeida@collabora.com>
On Wed, Dec 17, 2025 at 8:52 AM Daniel Almeida
<daniel.almeida@collabora.com> wrote:
>
> Hi Matthew,
>
> > On 15 Dec 2025, at 21:44, Matthew Maurer <mmaurer@google.com> wrote:
> >
> > Currently, we support either transmuting a byte slice of the exact size
> > of the target type or a single element from a prefix of a byte slice.
> >
> > This adds support for transmuting from a byte slice to a slice of
> > elements, assuming appropriate traits are implemented.
> >
> > Signed-off-by: Matthew Maurer <mmaurer@google.com>
> > ---
> > rust/kernel/transmute.rs | 72 ++++++++++++++++++++++++++++++++++++++++++++++++
> > 1 file changed, 72 insertions(+)
> >
> > diff --git a/rust/kernel/transmute.rs b/rust/kernel/transmute.rs
> > index be5dbf3829e25c92f85083cc0f4940f35bb7baec..5cc5f4fde4c31cea3c51ab078b4d68f3a0a2caa1 100644
> > --- a/rust/kernel/transmute.rs
> > +++ b/rust/kernel/transmute.rs
> > @@ -122,6 +122,78 @@ fn from_bytes_mut_prefix(bytes: &mut [u8]) -> Option<(&mut Self, &mut [u8])>
> > }
> > }
> >
> > + /// Converts a slice of bytes to a slice of `Self`.
> > + ///
> > + /// Succeeds if the reference is properly aligned, and the size of `bytes` is a multiple of that
> > + /// of `Self`.
> > + ///
> > + /// Otherwise, returns [`None`].
> > + fn from_bytes_to_slice(bytes: &[u8]) -> Option<&[Self]>
> > + where
> > + Self: Sized,
> > + {
> > + let size = size_of::<Self>();
> > + if size == 0 {
> > + return None;
> > + }
> > + if bytes.len() % size != 0 {
> > + return None;
> > + }
> > + let len = bytes.len() / size;
> > + let ptr = bytes.as_ptr().cast::<Self>();
> > +
> > + #[allow(clippy::incompatible_msrv)]
> > + if ptr.is_aligned() {
> > + // SAFETY:
> > + // - `ptr` is valid for reads of `bytes.len()` bytes, which is
> > + // `len * size_of::<Self>()`.
> > + // - `ptr` is aligned for `Self`.
> > + // - `ptr` points to `len` consecutive properly initialized values of type `Self`
> > + // because `Self` implements `FromBytes` (any bit pattern is valid).
> > + // - The lifetime of the returned slice is bound to the input `bytes`.
> > + unsafe { Some(core::slice::from_raw_parts(ptr, len)) }
> > + } else {
> > + None
> > + }
>
> Nit: I’d rewrite this as
>
> if !ptr.is_aligned() {
> return None;
> }
>
> unsafe { Some(core::slice::from_raw_parts(ptr, len)) }
>
> This saves one indentation level.
>
If this code were sizable, or if there were no unsafe, I'd agree with
you. However:
1. It makes the path condition for the `unsafe` block clearer - the if
condition directly guards the unsafe block, which makes it locally
obvious why it can assume "`ptr` is aligned for `Self`." With the
"check error and early return" strategy, you need to reason less
locally about the reachability of the statement.
2. The guarded code is one line long. If it were significant, then I
can see the point of using an early-return style in order to avoid
indentation, especially if the block *itself* had indentation. This is
one line.
3. This is coherent with `from_bytes_mut` and `from_bytes` in this
file, which also use this style.
> > + }
> > +
> > + /// Converts a mutable slice of bytes to a mutable slice of `Self`.
> > + ///
> > + /// Succeeds if the reference is properly aligned, and the size of `bytes` is a multiple of that
> > + /// of `Self`.
> > + ///
> > + /// Otherwise, returns [`None`].
> > + fn from_bytes_to_mut_slice(bytes: &mut [u8]) -> Option<&mut [Self]>
> > + where
> > + Self: AsBytes + Sized,
> > + {
> > + let size = size_of::<Self>();
> > + if size == 0 {
> > + return None;
> > + }
> > + if bytes.len() % size != 0 {
> > + return None;
> > + }
> > + let len = bytes.len() / size;
> > + let ptr = bytes.as_mut_ptr().cast::<Self>();
> > +
> > + #[allow(clippy::incompatible_msrv)]
> > + if ptr.is_aligned() {
> > + // SAFETY:
> > + // - `ptr` is valid for reads and writes of `bytes.len()` bytes, which is
> > + // `len * size_of::<Self>()`.
> > + // - `ptr` is aligned for `Self`.
> > + // - `ptr` points to `len` consecutive properly initialized values of type `Self`
> > + // because `Self` implements `FromBytes`.
> > + // - `AsBytes` guarantees that writing a new `Self` to the resulting slice can safely
> > + // be reflected as bytes in the original slice.
> > + // - The lifetime of the returned slice is bound to the input `bytes`.
> > + unsafe { Some(core::slice::from_raw_parts_mut(ptr, len)) }
> > + } else {
> > + None
> > + }
>
> Same here.
Same here :)
>
> > + }
> > +
> > /// Creates an owned instance of `Self` by copying `bytes`.
> > ///
> > /// Unlike [`FromBytes::from_bytes`], which requires aligned input, this method can be used on
> >
> > --
> > 2.52.0.305.g3fc767764a-goog
> >
> >
>
> Reviewed-by: Daniel Almeida <daniel.almeida@collabora.com>
>
© 2016 - 2026 Red Hat, Inc.