[PATCH] rust: transmute: Add implementation for FromBytes trait

From: Christian dos Santos de Lima
Date: Tue Oct 08 2024 - 21:48:26 EST


Add implementation and documentation for FromBytes trait.

Add new feature block in order to allow using ToBytes
and bound to from_bytes_mut function.

Link: https://github.com/Rust-for-Linux/linux/issues/1119
Signed-off-by: Christian dos Santos de Lima <christiansantoslima21@xxxxxxxxx>
---
rust/kernel/lib.rs | 2 +
rust/kernel/transmute.rs | 302 +++++++++++++++++++++++++++++++++++++--
2 files changed, 290 insertions(+), 14 deletions(-)

diff --git a/rust/kernel/lib.rs b/rust/kernel/lib.rs
index dc37aef6a008..5215f5744e12 100644
--- a/rust/kernel/lib.rs
+++ b/rust/kernel/lib.rs
@@ -18,6 +18,8 @@
#![feature(lint_reasons)]
#![feature(new_uninit)]
#![feature(unsize)]
+#![feature(portable_simd)]
+#![feature(trivial_bounds)]

// Ensure conditional compilation based on the kernel configuration works;
// otherwise we may silently break things like initcall handling.
diff --git a/rust/kernel/transmute.rs b/rust/kernel/transmute.rs
index 1c7d43771a37..f2d99c136017 100644
--- a/rust/kernel/transmute.rs
+++ b/rust/kernel/transmute.rs
@@ -12,24 +12,298 @@
/// # Safety
///
/// All bit-patterns must be valid for this type. This type must not have interior mutability.
-pub unsafe trait FromBytes {}
+pub unsafe trait FromBytes {
+ ///Converts a slice of Bytes into a Reference to Self
+ ///
+ /// # Examples
+ /// ```
+ /// pub unsafe trait FromBytes {
+ /// unsafe fn from_bytes(slice_of_bytes: &[u8]) -> &Self;
+ /// unsafe fn from_bytes_mut(slice_of_bytes: &mut [u8]) -> &mut Self
+ /// where
+ /// Self: ToBytes;
+ /// }
+ ///
+ ///unsafe impl FromBytes for u32 {
+ /// unsafe fn from_bytes(slice_of_bytes: &[u8]) -> &Self {
+ /// let slice_ptr = slice_of_bytes.as_ptr() as *const Self;
+ /// &*slice_ptr
+ /// }
+ ///
+ /// unsafe fn from_bytes_mut(slice_of_bytes: &mut [u8]) -> &mut Self
+ /// where
+ /// Self: ToBytes,
+ /// {
+ /// let slice_ptr = slice_of_bytes.as_mut_ptr() as *mut Self;
+ /// &mut *slice_ptr
+ /// }
+ ///}
+ ///
+ ///let slice_of_bytes : &[u8] = &[1, 2, 3, 4];
+ ///let result = u32::from_bytes(slice_of_bytes);
+ ///assert_eq!(*result, 0x4030201);
+ ///```
+ ///# Safety
+ ///
+ ///Guarantee that all values are initiliazed
+ unsafe fn from_bytes(slice_of_bytes: &[u8]) -> &Self;
+ ///Converts a mutabble slice of Bytes into a mutable Reference to Self
+ /// # Safety
+ ///
+ /// ToBytes in order to allow only types that implements ToBytes
+ unsafe fn from_bytes_mut(slice_of_bytes: &mut [u8]) -> &mut Self
+ where
+ Self: ToBytes;
+}

