use core::num::NonZeroUsize;
use super::super::{
decode_context::DecodeContext,
transcode_progress::TranscodeProgress,
};
use super::decode_step::DecodeStep;
use super::transcode_state::TranscodeState;
pub(in crate::transcode) struct DecodeState<'a, Unit, Value> {
state: TranscodeState<'a, Unit, Value>,
}
impl<'a, Unit, Value> DecodeState<'a, Unit, Value> {
#[inline(always)]
pub(in crate::transcode) fn new(
input: &'a [Unit],
input_index: usize,
output: &'a mut [Value],
output_index: usize,
) -> Self {
Self {
state: TranscodeState::new(
input,
input_index,
output,
output_index,
),
}
}
#[inline(always)]
pub(in crate::transcode) fn input(&self) -> &[Unit] {
self.state.input()
}
#[inline(always)]
pub(in crate::transcode) fn has_input(&self) -> bool {
self.state.has_input()
}
#[inline(always)]
pub(in crate::transcode) fn needs_output(&self) -> bool {
self.state.needs_output()
}
#[inline(always)]
fn available(&self) -> usize {
self.state.available_input()
}
#[inline(always)]
pub(in crate::transcode) fn context(&self) -> DecodeContext {
DecodeContext::new(
self.state.input_start(),
self.state.input_cursor(),
self.state.output_start(),
self.state.output_cursor(),
self.available(),
)
}
#[inline(always)]
pub(in crate::transcode) fn skip(&mut self, consumed: NonZeroUsize) {
let consumed = consumed.get();
assert!(
consumed <= self.available(),
"decode step consumed beyond available input",
);
self.state.advance_input(consumed);
}
#[inline(always)]
pub(in crate::transcode) fn emit(
&mut self,
value: Value,
consumed: NonZeroUsize,
) {
let consumed = consumed.get();
assert!(
consumed <= self.available(),
"decode step consumed beyond available input",
);
assert!(
!self.needs_output(),
"decode step emitted without output capacity",
);
let output_cursor = self.state.output_cursor();
unsafe {
*qubit_io::UncheckedSlice::get_mut(
self.state.output_mut(),
output_cursor,
) = value;
}
self.state.advance(consumed, 1);
}
#[inline(always)]
pub(in crate::transcode) fn complete_progress(&self) -> TranscodeProgress {
self.state.complete_progress()
}
#[inline(always)]
pub(in crate::transcode) fn need_output_progress(
&self,
) -> TranscodeProgress {
self.state.need_output_progress(NonZeroUsize::MIN, 0)
}
#[inline(always)]
pub(in crate::transcode) fn need_input_progress_with(
&self,
required: NonZeroUsize,
available: usize,
) -> TranscodeProgress {
self.state.need_input_progress(required, available)
}
#[inline]
#[must_use]
pub(in crate::transcode) fn apply_decode_step(
&mut self,
step: DecodeStep<Value>,
) -> Option<TranscodeProgress> {
match step {
DecodeStep::Decoded {
value, consumed, ..
} => {
self.emit(value, consumed);
None
}
DecodeStep::Skipped { consumed } => {
self.skip(consumed);
None
}
DecodeStep::NeedInput {
required,
available,
} => Some(self.need_input_progress_with(required, available)),
}
}
}