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 - 2024 Red Hat, Inc.