`FromBytes::from_bytes` comes with a few practical limitations: - It requires the bytes slice to have the same alignment as the returned type, which might not be guaranteed in the case of a byte stream, - It returns a reference, requiring the returned type to implement `Clone` if one wants to keep the value for longer than the lifetime of the slice.
To overcome these when needed, add a `from_bytes_copy` with a default implementation in the trait. `from_bytes_copy` returns an owned value that is populated using an unaligned read, removing the lifetime constraint and making it usable even on non-aligned byte slices. Reviewed-by: Alice Ryhl <alicer...@google.com> Signed-off-by: Alexandre Courbot <acour...@nvidia.com> --- rust/kernel/transmute.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/rust/kernel/transmute.rs b/rust/kernel/transmute.rs index 494bb3b1d059337520efef694fc8952972d44fbf..721dd8254dcedd71ed7c1fc0ee9292950c16c89e 100644 --- a/rust/kernel/transmute.rs +++ b/rust/kernel/transmute.rs @@ -78,6 +78,23 @@ fn from_bytes_mut(bytes: &mut [u8]) -> Option<&mut Self> None } } + + /// Creates an owned instance of `Self` by copying `bytes`. + /// + /// As the data is copied into a properly-aligned location, this method can be used even if + /// [`FromBytes::from_bytes`] would return `None` due to incompatible alignment. + fn from_bytes_copy(bytes: &[u8]) -> Option<Self> + where + Self: Sized, + { + if bytes.len() == size_of::<Self>() { + // SAFETY: `bytes` has the same size as `Self`, and per the invariants of `FromBytes`, + // any byte sequence is a valid value for `Self`. + Some(unsafe { core::ptr::read_unaligned(bytes.as_ptr().cast::<Self>()) }) + } else { + None + } + } } macro_rules! impl_frombytes { -- 2.50.1