transmute_bytes/
from_bytes.rs

1use std::{
2    error,
3    fmt::{Display, Formatter},
4    mem::size_of,
5};
6
7#[derive(Clone, Debug, PartialEq, Eq)]
8pub enum Error {
9    LengthMismatch { slice_size: usize, type_size: usize },
10}
11
12impl Display for Error {
13    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
14        let err = match self {
15            Error::LengthMismatch {
16                slice_size,
17                type_size,
18            } => {
19                format!(
20                    "cannot cast byte slice with size: {} to type with size: {}",
21                    slice_size, type_size
22                )
23            }
24            #[allow(unreachable_patterns)]
25            _ => todo!(),
26        };
27        write!(f, "{}", err)
28    }
29}
30
31impl error::Error for Error {}
32
33pub unsafe trait FromBytes: Sized {
34    fn from_bytes(bytes: &[u8]) -> Result<Self, Error>;
35}
36
37macro_rules! from_bytes_impl {
38    ($($ty:ty)*) => {
39        $(unsafe impl FromBytes for $ty {
40            fn from_bytes(bytes: &[u8]) -> Result<Self, Error> {
41                if bytes.len() > size_of::<$ty>() {
42                    Err(Error::LengthMismatch {
43                        slice_size: bytes.len(),
44                        type_size: size_of::<$ty>(),
45                    })
46                } else {
47                    let mut place: [u8; size_of::<$ty>()] = [0; size_of::<$ty>()];
48                    place[..bytes.len()].copy_from_slice(bytes);
49                    Ok(<$ty>::from_ne_bytes(place))
50                }
51            }
52        })*
53    };
54}
55
56from_bytes_impl!(
57    i8 i16 i32 i64 i128 isize u8 u16 u32 u64 u128 usize
58);