Skip to contentSkip to conversation

rust: transmute: add `as_bytes` method for `AsBytes` trait

PATCH Superseded Alexandre Courbot 4 participants 9 messages Jul 26, 2025 – Jul 28, 2025 Rust

v3 of 5 Superseded Latest is v5 →

lore
Share & tools
lore

Alexandre Courbot

author reviewer
#0 lore raw

PATCH v3 1/1 rust: transmute: add `as_bytes` method for `AsBytes` trait

Every type that implements AsBytes should be able to provide its byte representation. Introduce the as_bytes method that returns the implementer as a stream of bytes, and provide a default implementation that should be suitable for any type that satisfies AsBytes's safety requirements.

---
This is the sister patch of [1], providing an as_bytes method for AsBytes.

It is going to be used in Nova, but should also be universally useful - if anything, it felt a bit strange that AsBytes did not provide this method so far.

[1] https://lore.kernel.org/rust-for-linux/[email protected]/
---
Changes in v3:
- Use ptr::from_ref instead of as *const T.
- Link to v2: https://lore.kernel.org/r/[email protected]

Changes in v2:
- Use size_of_val to provide a default implementation for both Sized and non-Sized types, and remove AsBytesSized. (thanks Alice!)
- Link to v1: https://lore.kernel.org/r/[email protected]

---
 rust/kernel/transmute.rs | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)
