#![no_std]
#[cfg(feature = "std")]
extern crate std;
use core::ops::Deref;
use core::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<T> Length for &'_ [T] {
fn len(&self) -> usize {
<[T]>::len(self)
}
}
impl<T> Length for &'_ mut [T] {
fn len(&self) -> usize {
<[T]>::len(self)
}
}
impl<T, const N: usize> Length for [T; N] {
fn len(&self) -> usize {
N
}
}
impl<T, const N: usize> Length for &'_ [T; N] {
fn len(&self) -> usize {
N
}
}
impl<T, const N: usize> Length for &'_ 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>: Length {
type Element;
type AdvanceOut<const N: usize>: Deref<Target = [Self::Element; N]>
where
Self: 'a;
fn advance_array<const N: usize>(&'a mut self) -> Self::AdvanceOut<N> {
assert!(N <= self.len());
unsafe { self.advance_array_unchecked() }
}
fn try_advance_array<const N: usize>(
&'a mut self,
) -> Result<Self::AdvanceOut<N>, 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<const N: usize>(&'a mut self) -> Self::AdvanceOut<N>;
}
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> AdvanceArray<'a> for &'b mut [T] {
type Element = T;
type AdvanceOut<const N: usize>
= &'b mut [T; N]
where
Self: 'a;
unsafe fn advance_array_unchecked<const N: usize>(&'a mut self) -> Self::AdvanceOut<N> {
&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> AdvanceArray<'a> for &'b [T] {
type Element = T;
type AdvanceOut<const N: usize>
= &'b [T; N]
where
Self: 'a;
unsafe fn advance_array_unchecked<const N: usize>(&'a mut self) -> Self::AdvanceOut<N> {
&*(
self.advance_unchecked(N).as_ptr().cast::<[T; N]>()
)
}
}