-macro_rules! impl_frombytes {
- ($($({$($generics:tt)*})? $t:ty, )*) => {
- // SAFETY: Safety comments written in the macro invocation.
- $(unsafe impl$($($generics)*)? FromBytes for $t {})*
- };
+// SAFETY: All bit patterns are acceptable values of the types below.
+unsafe impl FromBytes for u8 {
+ unsafe fn from_bytes(slice_of_bytes: &[u8]) -> &Self {
+ unsafe {
+ let slice_ptr = slice_of_bytes.as_ptr() as *const Self;
+ &*slice_ptr
+ }
+ }
+
+ unsafe fn from_bytes_mut(slice_of_bytes: &mut [u8]) -> &mut Self
+ where
+ Self: ToBytes,
+ {
+ unsafe {
+ let slice_ptr = slice_of_bytes.as_mut_ptr() as *mut Self;
+ &mut *slice_ptr
+ }
+ }
}

-impl_frombytes! {
- // SAFETY: All bit patterns are acceptable values of the types below.
- u8, u16, u32, u64, usize,
- i8, i16, i32, i64, isize,
+unsafe impl FromBytes for u16 {
+ unsafe fn from_bytes(slice_of_bytes: &[u8]) -> &Self {
+ unsafe {
+ let slice_ptr = slice_of_bytes.as_ptr() as *const Self;
+ &*slice_ptr
+ }
+ }
+
+ unsafe fn from_bytes_mut(slice_of_bytes: &mut [u8]) -> &mut Self
+ where
+ Self: ToBytes,
+ {
+ unsafe {
+ let slice_ptr = slice_of_bytes.as_mut_ptr() as *mut Self;
+ &mut *slice_ptr
+ }
+ }
+}
+
+unsafe impl FromBytes for u32 {
+ unsafe fn from_bytes(slice_of_bytes: &[u8]) -> &Self {
+ unsafe {
+ let slice_ptr = slice_of_bytes.as_ptr() as *const Self;
+ &*slice_ptr
+ }
+ }
+
+ unsafe fn from_bytes_mut(slice_of_bytes: &mut [u8]) -> &mut Self
+ where
+ Self: ToBytes,
+ {
+ unsafe {
+ let slice_ptr = slice_of_bytes.as_mut_ptr() as *mut Self;
+ &mut *slice_ptr
+ }
+ }
+}
+
+unsafe impl FromBytes for u64 {
+ unsafe fn from_bytes(slice_of_bytes: &[u8]) -> &Self {
+ unsafe {
+ let slice_ptr = slice_of_bytes.as_ptr() as *const Self;
+ &*slice_ptr
+ }
+ }
+
+ unsafe fn from_bytes_mut(slice_of_bytes: &mut [u8]) -> &mut Self
+ where
+ Self: ToBytes,
+ {
+ unsafe {
+ let slice_ptr = slice_of_bytes.as_mut_ptr() as *mut Self;
+ &mut *slice_ptr
+ }
+ }
+}
+
+unsafe impl FromBytes for usize {
+ unsafe fn from_bytes(slice_of_bytes: &[u8]) -> &Self {
+ unsafe {
+ let slice_ptr = slice_of_bytes.as_ptr() as *const Self;
+ &*slice_ptr
+ }
+ }
+
+ unsafe fn from_bytes_mut(slice_of_bytes: &mut [u8]) -> &mut Self
+ where
+ Self: ToBytes,
+ {
+ unsafe {
+ let slice_ptr = slice_of_bytes.as_mut_ptr() as *mut Self;
+ &mut *slice_ptr
+ }
+ }
+}
+
+unsafe impl FromBytes for i8 {
+ unsafe fn from_bytes(slice_of_bytes: &[u8]) -> &Self {
+ unsafe {
+ let slice_ptr = slice_of_bytes.as_ptr() as *const Self;
+ &*slice_ptr
+ }
+ }
+
+ unsafe fn from_bytes_mut(slice_of_bytes: &mut [u8]) -> &mut Self
+ where
+ Self: ToBytes,
+ {
+ unsafe {
+ let slice_ptr = slice_of_bytes.as_mut_ptr() as *mut Self;
+ &mut *slice_ptr
+ }
+ }
+}
+
+unsafe impl FromBytes for i16 {
+ unsafe fn from_bytes(slice_of_bytes: &[u8]) -> &Self {
+ unsafe {
+ let slice_ptr = slice_of_bytes.as_ptr() as *const Self;
+ &*slice_ptr
+ }
+ }
+
+ unsafe fn from_bytes_mut(slice_of_bytes: &mut [u8]) -> &mut Self
+ where
+ Self: ToBytes,
+ {
+ unsafe {
+ let slice_ptr = slice_of_bytes.as_mut_ptr() as *mut Self;
+ &mut *slice_ptr
+ }
+ }
+}
+
+unsafe impl FromBytes for i32 {
+ unsafe fn from_bytes(slice_of_bytes: &[u8]) -> &Self {
+ unsafe {
+ let slice_ptr = slice_of_bytes.as_ptr() as *const Self;
+ &*slice_ptr
+ }
+ }
+
+ unsafe fn from_bytes_mut(slice_of_bytes: &mut [u8]) -> &mut Self
+ where
+ Self: ToBytes,
+ {
+ unsafe {
+ let slice_ptr = slice_of_bytes.as_mut_ptr() as *mut Self;
+ &mut *slice_ptr
+ }
+ }
+}
+
+unsafe impl FromBytes for i64 {
+ unsafe fn from_bytes(slice_of_bytes: &[u8]) -> &Self {
+ unsafe {
+ let slice_ptr = slice_of_bytes.as_ptr() as *const Self;
+ &*slice_ptr
+ }
+ }
+
+ unsafe fn from_bytes_mut(slice_of_bytes: &mut [u8]) -> &mut Self
+ where
+ Self: ToBytes,
+ {
+ unsafe {
+ let slice_ptr = slice_of_bytes.as_mut_ptr() as *mut Self;
+ &mut *slice_ptr
+ }
+ }
+}
+
+unsafe impl FromBytes for isize {
+ unsafe fn from_bytes(slice_of_bytes: &[u8]) -> &Self {
+ unsafe {
+ let slice_ptr = slice_of_bytes.as_ptr() as *const Self;
+ &*slice_ptr
+ }
+ }
+
+ unsafe fn from_bytes_mut(slice_of_bytes: &mut [u8]) -> &mut Self
+ where
+ Self: ToBytes,
+ {
+ unsafe {
+ let slice_ptr = slice_of_bytes.as_mut_ptr() as *mut Self;
+ &mut *slice_ptr
+ }
+ }
+}
+// SAFETY: If all bit patterns are acceptable for individual values in an array, then all bit
+// patterns are also acceptable for arrays of that type.
+unsafe impl<T: FromBytes> FromBytes for [T] {
+ unsafe fn from_bytes(slice_of_bytes: &[u8]) -> &Self {
+ unsafe {
+ let slice_ptr = slice_of_bytes.as_ptr() as *const T;
+ let slice_len = slice_of_bytes.len() / core::mem::size_of::<T>();
+ core::slice::from_raw_parts(slice_ptr, slice_len)
+ }
+ }
+
+ unsafe fn from_bytes_mut(slice_of_bytes: &mut [u8]) -> &mut Self
+ where
+ Self: ToBytes,
+ {
+ unsafe {
+ let slice_ptr = slice_of_bytes.as_mut_ptr() as *mut T;
+ let slice_len = slice_of_bytes.len() / core::mem::size_of::<T>();
+ core::slice::from_raw_parts_mut(slice_ptr, slice_len)
+ }
+ }
+}
+
+/// # Examples
+///```
+///let slice_of_bytes: &[u8] = &[
+/// 1, 0, 0, 0,
+/// 2, 0, 0, 0,
+/// 3, 0, 0, 0,
+/// 4, 0, 0, 0,
+/// 5, 0, 0, 0,
+/// 6, 0, 0, 0,
+/// 7, 0, 0, 0,
+/// 8, 0, 0, 0,
+///];
+///
+///let foo = <[u32; 8]>::from_bytes(slice_of_bytes);
+///let expected: [u32; 8] = [1, 2, 3, 4, 5, 6, 7, 8];
+///
+///assert_eq!(*foo, expected);
+///```
+unsafe impl<T: FromBytes, const N: usize> FromBytes for [T; N] {
+ unsafe fn from_bytes(slice_of_bytes: &[u8]) -> &Self {
+ unsafe {
+ let slice_ptr = slice_of_bytes.as_ptr() as *const T;
+ &*(slice_ptr as *const [T; N])
+ }
+ }

- // SAFETY: If all bit patterns are acceptable for individual values in an array, then all bit
- // patterns are also acceptable for arrays of that type.
- {<T: FromBytes>} [T],
- {<T: FromBytes, const N: usize>} [T; N],
+ unsafe fn from_bytes_mut(slice_of_bytes: &mut [u8]) -> &mut Self
+ where
+ Self: ToBytes,
+ {
+ unsafe {
+ let slice_ptr = slice_of_bytes.as_ptr() as *mut T;
+ &mut *(slice_ptr as *mut [T; N])
+ }
+ }
}

/// Types that can be viewed as an immutable slice of initialized bytes.
--
2.46.2