rust/kernel/transmute.rs +10 -1
index 1c7d43771a37b90150de86699f114a2ffb84db91..69c46c19a89191d8a2abc5801564cacda232218c 100644
@@ -47,7 +47,16 @@ macro_rules! impl_frombytes {
 ///
 /// Values of this type may not contain any uninitialized bytes. This type must not have interior
 /// mutability.
-pub unsafe trait AsBytes {}
+pub unsafe trait AsBytes {
+    /// Returns `self` as a slice of bytes.
+    fn as_bytes(&self) -> &[u8] {
+        let data = core::ptr::from_ref(self).cast::<u8>();
+        let len = size_of_val(self);
+
+        // SAFETY: `data` is non-null and valid for `len * sizeof::<u8>()` bytes.
+        unsafe { core::slice::from_raw_parts(data, len) }
+    }
+}
 
 macro_rules! impl_asbytes {
     ($($({$($generics:tt)*})? $t:ty, )*) => {

---
base-commit: 14ae91a81ec8fa0bc23170d4aa16dd2a20d54105
change-id: 20250725-as_bytes-6cbc11f2e8c3

Best regards,

Signature · 1 line
Alexandre Courbot <[email protected]>
reviewer Reviewed-by on v3 1/1
#1 lore raw
Quoted 8 lines · Alexandre Courbot

Every type that implements AsBytes should be able to provide its byte representation. Introduce the as_bytes method that returns the implementer as a stream of bytes, and provide a default implementation that should be suitable for any type that satisfies AsBytes's safety requirements.

Quoted 46 lines

---
This is the sister patch of [1], providing an as_bytes method for AsBytes.

It is going to be used in Nova, but should also be universally useful - if anything, it felt a bit strange that AsBytes did not provide this method so far.

[1] https://lore.kernel.org/rust-for-linux/[email protected]/
---
Changes in v3:
- Use ptr::from_ref instead of as *const T.
- Link to v2: https://lore.kernel.org/r/[email protected]

Changes in v2:
- Use size_of_val to provide a default implementation for both Sized and non-Sized types, and remove AsBytesSized. (thanks Alice!)
- Link to v1: https://lore.kernel.org/r/[email protected]

---
 rust/kernel/transmute.rs | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)
rust/kernel/transmute.rs +10 -2
index 1c7d43771a37b90150de86699f114a2ffb84db91..69c46c19a89191d8a2abc5801564cacda232218c 100644
@@ -47,7 +47,16 @@ macro_rules! impl_frombytes {
 ///
 /// Values of this type may not contain any uninitialized bytes. This type must not have interior
 /// mutability.
-pub unsafe trait AsBytes {}
+pub unsafe trait AsBytes {
+    /// Returns `self` as a slice of bytes.
+    fn as_bytes(&self) -> &[u8] {
+        let data = core::ptr::from_ref(self).cast::<u8>();
+        let len = size_of_val(self);
+
+        // SAFETY: `data` is non-null and valid for `len * sizeof::<u8>()` bytes.
+        unsafe { core::slice::from_raw_parts(data, len) }
+    }
+}
 
 macro_rules! impl_asbytes {
     ($($({$($generics:tt)*})? $t:ty, )*) => {
 
---
Quoted 1 line

base-commit: 14ae91a81ec8fa0bc23170d4aa16dd2a20d54105

Normally I'd expect this to be rust-next or an -rc tag... I did find this in one of the trees that I fetch, so no worries, but maybe in the future use one of those? Thanks!

---
Cheers,
Benno

Quoted 3 lines

change-id: 20250725-as_bytes-6cbc11f2e8c3

Best regards,

reviewer
#2 lore raw
In reply to Alexandre Courbot
Quoted 40 lines · Alexandre Courbot

Every type that implements AsBytes should be able to provide its byte representation. Introduce the as_bytes method that returns the implementer as a stream of bytes, and provide a default implementation that should be suitable for any type that satisfies AsBytes's safety requirements.

---
This is the sister patch of [1], providing an as_bytes method for AsBytes.

It is going to be used in Nova, but should also be universally useful - if anything, it felt a bit strange that AsBytes did not provide this method so far.

[1] https://lore.kernel.org/rust-for-linux/[email protected]/
---
Changes in v3:
- Use ptr::from_ref instead of as *const T.
- Link to v2: https://lore.kernel.org/r/[email protected]

Changes in v2:
- Use size_of_val to provide a default implementation for both Sized and non-Sized types, and remove AsBytesSized. (thanks Alice!)
- Link to v1: https://lore.kernel.org/r/[email protected]

---
 rust/kernel/transmute.rs | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)
rust/kernel/transmute.rs +0 -1
index 1c7d43771a37b90150de86699f114a2ffb84db91..69c46c19a89191d8a2abc5801564cacda232218c 100644
@@ -47,7 +47,16 @@ macro_rules! impl_frombytes {
 ///
 /// Values of this type may not contain any uninitialized bytes. This type must not have interior
 /// mutability.
-pub unsafe trait AsBytes {}

rust/kernel/transmute.rs macro_rules! impl_frombytes { · line 59

Quoted 10 lines
rust/kernel/transmute.rs +10 -0
+pub unsafe trait AsBytes {
+    /// Returns `self` as a slice of bytes.
+    fn as_bytes(&self) -> &[u8] {
+        let data = core::ptr::from_ref(self).cast::<u8>();
+        let len = size_of_val(self);
+
+        // SAFETY: `data` is non-null and valid for `len * sizeof::<u8>()` bytes.
+        unsafe { core::slice::from_raw_parts(data, len) }
+    }
+}

Let's also have an as_bytes_mut() method. I would require the type to also implement FromBytes as it lets you replace the value with another set of bytes.

Alice

reviewer
#3 lore raw
Quoted 47 lines · Alice Ryhl
Quoted 46 lines · Alexandre Courbot

Every type that implements AsBytes should be able to provide its byte representation. Introduce the as_bytes method that returns the implementer as a stream of bytes, and provide a default implementation that should be suitable for any type that satisfies AsBytes's safety requirements.

---
This is the sister patch of [1], providing an as_bytes method for AsBytes.

It is going to be used in Nova, but should also be universally useful - if anything, it felt a bit strange that AsBytes did not provide this method so far.

[1] https://lore.kernel.org/rust-for-linux/[email protected]/
---
Changes in v3:
- Use ptr::from_ref instead of as *const T.
- Link to v2: https://lore.kernel.org/r/[email protected]

Changes in v2:
- Use size_of_val to provide a default implementation for both Sized and non-Sized types, and remove AsBytesSized. (thanks Alice!)
- Link to v1: https://lore.kernel.org/r/[email protected]

---
 rust/kernel/transmute.rs | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)
rust/kernel/transmute.rs +6 -1
index 1c7d43771a37b90150de86699f114a2ffb84db91..69c46c19a89191d8a2abc5801564cacda232218c 100644
@@ -47,7 +47,16 @@ macro_rules! impl_frombytes {
 ///
 /// Values of this type may not contain any uninitialized bytes. This type must not have interior
 /// mutability.
-pub unsafe trait AsBytes {}
+pub unsafe trait AsBytes {
+    /// Returns `self` as a slice of bytes.
+    fn as_bytes(&self) -> &[u8] {
+        let data = core::ptr::from_ref(self).cast::<u8>();
+        let len = size_of_val(self);
+
Quoted 8 lines

rust/kernel/transmute.rs macro_rules! impl_frombytes { · line 59

Quoted 4 lines
rust/kernel/transmute.rs +4 -0
+        // SAFETY: `data` is non-null and valid for `len * sizeof::<u8>()` bytes.
+        unsafe { core::slice::from_raw_parts(data, len) }
+    }
+}

Let's also have an as_bytes_mut() method. I would require the type to also implement FromBytes as it lets you replace the value with another set of bytes.

s/I would/It would/

FromBytes is needed only for as_bytes_mut(), not for the existing method.

Alice

reviewer
#4 lore raw
Quoted 26 lines · Alice Ryhl
Quoted 16 lines · Alice Ryhl
Quoted 15 lines · Alexandre Courbot
rust/kernel/transmute.rs +6 -1
index 1c7d43771a37b90150de86699f114a2ffb84db91..69c46c19a89191d8a2abc5801564cacda232218c 100644
@@ -47,7 +47,16 @@ macro_rules! impl_frombytes {
 ///
 /// Values of this type may not contain any uninitialized bytes. This type must not have interior
 /// mutability.
-pub unsafe trait AsBytes {}
+pub unsafe trait AsBytes {
+    /// Returns `self` as a slice of bytes.
+    fn as_bytes(&self) -> &[u8] {
+        let data = core::ptr::from_ref(self).cast::<u8>();
+        let len = size_of_val(self);
+
Quoted 8 lines

rust/kernel/transmute.rs macro_rules! impl_frombytes { · line 59

Quoted 4 lines
rust/kernel/transmute.rs +4 -0
+        // SAFETY: `data` is non-null and valid for `len * sizeof::<u8>()` bytes.
+        unsafe { core::slice::from_raw_parts(data, len) }
+    }
+}

Let's also have an as_bytes_mut() method. I would require the type to also implement FromBytes as it lets you replace the value with another set of bytes.

Quoted 4 lines

s/I would/It would/

FromBytes is needed only for as_bytes_mut(), not for the existing method.

I agree with your suggestion, but it can be an independent patch and doesn't need to go in via this one, right?

---
Cheers,
Benno

reviewer
#5 lore raw
Quoted 28 lines · Benno Lossin
Quoted 26 lines · Alice Ryhl
Quoted 24 lines · Alice Ryhl
Quoted 9 lines · Alexandre Courbot
rust/kernel/transmute.rs +0 -1
index 1c7d43771a37b90150de86699f114a2ffb84db91..69c46c19a89191d8a2abc5801564cacda232218c 100644
@@ -47,7 +47,16 @@ macro_rules! impl_frombytes {
 ///
 /// Values of this type may not contain any uninitialized bytes. This type must not have interior
 /// mutability.
-pub unsafe trait AsBytes {}

rust/kernel/transmute.rs macro_rules! impl_frombytes { · line 59

Quoted 10 lines
rust/kernel/transmute.rs +10 -0
+pub unsafe trait AsBytes {
+    /// Returns `self` as a slice of bytes.
+    fn as_bytes(&self) -> &[u8] {
+        let data = core::ptr::from_ref(self).cast::<u8>();
+        let len = size_of_val(self);
+
+        // SAFETY: `data` is non-null and valid for `len * sizeof::<u8>()` bytes.
+        unsafe { core::slice::from_raw_parts(data, len) }
+    }
+}

Let's also have an as_bytes_mut() method. I would require the type to also implement FromBytes as it lets you replace the value with another set of bytes.

Quoted 7 lines
Quoted 4 lines

s/I would/It would/

FromBytes is needed only for as_bytes_mut(), not for the existing method.

I agree with your suggestion, but it can be an independent patch and doesn't need to go in via this one, right?

Sure, that's fine.

Alice

author reviewer
#6 lore raw
In reply to Benno Lossin
Quoted 27 lines · Benno Lossin
Quoted 26 lines · Alice Ryhl
Quoted 24 lines · Alice Ryhl
Quoted 9 lines · Alexandre Courbot
rust/kernel/transmute.rs +0 -1
index 1c7d43771a37b90150de86699f114a2ffb84db91..69c46c19a89191d8a2abc5801564cacda232218c 100644
@@ -47,7 +47,16 @@ macro_rules! impl_frombytes {
 ///
 /// Values of this type may not contain any uninitialized bytes. This type must not have interior
 /// mutability.
-pub unsafe trait AsBytes {}

rust/kernel/transmute.rs macro_rules! impl_frombytes { · line 59

Quoted 10 lines
rust/kernel/transmute.rs +10 -0
+pub unsafe trait AsBytes {
+    /// Returns `self` as a slice of bytes.
+    fn as_bytes(&self) -> &[u8] {
+        let data = core::ptr::from_ref(self).cast::<u8>();
+        let len = size_of_val(self);
+
+        // SAFETY: `data` is non-null and valid for `len * sizeof::<u8>()` bytes.
+        unsafe { core::slice::from_raw_parts(data, len) }
+    }
+}

Let's also have an as_bytes_mut() method. I would require the type to also implement FromBytes as it lets you replace the value with another set of bytes.

Quoted 7 lines
Quoted 4 lines

s/I would/It would/

FromBytes is needed only for as_bytes_mut(), not for the existing method.

I agree with your suggestion, but it can be an independent patch and doesn't need to go in via this one, right?

Given where we are in the merge cycle, it seems like we have a couple of months until that code gets merged anyway, so I don't see any reason to not send a v4 with Alice's suggestion? The only drawback I see is that I would have to reset the Reviewed-by tags.

reviewer
#7 lore raw
Quoted 33 lines · Alexandre Courbot
Quoted 32 lines · Benno Lossin
Quoted 30 lines · Alice Ryhl
Quoted 16 lines · Alice Ryhl
Quoted 15 lines · Alexandre Courbot
rust/kernel/transmute.rs +6 -1
index 1c7d43771a37b90150de86699f114a2ffb84db91..69c46c19a89191d8a2abc5801564cacda232218c 100644
@@ -47,7 +47,16 @@ macro_rules! impl_frombytes {
 ///
 /// Values of this type may not contain any uninitialized bytes. This type must not have interior
 /// mutability.
-pub unsafe trait AsBytes {}
+pub unsafe trait AsBytes {
+    /// Returns `self` as a slice of bytes.
+    fn as_bytes(&self) -> &[u8] {
+        let data = core::ptr::from_ref(self).cast::<u8>();
+        let len = size_of_val(self);
+
Quoted 8 lines

rust/kernel/transmute.rs macro_rules! impl_frombytes { · line 59

Quoted 4 lines
rust/kernel/transmute.rs +4 -0
+        // SAFETY: `data` is non-null and valid for `len * sizeof::<u8>()` bytes.
+        unsafe { core::slice::from_raw_parts(data, len) }
+    }
+}

Let's also have an as_bytes_mut() method. I would require the type to also implement FromBytes as it lets you replace the value with another set of bytes.

s/I would/It would/

FromBytes is needed only for as_bytes_mut(), not for the existing method.

Quoted 7 lines
Quoted 2 lines

I agree with your suggestion, but it can be an independent patch and doesn't need to go in via this one, right?

Given where we are in the merge cycle, it seems like we have a couple of months until that code gets merged anyway, so I don't see any reason to not send a v4 with Alice's suggestion? The only drawback I see is that I would have to reset the Reviewed-by tags.

Yeah sounds good.

---
Cheers,
Benno

#8 lore raw
In reply to Alexandre Courbot
Quoted 33 lines · Alexandre Courbot
Quoted 32 lines · Benno Lossin
Quoted 30 lines · Alice Ryhl
Quoted 16 lines · Alice Ryhl
Quoted 15 lines · Alexandre Courbot
rust/kernel/transmute.rs +6 -1
index 1c7d43771a37b90150de86699f114a2ffb84db91..69c46c19a89191d8a2abc5801564cacda232218c 100644
@@ -47,7 +47,16 @@ macro_rules! impl_frombytes {
  ///
  /// Values of this type may not contain any uninitialized bytes. This type must not have interior
  /// mutability.
-pub unsafe trait AsBytes {}
+pub unsafe trait AsBytes {
+    /// Returns `self` as a slice of bytes.
+    fn as_bytes(&self) -> &[u8] {
+        let data = core::ptr::from_ref(self).cast::<u8>();
+        let len = size_of_val(self);
+
Quoted 8 lines

rust/kernel/transmute.rs macro_rules! impl_frombytes { · line 59

Quoted 4 lines
rust/kernel/transmute.rs +4 -0
+        // SAFETY: `data` is non-null and valid for `len * sizeof::<u8>()` bytes.
+        unsafe { core::slice::from_raw_parts(data, len) }
+    }
+}

Let's also have an as_bytes_mut() method. I would require the type to also implement FromBytes as it lets you replace the value with another set of bytes.

s/I would/It would/

FromBytes is needed only for as_bytes_mut(), not for the existing method.

Quoted 7 lines
Quoted 2 lines

I agree with your suggestion, but it can be an independent patch and doesn't need to go in via this one, right?

Given where we are in the merge cycle, it seems like we have a couple of months until that code gets merged anyway, so I don't see any reason to not send a v4 with Alice's suggestion? The only drawback I see is that I would have to reset the Reviewed-by tags.

I'd make it a series and add as_bytes_mut() as a separate patch.