parst 0.2.0

declarative parsing
Documentation
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<Self> {
		try_from_fn(|_| {
			let (element, this_bytes) = Parsable::read(source, context)?;
			source = this_bytes;
			Ok(element)
		})
		.map(|array| (array, source))
	}
}

impl<T, const N: usize> 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<Self, S> {
                $(
                    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<T>
where
	Src: ?Sized,
	Ctx: Copy,
	T: Parsable<'a, Src, Ctx>,
{
	fn read(mut source: &'a Src, context: Ctx) -> PResult<Self, Src> {
		let mut v = Vec::new();
		while let Ok((element, remainder)) = Parsable::read(source, context) {
			v.push(element);
			source = remainder;
		}
		Ok((v, source))
	}
}

impl<T> Deparsable for Vec<T>
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<T>
where
	Src: ?Sized,
	T: Parsable<'a, Src, Ctx>,
{
	fn read(source: &'a Src, context: Ctx) -> PResult<Self, Src> {
		let (boxed, source) = Parsable::read(source, context)?;
		Ok((Box::new(boxed), source))
	}
}

impl<T> Deparsable for Box<T>
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<T>
where
	Src: ?Sized,
	T: Parsable<'a, Src, Ctx>,
{
	fn read(source: &'a Src, context: Ctx) -> PResult<Self, Src> {
		match Parsable::read(source, context) {
			Ok((inner, source)) => Ok((Some(inner), source)),
			Err(_) => Ok((None, source)),
		}
	}
}

impl<T> Deparsable for Option<T>
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<Src, Ctx, T> Parsable<'_, Src, Ctx> for PhantomData<T>
where
	Src: ?Sized,
{
	fn read(source: &Src, _context: Ctx) -> PResult<Self, Src> { Ok((PhantomData, source)) }
}