transmute_bytes/
transmute.rs1use crate::FromBytes;
2use std::{
3 borrow::Cow,
4 mem::{self, size_of},
5 slice,
6};
7
8fn is_aligned_slice<T>(slice: &[u8]) -> bool {
9 slice.as_ptr() as usize % mem::align_of::<T>() == 0
10}
11
12unsafe fn transmute_borrowed<T: FromBytes>(bytes: &[u8]) -> &[T] {
13 slice::from_raw_parts(bytes.as_ptr().cast(), bytes.len() / size_of::<T>())
14}
15
16fn transmute_owned<T: FromBytes>(bytes: &[u8]) -> Vec<T> {
17 (0..bytes.len())
18 .step_by(size_of::<T>())
19 .map(|i| {
20 let size = size_of::<T>();
21 let bytes = if i + size >= bytes.len() {
22 &bytes[i..]
23 } else {
24 &bytes[i..size]
25 };
26 unsafe { T::from_bytes(bytes).unwrap_unchecked() }
28 })
29 .collect()
30}
31
32pub fn transmute_bytes<T: Clone + FromBytes>(bytes: &impl AsRef<[u8]>) -> Cow<'_, [T]> {
33 let bytes = bytes.as_ref();
34 if is_aligned_slice::<T>(bytes) && bytes.len() % size_of::<T>() == 0 {
35 unsafe { transmute_borrowed(bytes).into() }
37 } else {
38 transmute_owned(bytes).into()
39 }
40}