use core::num::NonZeroUsize;
use super::super::transcode_progress::TranscodeProgress;
use super::{
convert_state::ConvertState,
decode_state::DecodeState,
pending_value::PendingValue,
};
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub(in crate::transcode) enum DecodeStep<Value> {
Decoded {
value: Value,
consumed: NonZeroUsize,
input_index: usize,
},
Skipped {
consumed: NonZeroUsize,
},
NeedInput {
additional: NonZeroUsize,
available: usize,
},
}
impl<Value> DecodeStep<Value> {
#[inline(always)]
pub(in crate::transcode) const fn decoded(
value: Value,
consumed: NonZeroUsize,
input_index: usize,
) -> Self {
Self::Decoded {
value,
consumed,
input_index,
}
}
#[inline(always)]
pub(in crate::transcode) const fn skipped(consumed: NonZeroUsize) -> Self {
Self::Skipped { consumed }
}
#[inline(always)]
pub(in crate::transcode) const fn need_input(
additional: NonZeroUsize,
available: usize,
) -> Self {
Self::NeedInput {
additional,
available,
}
}
#[inline]
pub(in crate::transcode) fn apply_to_convert_state<
Input,
Output,
Error,
F,
>(
self,
state: &mut ConvertState<'_, Input, Output>,
mut encode: F,
) -> Result<Option<TranscodeProgress>, Error>
where
F: FnMut(
PendingValue<Value>,
&mut ConvertState<'_, Input, Output>,
) -> Result<Option<TranscodeProgress>, Error>,
{
match self {
Self::Decoded {
value,
consumed,
input_index,
} => {
state.advance_input(consumed.get());
encode(PendingValue::new(value, input_index), state)
}
Self::Skipped { consumed } => {
state.advance_input(consumed.get());
Ok(None)
}
Self::NeedInput {
additional,
available,
} => Ok(Some(state.need_input_progress(additional, available))),
}
}
#[must_use]
#[inline]
pub(in crate::transcode) fn apply_to_decode_state<Unit>(
self,
state: &mut DecodeState<'_, Unit, Value>,
) -> Option<TranscodeProgress> {
match self {
Self::Decoded {
value, consumed, ..
} => {
if state.needs_output() {
return Some(state.need_output_progress());
}
state.emit(value, consumed);
None
}
Self::Skipped { consumed } => {
state.skip(consumed);
None
}
Self::NeedInput {
additional,
available,
} => Some(state.need_input_progress_with(additional, available)),
}
}
}