use core::num::NonZeroUsize;
use qubit_io::UncheckedSlice;
use super::super::{
encode_context::EncodeContext,
encode_outcome::EncodeOutcome,
transcode_progress::TranscodeProgress,
};
use super::transcode_state::TranscodeState;
pub(in crate::transcode) struct EncodeState<'a, Value, Unit> {
state: TranscodeState<'a, Value, Unit>,
}
impl<'a, Value, Unit> EncodeState<'a, Value, Unit> {
#[inline(always)]
pub(in crate::transcode) fn new(
input: &'a [Value],
input_index: usize,
output: &'a mut [Unit],
output_index: usize,
) -> Self {
Self {
state: TranscodeState::new(
input,
input_index,
output,
output_index,
),
}
}
#[inline(always)]
pub(in crate::transcode) fn has_input(&self) -> bool {
self.state.has_input()
}
#[inline(always)]
pub(in crate::transcode) unsafe fn context_unchecked(
&mut self,
) -> EncodeContext<'_, Value, Unit> {
let input_index = self.state.input_cursor();
let output_index = self.state.output_cursor();
let (input, output) = self.state.input_output_mut();
let value = unsafe { UncheckedSlice::get(input, input_index) };
EncodeContext::new(value, input_index, output, output_index)
}
#[inline(always)]
fn available_output(&self) -> usize {
self.state.available_output()
}
#[inline(always)]
pub(in crate::transcode) fn accept_written_value(
&mut self,
written: usize,
) {
assert!(
written <= self.available_output(),
"EncodeOutcome::Consumed wrote beyond available output",
);
self.state.advance(1, written);
}
#[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_with(
&self,
required: NonZeroUsize,
available: usize,
) -> TranscodeProgress {
self.state.need_output_progress(required, available)
}
#[inline]
pub(in crate::transcode) fn apply_encode_outcome(
&mut self,
outcome: EncodeOutcome,
) -> Option<TranscodeProgress> {
match outcome {
EncodeOutcome::Consumed { written } => {
self.accept_written_value(written);
None
}
EncodeOutcome::NeedOutput { required } => {
let available = self.available_output();
assert!(
required.get() > available,
"EncodeOutcome::NeedOutput required capacity must exceed available output",
);
Some(self.need_output_progress_with(required, available))
}
}
}
}