transmute_bytes/
from_bytes.rs1use 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);