use super::DecodeValue;
use crate::decoder::{DecodeIterError, Packet};
pub trait Partial: Sized {
type Final;
fn finalize(self) -> Result<Self::Final, &'static str>;
}
pub trait PartialIterator<P: Partial> {
fn next_resume(&mut self) -> Result<P::Final, DecodeIterError>;
fn next_fresh(&mut self) -> Result<P::Final, DecodeIterError>;
}
pub trait DecodePartial<S>: Sized + DecodeValue<S>
where
S: winnow::stream::Stream,
{
type Partial: Default + Partial<Final = Self>;
fn decode_partial(input: &mut S) -> Result<Packet<Self, Self::Partial>, &'static str>;
}
#[doc(hidden)]
pub trait ResumePartial<S>: DecodePartial<S>
where
S: winnow::stream::Stream,
{
fn resume_partial(
input: &mut S,
partial: Self::Partial,
) -> Result<Packet<Self, Self::Partial>, &'static str>;
}
impl<P: Partial> Partial for Vec<P> {
type Final = Vec<<P as Partial>::Final>;
#[inline(always)]
fn finalize(self) -> Result<Self::Final, &'static str> {
self.into_iter().map(P::finalize).collect()
}
}
impl<S, T> DecodePartial<S> for Vec<T>
where
S: winnow::stream::Stream,
T: DecodePartial<S>,
{
type Partial = Vec<<T as DecodePartial<S>>::Partial>;
fn decode_partial(input: &mut S) -> Result<Packet<Self, Self::Partial>, &'static str> {
let mut acc = Vec::new();
loop {
let before = input.eof_offset();
let cp = input.checkpoint();
match T::decode_partial(input) {
Ok(Packet::Ready(val)) => acc.push(val),
Ok(Packet::NeedMore(partial)) => {
if let Ok(last_elem) = partial.finalize() {
acc.push(last_elem);
}
return Ok(Packet::Ready(acc));
}
Err(label) => {
if input.eof_offset() == before {
input.reset(&cp);
return Ok(Packet::Ready(acc));
}
return Err(label);
}
}
}
}
}