use crate::ArrayVec;
use deku::ctx::{Limit, Order, ReadExact};
use deku::prelude::*;
use std::io::prelude::*;
use std::mem;
impl<const N: usize> DekuReader<'_, ReadExact> for ArrayVec<N, u8> {
fn from_reader_with_ctx<R: Read + Seek>(
reader: &mut Reader<R>,
exact: ReadExact,
) -> Result<Self, DekuError>
where
Self: Sized, {
assert!(exact.0 <= N);
let mut bytes = [0x00; N];
let _ = reader.read_bytes(exact.0, &mut bytes[..exact.0], Order::Lsb0)?;
Ok(Self::from_slice(&bytes[..exact.0]).unwrap())
}
}
fn reader_vec_with_predicate<'a, const N: usize, T, Ctx, Predicate, R: Read + Seek>(
reader: &mut Reader<R>,
ctx: Ctx,
mut predicate: Predicate,
) -> Result<ArrayVec<N, T>, DekuError>
where
T: DekuReader<'a, Ctx>,
Ctx: Copy,
Predicate: FnMut(usize, &T) -> bool, {
if mem::size_of::<T>() == 0 {
return Ok(ArrayVec::new());
}
let mut res = ArrayVec::new();
let start_read = reader.bits_read;
loop {
let val = <T>::from_reader_with_ctx(reader, ctx)?;
res.push(val);
if predicate(reader.bits_read - start_read, res.last().unwrap()) {
break;
}
}
Ok(res)
}
fn reader_vec_to_end<'a, const N: usize, T, Ctx, R: Read + Seek>(
reader: &mut Reader<R>,
ctx: Ctx,
) -> Result<ArrayVec<N, T>, DekuError>
where
T: DekuReader<'a, Ctx>,
Ctx: Copy, {
if mem::size_of::<T>() == 0 {
return Ok(ArrayVec::new());
}
let mut res = ArrayVec::new();
loop {
if reader.end() {
break;
}
let val = <T>::from_reader_with_ctx(reader, ctx)?;
res.push(val);
}
Ok(res)
}
impl<'a, const N: usize, T, Ctx, Predicate> DekuReader<'a, (Limit<T, Predicate>, Ctx)>
for ArrayVec<N, T>
where
T: DekuReader<'a, Ctx>,
Ctx: Copy,
Predicate: FnMut(&T) -> bool,
{
fn from_reader_with_ctx<R: Read + Seek>(
reader: &mut Reader<R>,
(limit, inner_ctx): (Limit<T, Predicate>, Ctx),
) -> Result<Self, DekuError>
where
Self: Sized, {
match limit {
Limit::Count(mut count) => {
assert!(count <= N);
if count == 0 {
return Ok(ArrayVec::new());
}
reader_vec_with_predicate(reader, inner_ctx, move |_, _| {
count -= 1;
count == 0
})
}
Limit::Until(mut predicate, _) => {
reader_vec_with_predicate(reader, inner_ctx, move |_, value| predicate(value))
}
Limit::BitSize(size) => {
let bit_size = size.0;
if bit_size == 0 {
return Ok(ArrayVec::new());
}
reader_vec_with_predicate(reader, inner_ctx, move |read_bits, _| {
read_bits == bit_size
})
}
Limit::ByteSize(size) => {
let bit_size = size.0 * 8;
if bit_size == 0 {
return Ok(ArrayVec::new());
}
reader_vec_with_predicate(reader, inner_ctx, move |read_bits, _| {
read_bits == bit_size
})
}
Limit::End => reader_vec_to_end(reader, inner_ctx),
}
}
}
impl<'a, const N: usize, T: DekuReader<'a>, Predicate: FnMut(&T) -> bool>
DekuReader<'a, Limit<T, Predicate>> for ArrayVec<N, T>
{
fn from_reader_with_ctx<R: Read + Seek>(
reader: &mut Reader<R>,
limit: Limit<T, Predicate>,
) -> Result<Self, DekuError>
where
Self: Sized, {
ArrayVec::from_reader_with_ctx(reader, (limit, ()))
}
}
impl<const N: usize, T: DekuWriter<Ctx>, Ctx: Copy> DekuWriter<Ctx> for ArrayVec<N, T> {
fn to_writer<W: Write + Seek>(
&self,
writer: &mut Writer<W>,
inner_ctx: Ctx,
) -> Result<(), DekuError> {
for v in self.iter() {
v.to_writer(writer, inner_ctx)?;
}
Ok(())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[deku_derive(DekuRead, DekuWrite)]
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct Cuesheet {
#[deku(endian = "big", count = "128")]
pub media_catalog_number: ArrayVec<128, u8>,
}
}