use core::num::NonZeroUsize;
use super::super::engine::DecodeContext;
use super::super::engine::DecodeOutcome;
use super::super::engine::EncodeOutcome;
use super::super::transcode_progress::TranscodeProgress;
use super::transcode_state::TranscodeState;
pub(crate) struct ConvertState<'a, Input, Output> {
state: TranscodeState<'a, Input, Output>,
}
impl<'a, Input, Output> ConvertState<'a, Input, Output> {
#[inline]
#[must_use]
pub(crate) fn new(input: &'a [Input], input_index: usize, output: &'a mut [Output], output_index: usize) -> Self {
Self {
state: TranscodeState::new(input, input_index, output, output_index),
}
}
#[inline]
#[must_use]
pub(crate) fn input(&self) -> &[Input] {
self.state.input()
}
#[inline]
#[must_use]
pub(crate) fn output_mut(&mut self) -> &mut [Output] {
self.state.output_mut()
}
#[inline]
#[must_use]
pub(crate) fn output_cursor(&self) -> usize {
self.state.output_cursor()
}
#[inline]
#[must_use]
pub(crate) fn has_input(&self) -> bool {
self.state.has_input()
}
#[inline]
#[must_use]
pub(crate) fn available_input(&self) -> usize {
self.state.available_input()
}
#[inline]
#[must_use]
pub(crate) fn available_output(&self) -> usize {
self.state.available_output()
}
#[inline]
#[must_use]
pub(crate) fn decode_context(&self) -> DecodeContext {
DecodeContext::new(
self.state.input_start(),
self.state.input_cursor(),
self.state.output_start(),
self.state.output_cursor(),
self.available_input(),
)
}
#[inline]
#[must_use]
pub(crate) fn read(&self) -> usize {
self.state.read()
}
#[inline]
#[must_use]
pub(crate) fn written(&self) -> usize {
self.state.written()
}
#[inline]
pub(crate) fn complete_progress(&self) -> TranscodeProgress {
self.state.complete_progress()
}
#[inline]
pub(crate) fn need_input_progress(&self, required: NonZeroUsize) -> TranscodeProgress {
self.state.need_input_progress(required)
}
#[inline]
pub(crate) fn need_output_progress(&self, required: NonZeroUsize) -> TranscodeProgress {
self.state.need_output_progress(required)
}
#[inline]
pub(crate) fn advance_input(&mut self, read: usize) {
assert!(read <= self.available_input(), "conversion step read beyond input",);
self.state.advance_input(read);
}
#[inline]
pub(crate) fn advance_output(&mut self, written: usize) {
assert!(
written <= self.available_output(),
"conversion step wrote beyond output",
);
self.state.advance_output(written);
}
#[inline]
pub(crate) fn apply_decode_outcome(&mut self, outcome: DecodeOutcome) -> Option<TranscodeProgress> {
match outcome {
DecodeOutcome::Emitted { read, emitted } => {
assert_eq!(
emitted,
NonZeroUsize::MIN,
"converter decode outcome can carry only one pending value",
);
self.advance_input(read.get());
None
}
DecodeOutcome::Skipped { read } => {
self.advance_input(read.get());
None
}
DecodeOutcome::NeedInput { required } => Some(self.need_input_progress(required)),
}
}
#[inline]
pub(crate) fn apply_encode_outcome(&mut self, outcome: EncodeOutcome) -> Option<TranscodeProgress> {
match outcome {
EncodeOutcome::Consumed { written } => {
self.advance_output(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(required))
}
}
}
}