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]
41pub struct AsyncTranscodeDecodeInput<I>
42where
43 I: AsyncInput,
44 I::Item: Copy + Default,
45{
46 input: AsyncBufferedInput<I>,
48}
49
50impl<I> AsyncTranscodeDecodeInput<I>
51where
52 I: AsyncInput,
53 I::Item: Copy + Default,
54{
55 pub fn new(inner: I) -> Self {
65 Self {
66 input: AsyncBufferedInput::new(inner),
67 }
68 }
69
70 pub fn with_capacity(inner: I, capacity: usize) -> Self {
81 Self {
82 input: AsyncBufferedInput::with_capacity(inner, capacity),
83 }
84 }
85
86 pub fn try_with_capacity(inner: I, capacity: usize) -> std::result::Result<Self, TryReserveError> {
94 Ok(Self {
95 input: AsyncBufferedInput::try_with_capacity(inner, capacity)?,
96 })
97 }
98
99 #[must_use]
104 pub const fn inner(&self) -> &I {
105 self.input.inner()
106 }
107
108 #[must_use]
113 pub fn inner_mut(&mut self) -> &mut I {
114 self.input.inner_mut()
115 }
116
117 #[must_use]
119 pub const fn unread_len(&self) -> usize {
120 self.input.unread_len()
121 }
122
123 #[must_use]
125 pub fn unread(&self) -> &[I::Item] {
126 self.input.unread()
127 }
128
129 #[must_use]
131 pub fn capacity(&self) -> usize {
132 self.input.capacity()
133 }
134
135 pub fn consume(&mut self, count: usize) {
141 assert!(count <= self.unread_len(), "cannot consume beyond buffered input",);
142 unsafe {
144 self.input.consume(count);
145 }
146 }
147
148 pub unsafe fn copy_unread_to(&self, output: &mut [I::Item], output_index: usize, count: usize) {
156 unsafe {
158 self.input.copy_unread_to(output, output_index, count);
159 }
160 }
161
162 #[must_use = "the returned input and unread buffer must be handled"]
164 pub fn into_parts(self) -> (I, Buffer<I::Item>) {
165 self.input.into_parts()
166 }
167
168 pub fn reset<D, M, Value>(
178 &self,
179 decoder: &mut D,
180 map_error: &mut M,
181 output: &mut [Value],
182 output_index: usize,
183 count: usize,
184 ) -> Result<usize>
185 where
186 D: Transcoder<Input = I::Item, Output = Value>,
187 M: FnMut(D::Error) -> Error,
188 {
189 let required = decoder.max_reset_output_len().map_err(capacity_to_io_error)?;
190 let output_end = SliceRange::checked_range_end(
191 output.len(),
192 output_index,
193 count,
194 "reset output range exceeds destination buffer",
195 )?;
196 if count < required {
197 return Err(Error::new(
198 ErrorKind::InvalidData,
199 "insufficient output for decoder reset bound",
200 ));
201 }
202 let output = &mut output[..output_end];
203 let written = decoder.reset(output, output_index).map_err(&mut *map_error)?;
204 assert!(written <= required, "reset wrote beyond its bound");
205 Ok(written)
206 }
207
208 pub fn finish<D, M, Value>(
219 &self,
220 decoder: &mut D,
221 map_error: &mut M,
222 output: &mut [Value],
223 output_index: usize,
224 count: usize,
225 ) -> Result<usize>
226 where
227 D: Transcoder<Input = I::Item, Output = Value>,
228 M: FnMut(D::Error) -> Error,
229 {
230 let required = decoder.max_finish_output_len().map_err(capacity_to_io_error)?;
231 let output_end = SliceRange::checked_range_end(
232 output.len(),
233 output_index,
234 count,
235 "finish output range exceeds destination buffer",
236 )?;
237 if count < required {
238 return Err(Error::new(
239 ErrorKind::InvalidData,
240 "insufficient output for decoder finish bound",
241 ));
242 }
243 let output = &mut output[..output_end];
244 let written = decoder.finish(output, output_index).map_err(&mut *map_error)?;
245 assert!(written <= required, "finish wrote beyond its bound");
246 Ok(written)
247 }
248}
249
250impl<I> AsyncTranscodeDecodeInput<I>
251where
252 I: AsyncInput + Unpin,
253 I::Item: Copy + Default + Unpin,
254{
255 pub async fn fill_more_async(&mut self) -> Result<bool> {
265 self.input.fill_more_async().await
266 }
267
268 pub async fn fill_until_async(&mut self, count: usize) -> Result<bool> {
279 if count > self.input.capacity() {
280 self.input.try_reserve_capacity(count).map_err(allocation_error)?;
281 }
282 self.input.fill_until_async(count).await
283 }
284
285 pub fn poll_transcode<D, M, Value>(
299 mut self: Pin<&mut Self>,
300 cx: &mut Context<'_>,
301 decoder: &mut D,
302 map_error: &mut M,
303 output: &mut [Value],
304 output_index: usize,
305 count: usize,
306 ) -> Poll<Result<AsyncTranscodeDecodeStep>>
307 where
308 D: Transcoder<Input = I::Item, Output = Value>,
309 M: FnMut(D::Error) -> Error,
310 {
311 let output_end = SliceRange::checked_range_end(
312 output.len(),
313 output_index,
314 count,
315 "decoded output range exceeds destination buffer",
316 )?;
317 if count == 0 {
318 return Poll::Ready(Ok(AsyncTranscodeDecodeStep::Progress(TranscodeProgress::complete(
319 0, 0,
320 ))));
321 }
322 let output = &mut output[..output_end];
323 if self.as_ref().get_ref().unread_len() == 0 {
324 let this = self.as_mut().get_mut();
325 match Pin::new(&mut this.input).poll_fill_more(cx) {
326 Poll::Ready(Ok(true)) => {}
327 Poll::Ready(Ok(false)) => {
328 return Poll::Ready(Ok(AsyncTranscodeDecodeStep::EndOfInput));
329 }
330 Poll::Ready(Err(error)) => return Poll::Ready(Err(error)),
331 Poll::Pending => return Poll::Pending,
332 }
333 }
334 let this = self.as_mut().get_mut();
335 let available_input = this.unread_len();
336 let progress = decoder
337 .transcode(this.unread(), 0, output, output_index)
338 .map_err(&mut *map_error)
339 .and_then(|progress| validate_decode_progress(progress, 0, available_input, output_index, count));
340 let progress = match progress {
341 Ok(progress) => progress,
342 Err(error) => return Poll::Ready(Err(error)),
343 };
344 this.consume(progress.read());
345 Poll::Ready(Ok(AsyncTranscodeDecodeStep::Progress(progress)))
346 }
347
348 pub fn transcode_eof_step<D, M, Value>(
359 &mut self,
360 decoder: &mut D,
361 map_error: &mut M,
362 output: &mut [Value],
363 output_index: usize,
364 count: usize,
365 ) -> Result<TranscodeProgress>
366 where
367 D: Transcoder<Input = I::Item, Output = Value>,
368 M: FnMut(D::Error) -> Error,
369 {
370 let output_end = SliceRange::checked_range_end(
371 output.len(),
372 output_index,
373 count,
374 "decoded EOF output range exceeds destination buffer",
375 )?;
376 if count == 0 {
377 return Ok(TranscodeProgress::complete(0, 0));
378 }
379 if self.unread_len() == 0 {
380 return Ok(TranscodeProgress::complete(0, 0));
381 }
382 let available_input = self.unread_len();
383 let progress = decoder
384 .transcode_eof(self.unread(), 0, &mut output[..output_end], output_index)
385 .map_err(&mut *map_error)
386 .and_then(|progress| validate_decode_progress(progress, 0, available_input, output_index, count))?;
387 self.consume(progress.read());
388 Ok(progress)
389 }
390
391 pub async fn transcode_async<D, M, Value>(
398 &mut self,
399 decoder: &mut D,
400 map_error: &mut M,
401 output: &mut [Value],
402 output_index: usize,
403 count: usize,
404 ) -> Result<AsyncTranscodeDecodeStep>
405 where
406 D: Transcoder<Input = I::Item, Output = Value>,
407 M: FnMut(D::Error) -> Error,
408 {
409 poll_fn(|cx| Pin::new(&mut *self).poll_transcode(cx, decoder, map_error, output, output_index, count)).await
410 }
411}
412
413impl<I> AsyncInput for AsyncTranscodeDecodeInput<I>
414where
415 I: AsyncInput,
416 I::Item: Copy + Default,
417{
418 type Item = I::Item;
420
421 fn is_buffered(&self) -> bool {
423 true
424 }
425
426 unsafe fn poll_read_unchecked(
432 mut self: Pin<&mut Self>,
433 cx: &mut Context<'_>,
434 output: &mut [Self::Item],
435 index: usize,
436 count: usize,
437 ) -> Poll<Result<usize>> {
438 let input = unsafe { Pin::new_unchecked(&mut self.as_mut().get_unchecked_mut().input) };
440 unsafe { input.poll_read_unchecked(cx, output, index, count) }
442 }
443}
444
445impl<I> fmt::Debug for AsyncTranscodeDecodeInput<I>
446where
447 I: AsyncInput,
448 I::Item: Copy + Default,
449 AsyncBufferedInput<I>: fmt::Debug,
450{
451 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
453 formatter
454 .debug_struct("AsyncTranscodeDecodeInput")
455 .field("input", &self.input)
456 .finish()
457 }
458}
459
460fn capacity_to_io_error(error: CapacityError) -> Error {
462 Error::new(ErrorKind::InvalidData, error)
463}