use core::num::NonZeroUsize;
use super::super::{
decode_context::DecodeContext,
transcode_progress::TranscodeProgress,
};
pub(in crate::transcode) struct DecodeState<'a, Unit, Value> {
input: &'a [Unit],
input_start: usize,
output: &'a mut [Value],
output_start: usize,
input_cursor: usize,
output_cursor: usize,
}
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 {
debug_assert!(
input_index <= input.len(),
"input index must be within the input slice"
);
Self {
input,
input_start: input_index,
output,
output_start: output_index,
input_cursor: input_index,
output_cursor: output_index,
}
}
#[inline(always)]
pub(in crate::transcode) fn input(&self) -> &[Unit] {
self.input
}
#[inline(always)]
pub(in crate::transcode) fn has_input(&self) -> bool {
self.input_cursor < self.input.len()
}
#[inline(always)]
pub(in crate::transcode) fn needs_output(&self) -> bool {
self.output_cursor == self.output.len()
}
#[inline(always)]
fn available(&self) -> usize {
self.input.len() - self.input_cursor
}
#[inline(always)]
pub(in crate::transcode) fn context(&self) -> DecodeContext {
DecodeContext::new(
self.input_start,
self.input_cursor,
self.output_start,
self.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.input_cursor += 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",
);
unsafe {
*qubit_io::UncheckedSlice::get_mut(
self.output,
self.output_cursor,
) = value;
}
self.input_cursor += consumed;
self.output_cursor += 1;
}
#[inline(always)]
pub(in crate::transcode) fn complete_progress(&self) -> TranscodeProgress {
TranscodeProgress::complete(
self.input_cursor - self.input_start,
self.output_cursor - self.output_start,
)
}
#[inline(always)]
pub(in crate::transcode) fn need_output_progress(
&self,
) -> TranscodeProgress {
let context = self.context();
TranscodeProgress::need_output(
context.output_index(),
NonZeroUsize::MIN,
0,
self.input_cursor - self.input_start,
self.output_cursor - self.output_start,
)
}
#[inline(always)]
pub(in crate::transcode) fn need_input_progress_with(
&self,
additional: NonZeroUsize,
available: usize,
) -> TranscodeProgress {
TranscodeProgress::need_input(
self.input_cursor,
additional,
available,
self.input_cursor - self.input_start,
self.output_cursor - self.output_start,
)
}
}