use super::components::VarZeroVecComponents;
use super::*;
use crate::ule::*;
use alloc::boxed::Box;
use alloc::vec::Vec;
use core::cmp::{Ord, Ordering, PartialOrd};
use core::fmt;
use core::marker::PhantomData;
use core::mem;
use core::ops::Index;
use core::ops::Range;
#[repr(transparent)]
pub struct VarZeroSlice<T: ?Sized, F = Index16> {
marker: PhantomData<(F, T)>,
entire_slice: [u8],
}
impl<T: VarULE + ?Sized, F: VarZeroVecFormat> VarZeroSlice<T, F> {
pub const fn new_empty() -> &'static Self {
let arr: &[u8] = &[];
unsafe { mem::transmute(arr) }
}
#[inline]
pub(crate) fn as_components<'a>(&'a self) -> VarZeroVecComponents<'a, T, F> {
unsafe {
VarZeroVecComponents::from_bytes_unchecked(&self.entire_slice)
}
}
pub const unsafe fn from_bytes_unchecked(bytes: &[u8]) -> &Self {
mem::transmute(bytes)
}
pub fn len(&self) -> usize {
self.as_components().len()
}
pub fn is_empty(&self) -> bool {
self.as_components().is_empty()
}
pub fn iter<'b>(&'b self) -> impl Iterator<Item = &'b T> {
self.as_components().iter()
}
pub fn get(&self, idx: usize) -> Option<&T> {
self.as_components().get(idx)
}
pub unsafe fn get_unchecked(&self, idx: usize) -> &T {
self.as_components().get_unchecked(idx)
}
pub fn to_vec(&self) -> Vec<Box<T>> {
self.as_components().to_vec()
}
#[inline]
pub const fn as_bytes(&self) -> &[u8] {
&self.entire_slice
}
pub const fn as_varzerovec<'a>(&'a self) -> VarZeroVec<'a, T, F> {
VarZeroVec::Borrowed(self)
}
pub fn parse_byte_slice<'a>(slice: &'a [u8]) -> Result<&'a Self, ZeroVecError> {
<Self as VarULE>::parse_byte_slice(slice)
}
pub(crate) unsafe fn from_byte_slice_unchecked_mut(bytes: &mut [u8]) -> &mut Self {
mem::transmute(bytes)
}
pub(crate) unsafe fn get_bytes_at_mut(&mut self, idx: usize) -> &mut [u8] {
let range = self.as_components().get_range(idx);
#[allow(clippy::indexing_slicing)] &mut self.entire_slice[range]
}
}
impl<T, F> VarZeroSlice<T, F>
where
T: VarULE,
T: ?Sized,
T: Ord,
F: VarZeroVecFormat,
{
#[inline]
pub fn binary_search(&self, x: &T) -> Result<usize, usize> {
self.as_components().binary_search(x)
}
#[inline]
pub fn binary_search_in_range(
&self,
x: &T,
range: Range<usize>,
) -> Option<Result<usize, usize>> {
self.as_components().binary_search_in_range(x, range)
}
}
impl<T, F> VarZeroSlice<T, F>
where
T: VarULE,
T: ?Sized,
F: VarZeroVecFormat,
{
#[inline]
pub fn binary_search_by(&self, predicate: impl FnMut(&T) -> Ordering) -> Result<usize, usize> {
self.as_components().binary_search_by(predicate)
}
pub fn binary_search_in_range_by(
&self,
predicate: impl FnMut(&T) -> Ordering,
range: Range<usize>,
) -> Option<Result<usize, usize>> {
self.as_components()
.binary_search_in_range_by(predicate, range)
}
}
unsafe impl<T: VarULE + ?Sized + 'static, F: VarZeroVecFormat> VarULE for VarZeroSlice<T, F> {
fn validate_byte_slice(bytes: &[u8]) -> Result<(), ZeroVecError> {
let _: VarZeroVecComponents<T, F> = VarZeroVecComponents::parse_byte_slice(bytes)?;
Ok(())
}
unsafe fn from_byte_slice_unchecked(bytes: &[u8]) -> &Self {
mem::transmute(bytes)
}
fn as_byte_slice(&self) -> &[u8] {
&self.entire_slice
}
}
impl<T: VarULE + ?Sized, F: VarZeroVecFormat> Index<usize> for VarZeroSlice<T, F> {
type Output = T;
fn index(&self, index: usize) -> &Self::Output {
#[allow(clippy::panic)] match self.get(index) {
Some(x) => x,
None => panic!(
"index out of bounds: the len is {} but the index is {index}",
self.len()
),
}
}
}
impl<T, F> PartialEq<VarZeroSlice<T, F>> for VarZeroSlice<T, F>
where
T: VarULE,
T: ?Sized,
T: PartialEq,
F: VarZeroVecFormat,
{
#[inline]
fn eq(&self, other: &VarZeroSlice<T, F>) -> bool {
self.entire_slice.eq(&other.entire_slice)
}
}
impl<T, F> Eq for VarZeroSlice<T, F>
where
T: VarULE,
T: ?Sized,
T: Eq,
F: VarZeroVecFormat,
{
}
impl<T: VarULE + ?Sized + PartialOrd, F: VarZeroVecFormat> PartialOrd for VarZeroSlice<T, F> {
#[inline]
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
self.iter().partial_cmp(other.iter())
}
}
impl<T: VarULE + ?Sized + Ord, F: VarZeroVecFormat> Ord for VarZeroSlice<T, F> {
#[inline]
fn cmp(&self, other: &Self) -> Ordering {
self.iter().cmp(other.iter())
}
}
impl<T: VarULE + ?Sized, F: VarZeroVecFormat> fmt::Debug for VarZeroSlice<T, F>
where
T: fmt::Debug,
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_list().entries(self.iter()).finish()
}
}
impl<T: ?Sized, F: VarZeroVecFormat> AsRef<VarZeroSlice<T, F>> for VarZeroSlice<T, F> {
fn as_ref(&self) -> &VarZeroSlice<T, F> {
self
}
}