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
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
/*******************************************************************************
*
* Copyright (c) 2026 Haixing Hu.
*
* SPDX-License-Identifier: Apache-2.0
*
* Licensed under the Apache License, Version 2.0.
*
******************************************************************************/
//! Internal decode-step result used by buffered converters.
use core::num::NonZeroUsize;
use super::{
convert_state::ConvertState,
decode_state::DecodeState,
pending_value::PendingValue,
transcode_progress::TranscodeProgress,
};
/// Result of one decode step in the converter loop.
#[derive(Clone, Copy, Debug, Eq, Hash, PartialEq)]
pub(super) enum DecodeStep<Value> {
/// A source value was decoded or emitted by policy.
Decoded {
/// Decoded logical value.
value: Value,
/// Number of consumed source units.
consumed: NonZeroUsize,
/// Source input index used for downstream encode context.
input_index: usize,
},
/// Source input was consumed without producing a value.
Skipped {
/// Number of consumed source units.
consumed: NonZeroUsize,
},
/// More source input is required before decoding can continue.
NeedInput {
/// Additional source units required to continue.
additional: NonZeroUsize,
/// Source units available at the incomplete boundary.
available: usize,
},
}
impl<Value> DecodeStep<Value> {
/// Creates a decoded-value step.
///
/// # Parameters
///
/// - `value`: Decoded logical value.
/// - `consumed`: Number of consumed source units.
/// - `input_index`: Source index used for downstream encode context.
///
/// # Returns
///
/// Returns a decoded step.
#[inline(always)]
pub(super) const fn decoded(value: Value, consumed: NonZeroUsize, input_index: usize) -> Self {
Self::Decoded {
value,
consumed,
input_index,
}
}
/// Creates a skipped-input step.
///
/// # Parameters
///
/// - `consumed`: Number of consumed source units.
///
/// # Returns
///
/// Returns a skipped step.
#[inline(always)]
pub(super) const fn skipped(consumed: NonZeroUsize) -> Self {
Self::Skipped { consumed }
}
/// Creates a missing-input step.
///
/// # Parameters
///
/// - `additional`: Additional source units required to continue.
/// - `available`: Source units currently available.
///
/// # Returns
///
/// Returns a need-input step.
#[inline(always)]
pub(super) const fn need_input(additional: NonZeroUsize, available: usize) -> Self {
Self::NeedInput { additional, available }
}
/// Applies this decode step to the current conversion state.
///
/// For each variant:
///
/// - `Decoded`: advances input cursor and passes the decoded value into the
/// converter encode path.
/// - `Skipped`: only advances input cursor.
/// - `NeedInput`: returns [`TranscodeProgress`] requesting additional input.
///
/// # Parameters
///
/// - `state`: Current conversion-call state.
/// - `encode`: Callback to emit a decoded value into the shared convert
/// state.
///
/// # Type Parameters
///
/// - `Input`: Input-unit type stored in the active [`ConvertState`].
/// - `Output`: Output-unit type stored in the active [`ConvertState`].
/// - `Error`: Error type produced by the encode callback.
/// - `F`: Callback type that consumes a decoded value and updates state.
///
/// # Returns
///
/// Returns:
/// - `Ok(Some(progress))` when conversion must stop,
/// - `Ok(None)` when conversion can continue, or
/// - `Err(error)` when emitting the decoded value fails.
#[inline]
pub(super) fn apply_to_convert_state<Input, Output, Error, F>(
self,
state: &mut ConvertState<'_, Input, Output>,
mut encode: F,
) -> Result<Option<TranscodeProgress>, Error>
where
F: FnMut(PendingValue<Value>, &mut ConvertState<'_, Input, Output>) -> Result<Option<TranscodeProgress>, Error>,
{
match self {
Self::Decoded {
value,
consumed,
input_index,
} => {
state.advance_input(consumed.get());
encode(PendingValue::new(value, input_index), state)
}
Self::Skipped { consumed } => {
state.advance_input(consumed.get());
Ok(None)
}
Self::NeedInput { additional, available } => Ok(Some(state.need_input_progress(additional, available))),
}
}
/// Applies this decode step to the current decode state.
///
/// # Parameters
///
/// - `state`: Current decode-call state.
///
/// # Type Parameters
///
/// - `Unit`: Decode input-unit type represented by this [`DecodeState`].
///
/// # Returns
///
/// Returns optional public stop progress when decoding cannot continue in this
/// call.
#[must_use]
#[inline]
pub(super) fn apply_to_decode_state<Unit>(
self,
state: &mut DecodeState<'_, Unit, Value>,
) -> Option<TranscodeProgress> {
match self {
Self::Decoded { value, consumed, .. } => {
if state.needs_output() {
return Some(state.need_output_progress());
}
state.emit(value, consumed);
None
}
Self::Skipped { consumed } => {
state.skip(consumed);
None
}
Self::NeedInput { additional, available } => Some(state.need_input_progress_with(additional, available)),
}
}
}