1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
/*******************************************************************************
*
* Copyright (c) 2026 Haixing Hu.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0.
*
******************************************************************************/
//! Mutable state for one buffered encode call.
use core::num::NonZeroUsize;
use super::{
encode_context::EncodeContext,
transcode_progress::TranscodeProgress,
};
/// Mutable state for one buffered encode call.
pub(super) struct EncodeState<'a, Value, Unit> {
/// Complete input value slice visible to the encoder.
input: &'a [Value],
/// Absolute input value index where this call starts.
input_start: usize,
/// Complete output unit slice visible to the encoder.
output: &'a mut [Unit],
/// Absolute output unit index where this call starts.
output_start: usize,
/// Absolute input value index for the next encode attempt.
input_cursor: usize,
/// Absolute output unit index for the next write.
output_cursor: usize,
}
impl<'a, Value, Unit> EncodeState<'a, Value, Unit> {
/// Creates mutable encode state.
///
/// # Parameters
///
/// - `input`: Complete input value slice visible to the encoder.
/// - `input_index`: Absolute input value index where encoding starts.
/// - `output`: Complete output unit slice visible to the encoder.
/// - `output_index`: Absolute output unit index where writing starts.
///
/// # Returns
///
/// Returns initialized encode state with cursors at the requested start
/// positions.
#[inline(always)]
pub(super) fn new(input: &'a [Value], input_index: usize, output: &'a mut [Unit], 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,
}
}
/// Returns whether there is still input to encode.
///
/// # Returns
///
/// Returns `true` when more input values remain.
#[inline(always)]
pub(super) fn has_input(&self) -> bool {
self.input_cursor < self.input.len()
}
/// Returns an encode context at the current cursors.
///
/// # Safety
///
/// The caller must guarantee that `self.has_input()` returned `true`.
#[inline(always)]
pub(super) unsafe fn context_unchecked(&mut self) -> EncodeContext<'_, Value, Unit> {
// SAFETY: Guaranteed by the caller.
let value = unsafe { self.input.get_unchecked(self.input_cursor) };
EncodeContext {
input_value: value,
input_index: self.input_cursor,
output: &mut *self.output,
output_index: self.output_cursor,
}
}
/// Returns the number of writable output units from the current cursor.
///
/// # Returns
///
/// Returns writable output capacity from the current output cursor.
#[inline(always)]
fn available_output(&self) -> usize {
self.output.len().saturating_sub(self.output_cursor)
}
/// Accepts a completed one-value write and advances both cursors.
///
/// # Parameters
///
/// - `written`: Output units written by the last encode call.
///
/// # Returns
///
/// Returns unit `()`, while advancing `input_cursor` and `output_cursor`.
#[inline(always)]
pub(super) fn accept_written_value(&mut self, written: usize) {
assert!(
written <= self.available_output(),
"encode step wrote beyond available output",
);
self.input_cursor += 1;
self.output_cursor += written;
}
/// Returns completed progress for the current cursors.
///
/// # Returns
///
/// Returns a completed [`TranscodeProgress`] with consumed input and output
/// counters.
#[inline(always)]
pub(super) fn complete_progress(&self) -> TranscodeProgress {
TranscodeProgress::complete(
self.input_cursor - self.input_start,
self.output_cursor - self.output_start,
)
}
/// Returns progress for a known missing output capacity.
///
/// # Parameters
///
/// - `additional`: Additional output units required before encoding can continue.
/// - `available`: Output units currently writable at the stop boundary.
///
/// # Returns
///
/// Returns [`TranscodeProgress::need_output`] with missing-capacity counters.
#[inline(always)]
pub(super) fn need_output_progress_with(&self, additional: NonZeroUsize, available: usize) -> TranscodeProgress {
TranscodeProgress::need_output(
self.output_cursor,
additional,
available,
self.input_cursor - self.input_start,
self.output_cursor - self.output_start,
)
}
}