use crate::coder::{Buffer, Decoder, Encoder, Result, View};
use crate::error::err;
use crate::fast::{CowSlice, NextUnchecked, PushUnchecked, SliceImpl, Unaligned, VecImpl};
use crate::pack_ints::{pack_ints, unpack_ints, Int};
use alloc::vec::Vec;
use bytemuck::{CheckedBitPattern, NoUninit, Pod};
use core::marker::PhantomData;
use core::num::NonZeroUsize;
#[derive(Default)]
pub struct IntEncoder<T>(VecImpl<T>);
impl<T: Int, P: NoUninit> Encoder<P> for IntEncoder<T> {
#[inline(always)]
fn as_primitive(&mut self) -> Option<&mut VecImpl<P>> {
use core::mem::*;
assert_eq!(align_of::<T>(), align_of::<P>());
assert_eq!(size_of::<T>(), size_of::<P>());
unsafe { Some(transmute(&mut self.0)) }
}
#[inline(always)]
fn encode(&mut self, p: &P) {
let t = bytemuck::must_cast(*p);
unsafe { self.0.push_unchecked(t) };
}
}
impl<T: Int> Buffer for IntEncoder<T> {
fn collect_into(&mut self, out: &mut Vec<u8>) {
pack_ints(self.0.as_mut_slice(), out);
self.0.clear();
}
fn reserve(&mut self, additional: NonZeroUsize) {
self.0.reserve(additional.get());
}
}
#[derive(Default)]
pub struct IntDecoder<'a, T: Int>(CowSlice<'a, T::Une>);
impl<'a, T: Int> IntDecoder<'a, T> {
pub(crate) fn borrowed_clone<'me: 'a>(&'me self) -> IntDecoder<'me, T> {
let mut cow = CowSlice::default();
cow.set_borrowed_slice_impl(self.0.ref_slice().clone());
Self(cow)
}
}
impl<'a, T: Int> View<'a> for IntDecoder<'a, T> {
fn populate(&mut self, input: &mut &'a [u8], length: usize) -> Result<()> {
unpack_ints::<T>(input, length, &mut self.0)?;
Ok(())
}
}
impl<'a, T: Int, P: Pod> Decoder<'a, P> for IntDecoder<'a, T> {
#[inline(always)]
fn as_primitive(&mut self) -> Option<&mut SliceImpl<Unaligned<P>>> {
Some(self.0.mut_slice().cast())
}
#[inline(always)]
fn decode(&mut self) -> P {
let v = unsafe { self.0.mut_slice().next_unchecked() };
bytemuck::must_cast(v)
}
}
pub struct CheckedIntDecoder<'a, C, I: Int>(IntDecoder<'a, I>, PhantomData<C>);
impl<C, I: Int> Default for CheckedIntDecoder<'_, C, I> {
fn default() -> Self {
Self(Default::default(), Default::default())
}
}
impl<'a, C: CheckedBitPattern, I: Int> View<'a> for CheckedIntDecoder<'a, C, I>
where
<C as CheckedBitPattern>::Bits: Pod,
{
fn populate(&mut self, input: &mut &'a [u8], length: usize) -> Result<()> {
self.0.populate(input, length)?;
let mut decoder = self.0.borrowed_clone();
if (0..length)
.filter(|_| !C::is_valid_bit_pattern(&decoder.decode()))
.count()
!= 0
{
return err("invalid bit pattern");
}
Ok(())
}
}
impl<'a, C: CheckedBitPattern + Send + Sync, I: Int> Decoder<'a, C> for CheckedIntDecoder<'a, C, I>
where
<C as CheckedBitPattern>::Bits: Pod,
{
#[inline(always)]
fn as_primitive(&mut self) -> Option<&mut SliceImpl<Unaligned<C>>> {
self.0
.as_primitive()
.map(|p: &mut SliceImpl<'_, Unaligned<I>>| {
let p = p.cast::<Unaligned<C::Bits>>();
unsafe { core::mem::transmute(p) }
})
}
#[inline(always)]
fn decode(&mut self) -> C {
let v: I = self.0.decode();
let v: C::Bits = bytemuck::must_cast(v);
unsafe { core::mem::transmute_copy(&v) }
}
}
#[cfg(test)]
mod tests {
use crate::{decode, encode};
use alloc::vec::Vec;
use core::num::NonZeroU32;
#[test]
fn non_zero_u32() {
assert!(decode::<NonZeroU32>(&encode(&0u32)).is_err());
assert!(decode::<NonZeroU32>(&encode(&1u32)).is_ok());
}
#[test]
fn char_() {
assert!(decode::<char>(&encode(&u32::MAX)).is_err());
assert!(decode::<char>(&encode(&0u32)).is_ok());
}
fn bench_data() -> Vec<u16> {
crate::random_data(1000)
}
crate::bench_encode_decode!(u16_vec: Vec<_>);
}
#[cfg(test)]
mod test2 {
use alloc::vec::Vec;
fn bench_data() -> Vec<Vec<u16>> {
crate::random_data::<u8>(125)
.into_iter()
.map(|n| (0..n / 54).map(|_| n as u16 * 255).collect())
.collect()
}
crate::bench_encode_decode!(u16_vecs: Vec<Vec<_>>);
}