#![no_std]
pub use bytes_cast_derive::BytesCast;
use core::fmt;
use core::mem;
use core::slice;
pub mod unaligned;
#[cfg(doctest)]
mod compile_fail_tests;
pub unsafe trait BytesCast {
#[inline]
fn from_bytes(bytes: &[u8]) -> Result<(&Self, &[u8]), FromBytesError>
where
Self: Sized,
{
let expected_len = mem::size_of::<Self>();
remaining_bytes(bytes, expected_len).map(|rest| {
let this = unsafe { &*bytes.as_ptr().cast::<Self>() };
(this, rest)
})
}
#[inline]
fn slice_from_bytes(bytes: &[u8], slice_len: usize) -> Result<(&[Self], &[u8]), FromBytesError>
where
Self: Sized,
{
let expected_byte_len =
mem::size_of::<Self>()
.checked_mul(slice_len)
.ok_or(FromBytesError {
input_len: bytes.len(),
expected_len: None,
})?;
remaining_bytes(bytes, expected_byte_len).map(|rest| {
let this = unsafe { slice::from_raw_parts(bytes.as_ptr().cast::<Self>(), slice_len) };
(this, rest)
})
}
#[inline]
fn as_bytes(&self) -> &[u8] {
let ptr: *const Self = self;
let bytes_ptr = ptr.cast::<u8>();
let bytes_len = mem::size_of_val(self);
unsafe { slice::from_raw_parts(bytes_ptr, bytes_len) }
}
}
#[inline]
fn remaining_bytes(bytes: &[u8], expected_byte_len: usize) -> Result<&[u8], FromBytesError> {
bytes.get(expected_byte_len..).ok_or(FromBytesError {
input_len: bytes.len(),
expected_len: Some(expected_byte_len),
})
}
pub struct FromBytesError {
expected_len: Option<usize>,
input_len: usize,
}
impl fmt::Display for FromBytesError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
if let Some(expected_len) = self.expected_len {
write!(
f,
"Expected at least {} bytes, got {}",
expected_len, self.input_len
)
} else {
write!(f, "Expected byte size overflowed in slice_from_bytes")
}
}
}
impl fmt::Debug for FromBytesError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
fmt::Display::fmt(self, f)
}
}
unsafe impl<T: ?Sized> BytesCast for core::marker::PhantomData<T> {}
unsafe impl<T: BytesCast> BytesCast for [T] {}
unsafe impl BytesCast for () {}
unsafe impl BytesCast for u8 {}
macro_rules! array_impls {
($($N: expr)+) => {
$(
unsafe impl<T: BytesCast> BytesCast for [T; $N] {}
)+
};
}
array_impls!(
0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
);