use core::mem::{offset_of, size_of, MaybeUninit};
use core::num::NonZeroU8;
use super::TAG_BORROWED;
#[cfg(test)]
mod tests;
const TAG_NZ: NonZeroU8 = NonZeroU8::new(TAG_BORROWED).unwrap();
#[derive(Clone, Copy)]
#[repr(C)]
pub struct Borrowed<'borrow> {
#[cfg(target_endian = "little")]
tag: NonZeroU8,
#[cfg(target_endian = "little")]
reserved: MaybeUninit<[u8; size_of::<usize>() - 1]>,
slice: &'borrow [u8],
#[cfg(target_endian = "big")]
reserved: MaybeUninit<[u8; size_of::<usize>() - 1]>,
#[cfg(target_endian = "big")]
tag: NonZeroU8,
}
impl<'borrow> Borrowed<'borrow> {
const ASSERTS: () = {
if cfg!(target_endian = "little") {
assert!(offset_of!(Self, tag) == 0);
} else {
assert!(offset_of!(Self, tag) == size_of::<Self>() - 1);
}
};
#[inline]
pub const fn new(slice: &'borrow [u8]) -> Self {
let () = Self::ASSERTS;
let this = Self {
slice,
tag: TAG_NZ,
reserved: MaybeUninit::uninit(),
};
debug_assert!(this.is_valid());
this
}
#[inline]
pub const fn len(&self) -> usize {
debug_assert!(self.is_valid());
self.slice.len()
}
#[inline]
pub const fn as_slice(&self) -> &'borrow [u8] {
debug_assert!(self.is_valid());
self.slice
}
#[inline]
pub const fn as_ptr(&self) -> *const u8 {
debug_assert!(self.is_valid());
self.slice.as_ptr()
}
#[inline]
pub const fn is_valid(&self) -> bool {
self.tag.get() == TAG_BORROWED
}
pub unsafe fn set_len(&mut self, new_len: usize) {
debug_assert!(self.len() >= new_len, "set_len on borrowed slice");
self.slice = unsafe { self.slice.get_unchecked(0..new_len) };
}
}