Skip to content

Commit 7203190

Browse files
Christian S. LimaGnurou
authored andcommitted
rust: transmute: Add methods for FromBytes trait
The two methods added take a slice of bytes and return those bytes in a specific type. These methods are useful when we need to transform the stream of bytes into specific type. Since the `is_aligned` method for pointer types has been stabilized in `1.79` version and is being used in this patch, I'm enabling the feature. In this case, using this method is useful to check the alignment and avoid a giant boilerplate, such as `(foo.as_ptr() as usize) % core::mem::align_of::<T>() == 0`. Also add `#[allow(clippy::incompatible_msrv)]` where needed until the MSRV is updated to `1.79`. Suggested-by: Benno Lossin <benno.lossin@proton.me> Link: Rust-for-Linux/linux#1119 Reviewed-by: Alice Ryhl <aliceryhl@google.com> Tested-by: Alexandre Courbot <acourbot@nvidia.com> Reviewed-by: Alexandre Courbot <acourbot@nvidia.com> Signed-off-by: Christian S. Lima <christiansantoslima21@gmail.com> Link: https://lore.kernel.org/r/20250824213134.27079-1-christiansantoslima21@gmail.com Acked-by: Miguel Ojeda <ojeda@kernel.org> [acourbot@nvidia.com: minor rewording of commit messages and doccomments] [acourbot@nvidia.com: revert slice implementation removal] [acourbot@nvidia.com: move incompatible_msrv clippy allow closer to site of need] [acourbot@nvidia.com: call the doctest method] Signed-off-by: Alexandre Courbot <acourbot@nvidia.com>
1 parent 331c24e commit 7203190

2 files changed

Lines changed: 69 additions & 1 deletion

File tree

rust/kernel/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
//
1919
// Stable since Rust 1.79.0.
2020
#![feature(inline_const)]
21+
#![feature(pointer_is_aligned)]
2122
//
2223
// Stable since Rust 1.81.0.
2324
#![feature(lint_reasons)]

rust/kernel/transmute.rs

Lines changed: 68 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,84 @@
22

33
//! Traits for transmuting types.
44
5+
use core::mem::size_of;
6+
57
/// Types for which any bit pattern is valid.
68
///
79
/// Not all types are valid for all values. For example, a `bool` must be either zero or one, so
810
/// reading arbitrary bytes into something that contains a `bool` is not okay.
911
///
1012
/// It's okay for the type to have padding, as initializing those bytes has no effect.
1113
///
14+
/// # Examples
15+
///
16+
/// ```
17+
/// use kernel::transmute::FromBytes;
18+
///
19+
/// # fn test() -> Option<()> {
20+
/// let raw = [1, 2, 3, 4];
21+
///
22+
/// let result = u32::from_bytes(&raw)?;
23+
///
24+
/// #[cfg(target_endian = "little")]
25+
/// assert_eq!(*result, 0x4030201);
26+
///
27+
/// #[cfg(target_endian = "big")]
28+
/// assert_eq!(*result, 0x1020304);
29+
///
30+
/// # Some(()) }
31+
/// # test().ok_or(EINVAL)?;
32+
/// # Ok::<(), Error>(())
33+
/// ```
34+
///
1235
/// # Safety
1336
///
1437
/// All bit-patterns must be valid for this type. This type must not have interior mutability.
15-
pub unsafe trait FromBytes {}
38+
pub unsafe trait FromBytes {
39+
/// Converts a slice of bytes to a reference to `Self`.
40+
///
41+
/// Succeeds if the reference is properly aligned, and the size of `bytes` is equal to that of
42+
/// `T` and different from zero.
43+
///
44+
/// Otherwise, returns [`None`].
45+
fn from_bytes(bytes: &[u8]) -> Option<&Self>
46+
where
47+
Self: Sized,
48+
{
49+
let slice_ptr = bytes.as_ptr().cast::<Self>();
50+
let size = size_of::<Self>();
51+
52+
#[allow(clippy::incompatible_msrv)]
53+
if bytes.len() == size && slice_ptr.is_aligned() {
54+
// SAFETY: Size and alignment were just checked.
55+
unsafe { Some(&*slice_ptr) }
56+
} else {
57+
None
58+
}
59+
}
60+
61+
/// Converts a mutable slice of bytes to a reference to `Self`.
62+
///
63+
/// Succeeds if the reference is properly aligned, and the size of `bytes` is equal to that of
64+
/// `T` and different from zero.
65+
///
66+
/// Otherwise, returns [`None`].
67+
fn from_bytes_mut(bytes: &mut [u8]) -> Option<&mut Self>
68+
where
69+
Self: AsBytes + Sized,
70+
{
71+
let slice_ptr = bytes.as_mut_ptr().cast::<Self>();
72+
let size = size_of::<Self>();
73+
74+
#[allow(clippy::incompatible_msrv)]
75+
if bytes.len() == size && slice_ptr.is_aligned() {
76+
// SAFETY: Size and alignment were just checked.
77+
unsafe { Some(&mut *slice_ptr) }
78+
} else {
79+
None
80+
}
81+
}
82+
}
1683

1784
macro_rules! impl_frombytes {
1885
($($({$($generics:tt)*})? $t:ty, )*) => {

0 commit comments

Comments
 (0)