use super::ReadData;
use core::ops::Range;
#[derive(Copy, Clone)]
pub struct Slice<'a, T: ReadData> {
data: &'a [u8],
len: usize,
_p: core::marker::PhantomData<T>,
}
impl<'a, T: ReadData> Slice<'a, T> {
pub fn new(data: &'a [u8]) -> Self {
Self {
data,
len: data.len() / T::SIZE,
_p: core::marker::PhantomData {},
}
}
pub fn len(&self) -> usize {
self.len
}
pub fn is_empty(&self) -> bool {
self.len == 0
}
pub fn get(&self, index: usize) -> Option<T> {
if index >= self.len {
None
} else {
unsafe { Some(T::read_data_unchecked(self.data, index * T::SIZE)) }
}
}
pub fn get_or(&self, index: usize, or: T) -> T {
if index >= self.len {
or
} else {
unsafe { T::read_data_unchecked(self.data, index * T::SIZE) }
}
}
pub unsafe fn get_unchecked(&self, index: usize) -> T {
T::read_data_unchecked(self.data, index * T::SIZE)
}
pub fn binary_search_by<F>(&self, mut f: F) -> Option<(usize, T)>
where
F: FnMut(&T) -> core::cmp::Ordering,
{
use core::cmp::Ordering::*;
let mut size = self.len;
if size == 0 {
return None;
}
let mut base = 0usize;
while size > 1 {
let half = size / 2;
let mid = base + half;
let element = unsafe { self.get_unchecked(mid) };
base = match f(&element) {
Greater => base,
Less => mid,
Equal => return Some((mid, element)),
};
size -= half;
}
None
}
pub fn iter(&self) -> Iter<'a, T> {
Iter {
inner: *self,
range: 0..self.len,
}
}
}
impl<T: ReadData> Default for Slice<'_, T> {
fn default() -> Self {
Slice::new(&[])
}
}
impl<T> core::fmt::Debug for Slice<'_, T>
where
T: core::fmt::Debug + ReadData,
{
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
f.debug_list().entries(self.iter()).finish()
}
}
impl<T: ReadData + PartialEq> PartialEq for Slice<'_, T> {
fn eq(&self, other: &Self) -> bool {
if self.len() == other.len() {
self.iter().eq(other.iter())
} else {
false
}
}
}
impl<T: ReadData + PartialEq> Eq for Slice<'_, T> {}
impl<T: ReadData + PartialOrd> PartialOrd for Slice<'_, T> {
fn partial_cmp(&self, other: &Self) -> Option<core::cmp::Ordering> {
self.iter().partial_cmp(other.iter())
}
}
impl<T: ReadData + Ord> Ord for Slice<'_, T> {
fn cmp(&self, other: &Self) -> core::cmp::Ordering {
self.iter().cmp(other.iter())
}
}
#[derive(Clone)]
pub struct Iter<'a, T: ReadData> {
inner: Slice<'a, T>,
range: Range<usize>,
}
impl<'a, T: ReadData + 'a> Iterator for Iter<'a, T> {
type Item = T;
fn size_hint(&self) -> (usize, Option<usize>) {
let remaining = self.range.len();
(remaining, Some(remaining))
}
fn next(&mut self) -> Option<T> {
let index = self.range.next()?;
unsafe { Some(self.inner.get_unchecked(index)) }
}
}
impl<'a, T: ReadData + 'a> ExactSizeIterator for Iter<'a, T> {
fn len(&self) -> usize {
self.range.len()
}
}
impl<'a, T: ReadData + 'a> DoubleEndedIterator for Iter<'a, T> {
fn next_back(&mut self) -> Option<Self::Item> {
let index = self.range.next_back()?;
unsafe { Some(self.inner.get_unchecked(index)) }
}
}
impl<'a, T: ReadData + 'a> IntoIterator for Slice<'a, T> {
type IntoIter = Iter<'a, T>;
type Item = T;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl<'a, T: ReadData + 'a> IntoIterator for &'_ Slice<'a, T> {
type IntoIter = Iter<'a, T>;
type Item = T;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}