use core::marker::PhantomData;
#[repr(transparent)]
pub struct LocatedLength<T>(usize, PhantomData<T>);
impl<T> Clone for LocatedLength<T> {
#[inline]
fn clone(&self) -> Self {
*self
}
}
impl<T> Copy for LocatedLength<T> {}
#[allow(clippy::len_without_is_empty)]
impl<T> LocatedLength<T> {
const MAX_LEN: usize = usize::MAX >> Self::SHIFT;
const SHIFT: u32 = (size_of::<T>() != 0) as u32;
const TAG: usize = Self::SHIFT as usize;
#[inline(always)]
pub const fn new(length: usize, on_heap: bool) -> Self {
debug_assert!(length < Self::MAX_LEN);
debug_assert!(!on_heap || Self::TAG != 0);
Self(
(length << Self::SHIFT) | ((on_heap as usize) & Self::TAG),
PhantomData
)
}
#[inline(always)]
pub const fn len(self) -> usize {
self.0 >> Self::SHIFT
}
#[inline(always)]
#[must_use]
pub const fn on_heap(self) -> bool {
self.0 & Self::TAG != 0
}
#[inline(always)]
pub const fn parts(self) -> (usize, bool) {
(self.0 >> Self::SHIFT, (self.0 & Self::TAG) != 0)
}
#[inline(always)]
pub const fn set_location<const ON: bool>(&mut self) {
if Self::TAG != 0 {
self.0 = (self.0 & !Self::TAG) | ON as usize;
}
}
#[inline(always)]
pub const unsafe fn add(&mut self, n: usize) {
#[cfg(any(debug_assertions, not(target_pointer_width = "64")))]
{
#[cold]
#[inline(never)]
const fn assert_failed() {
panic!("smallvec length overflow")
}
match self.len().checked_add(n) {
Some(value) => {
if value > Self::MAX_LEN {
assert_failed()
}
}
None => assert_failed()
}
}
self.0 += n << Self::SHIFT;
}
#[inline(always)]
pub const unsafe fn sub(&mut self, n: usize) {
debug_assert!(self.len() >= n);
self.0 -= n << Self::SHIFT;
}
}