#![no_std]
use core::alloc::Layout;
use core::mem;
use core::slice;
use core::slice::SliceIndex;
pub unsafe trait Buf {
type Element: zerocopy::AsBytes + Copy;
fn elem_len(&self) -> usize {
mem::size_of_val(self) / mem::size_of::<Self::Element>()
}
fn byte_len(&self) -> usize {
mem::size_of_val(self)
}
fn empty<'a, B: ?Sized + Buf>() -> &'a B {
empty()
}
fn as_bytes(&self) -> &[u8] {
as_bytes(self)
}
unsafe fn from_bytes(bytes: &[u8]) -> &Self {
as_buf(bytes)
}
fn as_bytes_mut(&mut self) -> &mut [u8] {
as_bytes_mut(self)
}
unsafe fn from_bytes_mut(bytes: &mut [u8]) -> &mut Self {
as_buf_mut(bytes)
}
unsafe fn slice_along_bytes<Idx>(&self, index: Idx) -> Option<&Self>
where
Idx: SliceIndex<[u8], Output = [u8]>,
{
self.as_bytes().get(index).map(|b| Self::from_bytes(b))
}
}
unsafe impl<T: zerocopy::AsBytes + Copy> Buf for [T] {
type Element = T;
}
unsafe impl Buf for str {
type Element = u8;
}
pub const fn layout_of<B: ?Sized + Buf>(buf: &B) -> Layout {
unsafe {
Layout::from_size_align_unchecked(
as_bytes(buf).len(),
mem::align_of::<B::Element>(),
)
}
}
pub const fn empty<'a, B: ?Sized + Buf>() -> &'a B {
unsafe { as_buf(&[]) }
}
pub const fn as_bytes<B: ?Sized + Buf>(buf: &B) -> &[u8] {
assert!(
mem::size_of::<B::Element>() > 0,
"buf-trait: cannot use ZST as in type-erased context"
);
let ptr = &buf as *const &_ as *const &[B::Element];
unsafe {
let buf = *ptr;
let ptr = buf as *const _ as *const u8;
let len = buf.len() * mem::size_of::<B::Element>();
slice::from_raw_parts(ptr, len)
}
}
pub fn as_bytes_mut<B: ?Sized + Buf>(mut buf: &mut B) -> &mut [u8] {
assert!(
mem::size_of::<B::Element>() > 0,
"buf-trait: cannot use ZST as in type-erased context"
);
let ptr = &mut buf as *mut &mut _ as *mut &mut [B::Element];
unsafe {
let buf = &mut *ptr;
let ptr = buf as *mut _ as *mut u8;
slice::from_raw_parts_mut(ptr, mem::size_of_val(&**buf))
}
}
pub const unsafe fn as_buf<B: ?Sized + Buf>(bytes: &[u8]) -> &B {
assert!(
mem::size_of::<B::Element>() > 0,
"buf-trait: cannot use ZST as in type-erased context"
);
let buf = slice::from_raw_parts(
bytes.as_ptr().cast::<B::Element>(),
bytes.len() / mem::size_of::<B::Element>(),
);
let ptr = &buf as *const &[_] as *const &B;
*ptr
}
pub unsafe fn as_buf_mut<B: ?Sized + Buf>(bytes: &mut [u8]) -> &mut B {
assert!(
mem::size_of::<B::Element>() > 0,
"buf-trait: cannot use ZST as in type-erased context"
);
let mut buf = slice::from_raw_parts_mut(
bytes.as_mut_ptr().cast::<B::Element>(),
bytes.len() / mem::size_of::<B::Element>(),
);
let ptr = &mut buf as *mut &mut [_] as *mut &mut B;
*ptr
}