qubit_codec/transcode/io/
async_transcode_decode_input.rs1use core::fmt;
11use std::collections::TryReserveError;
12use std::future::poll_fn;
13use std::io::Error;
14use std::io::ErrorKind;
15use std::io::Result;
16use std::pin::Pin;
17use std::task::Context;
18use std::task::Poll;
19
20use qubit_io::AsyncBufferedInput;
21use qubit_io::AsyncInput;
22use qubit_io::Buffer;
23use qubit_utils::SliceRange;
24use qubit_utils::allocation_error;
25
26use super::async_transcode_decode_step::AsyncTranscodeDecodeStep;
27use super::transcode_progress_validation::validate_decode_progress;
28use crate::CapacityError;
29use crate::TranscodeProgress;
30use crate::Transcoder;
31
32#[must_use]
52pub struct AsyncTranscodeDecodeInput<I>
53where
54 I: AsyncInput,
55 I::Item: Copy + Default,
56{
57 input: AsyncBufferedInput<I>,
59}
60
61impl<I> AsyncTranscodeDecodeInput<I>
62where
63 I: AsyncInput,
64 I::Item: Copy + Default,
65{
66 pub fn new(inner: I) -> Self {
76 Self {
77 input: AsyncBufferedInput::new(inner),
78 }
79 }
80
81 pub fn with_capacity(inner: I, capacity: usize) -> Self {
92 Self {
93 input: AsyncBufferedInput::with_capacity(inner, capacity),
94 }
95 }
96
97 pub fn try_with_capacity(inner: I, capacity: usize) -> std::result::Result<Self, TryReserveError> {
105 Ok(Self {
106 input: AsyncBufferedInput::try_with_capacity(inner, capacity)?,
107 })
108 }
109
110 #[must_use]
115 pub const fn inner(&self) -> &I {
116 self.input.inner()
117 }
118
119 #[must_use]
124 pub fn inner_mut(&mut self) -> &mut I {
125 self.input.inner_mut()
126 }
127
128 #[must_use]
130 pub const fn unread_len(&self) -> usize {
131 self.input.unread_len()
132 }
133
134 #[must_use]
136 pub fn unread(&self) -> &[I::Item] {
137 self.input.unread()
138 }
139
140 #[must_use]
142 pub fn capacity(&self) -> usize {
143 self.input.capacity()
144 }
145
146 pub fn consume(&mut self, count: usize) {
152 assert!(count <= self.unread_len(), "cannot consume beyond buffered input",);
153 unsafe {
155 self.input.consume(count);
156 }
157 }
158
159 pub unsafe fn copy_unread_to(&self, output: &mut [I::Item], output_index: usize, count: usize) {
167 unsafe {
169 self.input.copy_unread_to(output, output_index, count);
170 }
171 }
172
173 #[must_use = "the returned input and unread buffer must be handled"]
175 pub fn into_parts(self) -> (I, Buffer<I::Item>) {
176 self.input.into_parts()
177 }
178
179 pub fn reset<D, M, Value>(
189 &self,
190 decoder: &mut D,
191 map_error: &mut M,
192 output: &mut [Value],
193 output_index: usize,
194 count: usize,
195 ) -> Result<usize>
196 where
197 D: Transcoder<Input = I::Item, Output = Value>,
198 M: FnMut(D::Error) -> Error,
199 {
200 let required = decoder.max_reset_output_len().map_err(capacity_to_io_error)?;
201 let output_end = SliceRange::checked_range_end(
202 output.len(),
203 output_index,
204 count,
205 "reset output range exceeds destination buffer",
206 )?;
207 if count < required {
208 return Err(Error::new(
209 ErrorKind::InvalidData,
210 "insufficient output for decoder reset bound",
211 ));
212 }
213 let output = &mut output[..output_end];
214 let written = decoder.reset(output, output_index).map_err(&mut *map_error)?;
215 assert!(written <= required, "reset wrote beyond its bound");
216 Ok(written)
217 }
218
219 pub fn finish<D, M, Value>(
230 &self,
231 decoder: &mut D,
232 map_error: &mut M,
233 output: &mut [Value],
234 output_index: usize,
235 count: usize,
236 ) -> Result<usize>
237 where
238 D: Transcoder<Input = I::Item, Output = Value>,
239 M: FnMut(D::Error) -> Error,
240 {
241 let required = decoder.max_finish_output_len().map_err(capacity_to_io_error)?;
242 let output_end = SliceRange::checked_range_end(
243 output.len(),
244 output_index,
245 count,
246 "finish output range exceeds destination buffer",
247 )?;
248 if count < required {
249 return Err(Error::new(
250 ErrorKind::InvalidData,
251 "insufficient output for decoder finish bound",
252 ));
253 }
254 let output = &mut output[..output_end];
255 let written = decoder.finish(output, output_index).map_err(&mut *map_error)?;
256 assert!(written <= required, "finish wrote beyond its bound");
257 Ok(written)
258 }
259}
260
261impl<I> AsyncTranscodeDecodeInput<I>
262where
263 I: AsyncInput + Unpin,
264 I::Item: Copy + Default + Unpin,
265{
266 pub async fn fill_more_async(&mut self) -> Result<bool> {
276 self.input.fill_more_async().await
277 }
278
279 pub async fn fill_until_async(&mut self, count: usize) -> Result<bool> {
290 if count > self.input.capacity() {
291 self.input.try_reserve_capacity(count).map_err(allocation_error)?;
292 }
293 self.input.fill_until_async(count).await
294 }
295
296 pub fn poll_transcode<D, M, Value>(
310 mut self: Pin<&mut Self>,
311 cx: &mut Context<'_>,
312 decoder: &mut D,
313 map_error: &mut M,
314 output: &mut [Value],
315 output_index: usize,
316 count: usize,
317 ) -> Poll<Result<AsyncTranscodeDecodeStep>>
318 where
319 D: Transcoder<Input = I::Item, Output = Value>,
320 M: FnMut(D::Error) -> Error,
321 {
322 let output_end = SliceRange::checked_range_end(
323 output.len(),
324 output_index,
325 count,
326 "decoded output range exceeds destination buffer",
327 )?;
328 if count == 0 {
329 return Poll::Ready(Ok(AsyncTranscodeDecodeStep::Progress(TranscodeProgress::complete(
330 0, 0,
331 ))));
332 }
333 let output = &mut output[..output_end];
334 if self.as_ref().get_ref().unread_len() == 0 {
335 let this = self.as_mut().get_mut();
336 match Pin::new(&mut this.input).poll_fill_more(cx) {
337 Poll::Ready(Ok(true)) => {}
338 Poll::Ready(Ok(false)) => {
339 return Poll::Ready(Ok(AsyncTranscodeDecodeStep::EndOfInput));
340 }
341 Poll::Ready(Err(error)) => return Poll::Ready(Err(error)),
342 Poll::Pending => return Poll::Pending,
343 }
344 }
345 let this = self.as_mut().get_mut();
346 let available_input = this.unread_len();
347 let progress = decoder
348 .transcode(this.unread(), 0, output, output_index)
349 .map_err(&mut *map_error)
350 .and_then(|progress| validate_decode_progress(progress, 0, available_input, output_index, count));
351 let progress = match progress {
352 Ok(progress) => progress,
353 Err(error) => return Poll::Ready(Err(error)),
354 };
355 this.consume(progress.read());
356 Poll::Ready(Ok(AsyncTranscodeDecodeStep::Progress(progress)))
357 }
358
359 pub fn transcode_eof_step<D, M, Value>(
370 &mut self,
371 decoder: &mut D,
372 map_error: &mut M,
373 output: &mut [Value],
374 output_index: usize,
375 count: usize,
376 ) -> Result<TranscodeProgress>
377 where
378 D: Transcoder<Input = I::Item, Output = Value>,
379 M: FnMut(D::Error) -> Error,
380 {
381 let output_end = SliceRange::checked_range_end(
382 output.len(),
383 output_index,
384 count,
385 "decoded EOF output range exceeds destination buffer",
386 )?;
387 if count == 0 {
388 return Ok(TranscodeProgress::complete(0, 0));
389 }
390 if self.unread_len() == 0 {
391 return Ok(TranscodeProgress::complete(0, 0));
392 }
393 let available_input = self.unread_len();
394 let progress = decoder
395 .transcode_eof(self.unread(), 0, &mut output[..output_end], output_index)
396 .map_err(&mut *map_error)
397 .and_then(|progress| validate_decode_progress(progress, 0, available_input, output_index, count))?;
398 self.consume(progress.read());
399 Ok(progress)
400 }
401
402 pub async fn transcode_async<D, M, Value>(
409 &mut self,
410 decoder: &mut D,
411 map_error: &mut M,
412 output: &mut [Value],
413 output_index: usize,
414 count: usize,
415 ) -> Result<AsyncTranscodeDecodeStep>
416 where
417 D: Transcoder<Input = I::Item, Output = Value>,
418 M: FnMut(D::Error) -> Error,
419 {
420 poll_fn(|cx| Pin::new(&mut *self).poll_transcode(cx, decoder, map_error, output, output_index, count)).await
421 }
422}
423
424impl<I> AsyncInput for AsyncTranscodeDecodeInput<I>
425where
426 I: AsyncInput,
427 I::Item: Copy + Default,
428{
429 type Item = I::Item;
431
432 fn is_buffered(&self) -> bool {
434 true
435 }
436
437 unsafe fn poll_read_unchecked(
443 mut self: Pin<&mut Self>,
444 cx: &mut Context<'_>,
445 output: &mut [Self::Item],
446 index: usize,
447 count: usize,
448 ) -> Poll<Result<usize>> {
449 let input = unsafe { Pin::new_unchecked(&mut self.as_mut().get_unchecked_mut().input) };
451 unsafe { input.poll_read_unchecked(cx, output, index, count) }
453 }
454}
455
456impl<I> fmt::Debug for AsyncTranscodeDecodeInput<I>
457where
458 I: AsyncInput,
459 I::Item: Copy + Default,
460 AsyncBufferedInput<I>: fmt::Debug,
461{
462 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
464 formatter
465 .debug_struct("AsyncTranscodeDecodeInput")
466 .field("input", &self.input)
467 .finish()
468 }
469}
470
471fn capacity_to_io_error(error: CapacityError) -> Error {
473 Error::new(ErrorKind::InvalidData, error)
474}