rust/kernel/lib.rs | 2 + rust/kernel/transmute.rs | 302 +++++++++++++++++++++++++++++++++++++-- 2 files changed, 290 insertions(+), 14 deletions(-)
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@gmail.com>
---
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
Am 09.10.24 um 03:47 schrieb Christian dos Santos de Lima:
> 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@gmail.com>
> ---
> rust/kernel/lib.rs | 2 +
> rust/kernel/transmute.rs | 302 +++++++++++++++++++++++++++++++++++++--
> 2 files changed, 290 insertions(+), 14 deletions(-)
>
...
> --- a/rust/kernel/transmute.rs
> +++ b/rust/kernel/transmute.rs
...
> +unsafe impl FromBytes for u8 {
...
> +unsafe impl FromBytes for u16 {
...
> +unsafe impl FromBytes for u32 {
...
> +unsafe impl FromBytes for u64 {
...
> +unsafe impl FromBytes for usize {
...
> +unsafe impl FromBytes for i8 {
...
> +unsafe impl FromBytes for i16 {
...
> +unsafe impl FromBytes for i32 {
...
> +unsafe impl FromBytes for i64 {
...
> +unsafe impl FromBytes for isize {
...
Asahi Lina's device tree code which reads the device tree node's data
as a byte slice and then has to convert it
https://github.com/Fabo/linux/blob/9e496b356ee8e25f9bee9258491aa6ae3a4f1ddf/rust/kernel/of.rs#L390
uses macros to avoid code dublication:
prop_int_type!(u8);
prop_int_type!(u16);
prop_int_type!(u32);
prop_int_type!(u64);
prop_int_type!(i8);
prop_int_type!(i16);
prop_int_type!(i32);
prop_int_type!(i64);
Would anything like this be possible here, as well? To avoid code
dublication?
Best regards
Dirk
On 09.10.24 15:03, Dirk Behme wrote:
> Am 09.10.24 um 03:47 schrieb Christian dos Santos de Lima:
>> 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@gmail.com>
>> ---
>> rust/kernel/lib.rs | 2 +
>> rust/kernel/transmute.rs | 302 +++++++++++++++++++++++++++++++++++++--
>> 2 files changed, 290 insertions(+), 14 deletions(-)
>>
> ...
>> --- a/rust/kernel/transmute.rs
>> +++ b/rust/kernel/transmute.rs
> ...
>> +unsafe impl FromBytes for u8 {
> ...
>> +unsafe impl FromBytes for u16 {
> ...
>> +unsafe impl FromBytes for u32 {
> ...
>> +unsafe impl FromBytes for u64 {
> ...
>> +unsafe impl FromBytes for usize {
> ...
>> +unsafe impl FromBytes for i8 {
> ...
>> +unsafe impl FromBytes for i16 {
> ...
>> +unsafe impl FromBytes for i32 {
> ...
>> +unsafe impl FromBytes for i64 {
> ...
>> +unsafe impl FromBytes for isize {
> ...
>
> Asahi Lina's device tree code which reads the device tree node's data
> as a byte slice and then has to convert it
>
> https://github.com/Fabo/linux/blob/9e496b356ee8e25f9bee9258491aa6ae3a4f1ddf/rust/kernel/of.rs#L390
>
> uses macros to avoid code dublication:
>
> prop_int_type!(u8);
> prop_int_type!(u16);
> prop_int_type!(u32);
> prop_int_type!(u64);
> prop_int_type!(i8);
> prop_int_type!(i16);
> prop_int_type!(i32);
> prop_int_type!(i64);
>
> Would anything like this be possible here, as well? To avoid code
> dublication?
Yes please, create a macro.
---
Cheers,
Benno
On Wed, Oct 9, 2024 at 3:48 AM Christian dos Santos de Lima
<christiansantoslima21@gmail.com> wrote:
>
> +pub unsafe trait FromBytes {
> + ///Converts a slice of Bytes into a Reference to Self
> + ///
> + /// # Examples
> + /// ```
> + /// pub unsafe trait FromBytes {
Apart from what Alice mentions (which is critical, since we are
looking to get into stable Rust as soon as feasible -- please see
https://rust-for-linux.com/unstable-features#usage-in-the-kernel),
please also format the code, documentation and examples appropriately
(please see other files to see how it is usually done, we mostly
follow Rust's standard library conventions).
> + unsafe {
> + let slice_ptr = slice_of_bytes.as_ptr() as *const Self;
> + &*slice_ptr
> + }
Please note that we require `// SAFETY` comments too. Missing those is
already a warning/error (depending on the kernel configuration) in
rust-next.
Thanks for the patch!
Cheers,
Miguel
On Wed, Oct 9, 2024 at 3:48 AM Christian dos Santos de Lima <christiansantoslima21@gmail.com> wrote: > > 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@gmail.com> > --- > 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)] New unstable features must come with a good justification. Why are you adding these? Why can't we avoid adding them? This information needs to be in the commit message. Alice
© 2016 - 2026 Red Hat, Inc.