use std::{array::try_from_fn, marker::PhantomData, ops::Deref}; use crate::{Deparsable, PResult, PResultBytes, Parsable}; impl<'a, T, Ctx, const N: usize> Parsable<'a, [u8], Ctx> for [T; N] where Ctx: Copy, T: Parsable<'a, [u8], Ctx>, { fn read(mut source: &'a [u8], context: Ctx) -> PResultBytes { try_from_fn(|_| { let (element, this_bytes) = Parsable::read(source, context)?; source = this_bytes; Ok(element) }) .map(|array| (array, source)) } } impl Deparsable for [T; N] where T: Deparsable, { fn write(&self, w: &mut impl std::io::Write) -> std::io::Result<()> { self.iter().try_for_each(|element| element.write(&mut *w)) } } macro_rules! impl_tuple { ($name:ident $ty:ident) => { impl_tuple!(@impl $name $ty); }; ($name:ident $ty:ident $( $N:ident $T:ident )+) => { impl_tuple!($( $N $T )+); impl_tuple!(@impl $name $ty $( $N $T )+); }; (@impl $( $N:ident $T:ident )+) => { impl<'a, S, Ctx, $( $T ),+> Parsable<'a, S, Ctx> for ($( $T, )+) where Ctx: Copy, $( $T: Parsable<'a, S, Ctx>, )+ { fn read(source: &'a S, context: Ctx) -> PResult { $( let ($N, source) = Parsable::read(source, context)?; )+ Ok((($( $N, )+), source)) } } impl<$( $T ),+> Deparsable for ($( $T, )+) where $( $T: Deparsable, )+ { fn write(&self, w: &mut impl std::io::Write) -> std::io::Result<()> { let ( $( $N, )+ ) = self; $( $N.write(&mut *w)?; )+ Ok(()) } } }; } impl_tuple!(a A b B c C d D e E f F g G h H); impl<'a, Src, Ctx, T> Parsable<'a, Src, Ctx> for Vec where Src: ?Sized, Ctx: Copy, T: Parsable<'a, Src, Ctx>, { fn read(mut source: &'a Src, context: Ctx) -> PResult { let mut v = Vec::new(); while let Ok((element, remainder)) = Parsable::read(source, context) { v.push(element); source = remainder; } Ok((v, source)) } } impl Deparsable for Vec where T: Deparsable, { fn write(&self, w: &mut impl std::io::Write) -> std::io::Result<()> { for element in self { element.write(&mut *w)?; } Ok(()) } } impl<'a, Src, Ctx, T> Parsable<'a, Src, Ctx> for Box where Src: ?Sized, T: Parsable<'a, Src, Ctx>, { fn read(source: &'a Src, context: Ctx) -> PResult { let (boxed, source) = Parsable::read(source, context)?; Ok((Box::new(boxed), source)) } } impl Deparsable for Box where T: Deparsable, { fn write(&self, w: &mut impl std::io::Write) -> std::io::Result<()> { self.deref().write(&mut *w) } } impl<'a, Src, Ctx, T> Parsable<'a, Src, Ctx> for Option where Src: ?Sized, T: Parsable<'a, Src, Ctx>, { fn read(source: &'a Src, context: Ctx) -> PResult { match Parsable::read(source, context) { Ok((inner, source)) => Ok((Some(inner), source)), Err(_) => Ok((None, source)), } } } impl Deparsable for Option where T: Deparsable, { fn write(&self, w: &mut impl std::io::Write) -> std::io::Result<()> { match self { Some(inner) => inner.write(&mut *w), None => Ok(()), } } } impl Parsable<'_, Src, Ctx> for PhantomData where Src: ?Sized, { fn read(source: &Src, _context: Ctx) -> PResult { Ok((PhantomData, source)) } }