qubit_codec/buffered/transcode_progress.rs
1/*******************************************************************************
2 *
3 * Copyright (c) 2026 Haixing Hu.
4 *
5 * SPDX-License-Identifier: Apache-2.0
6 *
7 * Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10use core::num::NonZeroUsize;
11
12use super::TranscodeStatus;
13
14/// Counts how much work a [`crate::BufferedTranscoder`] completed before returning.
15#[derive(Clone, Copy, Debug, Eq, PartialEq)]
16pub struct TranscodeProgress {
17 /// Stop reason reported by the transcoder.
18 status: TranscodeStatus,
19 /// Number of input units consumed from the requested input index.
20 read: usize,
21 /// Number of output units written from the requested output index.
22 written: usize,
23}
24
25impl TranscodeProgress {
26 /// Creates a progress value.
27 ///
28 /// # Parameters
29 ///
30 /// - `status`: The reason conversion stopped.
31 /// - `read`: Number of input units consumed from the call's input index.
32 /// - `written`: Number of output units written from the call's output index.
33 ///
34 /// # Returns
35 ///
36 /// Returns a progress value carrying the supplied counters.
37 #[must_use]
38 #[inline(always)]
39 pub const fn new(status: TranscodeStatus, read: usize, written: usize) -> Self {
40 Self { status, read, written }
41 }
42
43 /// Creates a completed progress value.
44 ///
45 /// # Parameters
46 ///
47 /// - `read`: Number of consumed input units.
48 /// - `written`: Number of produced output units.
49 ///
50 /// # Returns
51 ///
52 /// Returns a progress value whose status is [`TranscodeStatus::Complete`].
53 #[must_use]
54 #[inline(always)]
55 pub const fn complete(read: usize, written: usize) -> Self {
56 Self::new(TranscodeStatus::Complete, read, written)
57 }
58
59 /// Creates progress that stopped because more input is needed.
60 ///
61 /// # Parameters
62 ///
63 /// - `input_index`: Absolute input boundary where conversion stopped.
64 /// - `additional`: Additional input units required to continue.
65 /// - `available`: Input units currently available at the boundary.
66 /// - `read`: Number of consumed input units.
67 /// - `written`: Number of produced output units.
68 ///
69 /// # Returns
70 ///
71 /// Returns a progress value with [`TranscodeStatus::NeedInput`].
72 #[must_use]
73 #[inline(always)]
74 pub const fn need_input(
75 input_index: usize,
76 additional: NonZeroUsize,
77 available: usize,
78 read: usize,
79 written: usize,
80 ) -> Self {
81 Self::new(
82 TranscodeStatus::need_input(input_index, additional, available),
83 read,
84 written,
85 )
86 }
87
88 /// Creates progress that stopped because more output capacity is needed.
89 ///
90 /// # Parameters
91 ///
92 /// - `output_index`: Absolute output boundary where conversion stopped.
93 /// - `additional`: Additional output units required to continue.
94 /// - `available`: Output units currently available at the boundary.
95 /// - `read`: Number of consumed input units.
96 /// - `written`: Number of produced output units.
97 ///
98 /// # Returns
99 ///
100 /// Returns a progress value with [`TranscodeStatus::NeedOutput`].
101 #[must_use]
102 #[inline(always)]
103 pub const fn need_output(
104 output_index: usize,
105 additional: NonZeroUsize,
106 available: usize,
107 read: usize,
108 written: usize,
109 ) -> Self {
110 Self::new(
111 TranscodeStatus::need_output(output_index, additional, available),
112 read,
113 written,
114 )
115 }
116
117 /// Returns the status that stopped conversion.
118 ///
119 /// # Returns
120 ///
121 /// Returns the stored [`TranscodeStatus`].
122 #[must_use]
123 #[inline(always)]
124 pub const fn status(self) -> TranscodeStatus {
125 self.status
126 }
127
128 /// Returns the number of input units consumed by the call.
129 ///
130 /// # Returns
131 ///
132 /// Returns a count relative to the input index passed to the conversion call.
133 #[must_use]
134 #[inline(always)]
135 pub const fn read(self) -> usize {
136 self.read
137 }
138
139 /// Returns the number of output units written by the call.
140 ///
141 /// # Returns
142 ///
143 /// Returns a count relative to the output index passed to the conversion call.
144 #[must_use]
145 #[inline(always)]
146 pub const fn written(self) -> usize {
147 self.written
148 }
149
150 /// Rebases `read` and `written` onto `self` while preserving its stop reason.
151 ///
152 /// Nested engines report progress scoped to one sub-step. Callers that
153 /// orchestrate several sub-steps must replace those counters with totals
154 /// relative to the outer call while keeping boundary fields from the
155 /// sub-step status.
156 ///
157 /// # Parameters
158 ///
159 /// - `read`: Input units consumed relative to the outer call's input index.
160 /// - `written`: Output units written relative to the outer call's output index.
161 ///
162 /// # Returns
163 ///
164 /// Returns progress with the same status as `self` and the supplied counters.
165 #[must_use]
166 #[inline(always)]
167 pub const fn with_counters(self, read: usize, written: usize) -> Self {
168 match self.status {
169 TranscodeStatus::Complete => Self::complete(read, written),
170 TranscodeStatus::NeedInput {
171 input_index,
172 additional,
173 available,
174 } => Self::need_input(input_index, additional, available, read, written),
175 TranscodeStatus::NeedOutput {
176 output_index,
177 additional,
178 available,
179 } => Self::need_output(output_index, additional, available, read, written),
180 }
181 }
182
183 /// Returns the additional unit count required by the reported status.
184 ///
185 /// # Returns
186 ///
187 /// Returns `Some` with a non-zero count when conversion needs more input or
188 /// output. Returns `None` when conversion completed.
189 #[must_use]
190 #[inline(always)]
191 pub const fn additional(self) -> Option<NonZeroUsize> {
192 match self.status {
193 TranscodeStatus::Complete => None,
194 TranscodeStatus::NeedInput { additional, .. } => Some(additional),
195 TranscodeStatus::NeedOutput { additional, .. } => Some(additional),
196 }
197 }
198
199 /// Returns the absolute boundary index associated with this status, if any.
200 ///
201 /// - For [`TranscodeStatus::NeedInput`], returns `input_index`.
202 /// - For [`TranscodeStatus::NeedOutput`], returns `output_index`.
203 /// - For [`TranscodeStatus::Complete`], returns `None`.
204 /// # Returns
205 ///
206 /// Returns the boundary index for non-complete status values.
207 #[must_use]
208 #[inline(always)]
209 pub const fn index(self) -> Option<usize> {
210 match self.status {
211 TranscodeStatus::Complete => None,
212 TranscodeStatus::NeedInput { input_index, .. } => Some(input_index),
213 TranscodeStatus::NeedOutput { output_index, .. } => Some(output_index),
214 }
215 }
216
217 /// Returns the number of available units at the reported status boundary.
218 ///
219 /// # Returns
220 ///
221 /// Returns `0` when conversion completed.
222 #[must_use]
223 #[inline(always)]
224 pub const fn available(self) -> usize {
225 match self.status {
226 TranscodeStatus::Complete => 0,
227 TranscodeStatus::NeedInput { available, .. } => available,
228 TranscodeStatus::NeedOutput { available, .. } => available,
229 }
230 }
231}