Skip to main content

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}