use std::ops::Deref;
use std::ptr::{slice_from_raw_parts, slice_from_raw_parts_mut};
use thiserror::Error;
pub trait Length {
fn len(&self) -> usize;
fn is_empty(&self) -> bool {
self.len() == 0
}
}
impl<T> Length for [T] {
fn len(&self) -> usize {
self.len()
}
}
impl<'a, T> Length for &'a [T] {
fn len(&self) -> usize {
<[T]>::len(self)
}
}
impl<'a, T> Length for &'a mut [T] {
fn len(&self) -> usize {
<[T]>::len(self)
}
}
impl<T, const N: usize> Length for [T; N] {
fn len(&self) -> usize {
N
}
}
impl<'a, T, const N: usize> Length for &'a [T; N] {
fn len(&self) -> usize {
N
}
}
impl<'a, T, const N: usize> Length for &'a mut [T; N] {
fn len(&self) -> usize {
N
}
}
#[derive(Error, Debug)]
pub enum AdvanceError {
#[error("Not enough data, needed: `{needed}`, remaining: `{remaining}`")]
NotEnoughData { needed: usize, remaining: usize },
}
pub trait Advance<'a>: Length {
type Element;
type AdvanceOut: Deref<Target = [Self::Element]>;
fn advance(&'a mut self, amount: usize) -> Self::AdvanceOut {
assert!(amount <= self.len());
unsafe { self.advance_unchecked(amount) }
}
fn try_advance(&'a mut self, amount: usize) -> Result<Self::AdvanceOut, AdvanceError> {
if self.len() < amount {
Err(AdvanceError::NotEnoughData {
needed: amount,
remaining: self.len(),
})
} else {
Ok(unsafe { self.advance_unchecked(amount) })
}
}
unsafe fn advance_unchecked(&'a mut self, amount: usize) -> Self::AdvanceOut;
}
pub trait AdvanceArray<'a, const N: usize>: Length {
type Element;
type AdvanceOut: Deref<Target = [Self::Element; N]>;
fn advance_array(&'a mut self) -> Self::AdvanceOut {
assert!(N <= self.len());
unsafe { self.advance_array_unchecked() }
}
fn try_advance_array(&'a mut self) -> Result<Self::AdvanceOut, AdvanceError> {
if self.len() < N {
Err(AdvanceError::NotEnoughData {
needed: N,
remaining: self.len(),
})
} else {
Ok(unsafe { self.advance_array_unchecked() })
}
}
unsafe fn advance_array_unchecked(&'a mut self) -> Self::AdvanceOut;
}
impl<'a, 'b, T> Advance<'a> for &'b mut [T] {
type Element = T;
type AdvanceOut = &'b mut [T];
unsafe fn advance_unchecked(&'a mut self, amount: usize) -> Self::AdvanceOut {
let len = self.len();
let ptr = self.as_mut_ptr();
*self = &mut *slice_from_raw_parts_mut(ptr.add(amount), len - amount);
&mut *slice_from_raw_parts_mut(ptr, amount)
}
}
impl<'a, 'b, T, const N: usize> AdvanceArray<'a, N> for &'b mut [T] {
type Element = T;
type AdvanceOut = &'b mut [T; N];
unsafe fn advance_array_unchecked(&'a mut self) -> Self::AdvanceOut {
&mut *(
self.advance_unchecked(N).as_mut_ptr().cast::<[T; N]>()
)
}
}
impl<'a, 'b, T> Advance<'a> for &'b [T] {
type Element = T;
type AdvanceOut = &'b [T];
unsafe fn advance_unchecked(&'a mut self, amount: usize) -> Self::AdvanceOut {
let len = self.len();
let ptr = self.as_ptr();
*self = &*slice_from_raw_parts(ptr.add(amount), len - amount);
&*slice_from_raw_parts(ptr, amount)
}
}
impl<'a, 'b, T, const N: usize> AdvanceArray<'a, N> for &'b [T] {
type Element = T;
type AdvanceOut = &'b [T; N];
unsafe fn advance_array_unchecked(&'a mut self) -> Self::AdvanceOut {
&*(
self.advance_unchecked(N).as_ptr().cast::<[T; N]>()
)
}
}