qubit_codec/transcode/io/transcode_encode_output.rs
1// =============================================================================
2// Copyright (c) 2026 Haixing Hu.
3//
4// SPDX-License-Identifier: Apache-2.0
5//
6// Licensed under the Apache License, Version 2.0.
7// =============================================================================
8//! Buffered output driver that encodes values into units.
9
10use core::fmt;
11use std::collections::TryReserveError;
12use std::io::Error;
13use std::io::ErrorKind;
14use std::io::Result;
15use std::io::Seek;
16use std::io::SeekFrom;
17use std::io::Write;
18use std::result::Result as CoreResult;
19
20use qubit_io::BufferedOutput;
21use qubit_io::BufferedOutputRecovery;
22use qubit_io::ByteOutput;
23use qubit_io::Output;
24use qubit_io::SeekableByteOutput;
25use qubit_utils::SliceRange;
26use qubit_utils::allocation_error;
27
28use super::internal::capacity_error_to_invalid_data;
29use super::internal::map_encode_value_result;
30use super::transcode_progress_validation::validate_encode_progress;
31use crate::CapacityError;
32use crate::Codec;
33use crate::TranscodeEncodeErrorOf;
34use crate::TranscodeEncoder;
35use crate::TranscodeProgress;
36use crate::TranscodeStatus;
37use crate::Transcoder;
38use crate::value::codec_value_lifecycle::encode_complete_value_into_reserved;
39use crate::value::codec_value_lifecycle::max_complete_encode_units;
40
41/// Encodes an [`Output`] value stream into an [`Output`] unit stream.
42///
43/// This type owns only the unit-level [`qubit_io::BufferedOutput`]. Callers
44/// pass a [`crate::Codec`] and error mapper to each encode operation, which
45/// lets one buffered output drive different encoders without nesting buffers or
46/// storing codec-specific state in the buffer owner.
47///
48/// [`Self::flush`] only drains already buffered units. State-aware streaming
49/// encoders can use [`Self::reset`], [`Self::transcode`], and [`Self::finish`]
50/// explicitly.
51///
52/// # Type Parameters
53///
54/// * `O` - Wrapped unit output.
55///
56/// # Examples
57///
58/// ```
59/// use std::io::Cursor;
60///
61/// use qubit_codec::TranscodeEncodeOutput;
62///
63/// let output = TranscodeEncodeOutput::with_capacity(Cursor::new(Vec::<u8>::new()), 8);
64/// assert!(output.spare_capacity() >= 8);
65/// ```
66pub struct TranscodeEncodeOutput<O>
67where
68 O: Output,
69 O::Item: Copy + Default,
70{
71 /// Owns the wrapped unit sink and pending encoded units awaiting delivery.
72 output: BufferedOutput<O>,
73}
74
75impl<O> TranscodeEncodeOutput<O>
76where
77 O: Output,
78 O::Item: Copy + Default,
79{
80 /// Creates an encoder output with the default unit buffer capacity.
81 ///
82 /// # Parameters
83 ///
84 /// * `inner` - Unit output written by this adapter.
85 ///
86 /// # Returns
87 ///
88 /// A new buffered encoder output.
89 #[must_use]
90 pub fn new(inner: O) -> Self {
91 Self {
92 output: BufferedOutput::new(inner),
93 }
94 }
95
96 /// Creates an encoder output with a unit buffer of at least `capacity`.
97 ///
98 /// # Parameters
99 ///
100 /// * `inner` - Unit output written by this adapter.
101 /// * `capacity` - Requested internal unit buffer capacity.
102 ///
103 /// # Returns
104 ///
105 /// A new buffered encoder output.
106 #[must_use]
107 pub fn with_capacity(inner: O, capacity: usize) -> Self {
108 Self {
109 output: BufferedOutput::with_capacity(inner, capacity),
110 }
111 }
112
113 /// Creates an encoder output with a unit buffer of at least `capacity`.
114 ///
115 /// # Parameters
116 ///
117 /// * `inner` - Unit output written by this adapter.
118 /// * `capacity` - Requested internal unit buffer capacity.
119 ///
120 /// # Errors
121 ///
122 /// Returns an allocation error when the requested buffer cannot be
123 /// allocated.
124 ///
125 /// # Returns
126 ///
127 /// A buffered adapter owning `inner` on success.
128 pub fn try_with_capacity(inner: O, capacity: usize) -> CoreResult<Self, TryReserveError> {
129 Ok(Self {
130 output: BufferedOutput::try_with_capacity(inner, capacity)?,
131 })
132 }
133
134 /// Returns a shared reference to the wrapped unit output.
135 ///
136 /// Pending units remain in this adapter's internal buffer and are not
137 /// visible through the returned output until [`Self::flush`] succeeds.
138 ///
139 /// # Returns
140 ///
141 /// A shared reference to the wrapped unit output.
142 #[must_use]
143 #[inline]
144 pub const fn inner(&self) -> &O {
145 self.output.inner()
146 }
147
148 /// Returns the available capacity of the spare output buffer.
149 ///
150 /// # Returns
151 ///
152 /// The number of output units that can still be appended without flushing.
153 #[must_use]
154 #[inline]
155 pub fn spare_capacity(&self) -> usize {
156 self.output.spare_capacity()
157 }
158
159 /// Returns raw spare-buffer parts for the internal output buffer.
160 ///
161 /// # Returns
162 ///
163 /// The full backing storage, the spare start index, and the spare unit
164 /// count.
165 #[must_use]
166 #[inline]
167 pub fn spare_raw_parts_mut(&mut self) -> (&mut [O::Item], usize, usize) {
168 self.output.spare_raw_parts_mut()
169 }
170
171 /// Marks `count` units from [`Self::spare_raw_parts_mut`] as written.
172 ///
173 /// # Parameters
174 ///
175 /// * `count` - Initialized units to commit from the spare window.
176 ///
177 /// # Safety
178 ///
179 /// The caller must guarantee that `count <= Self::spare_capacity()` and
180 /// that the corresponding units in the returned spare slice have been
181 /// initialized.
182 #[inline]
183 pub unsafe fn advance(&mut self, count: usize) {
184 // SAFETY: The caller guarantees `count` and initialization invariants.
185 unsafe { self.output.advance(count) }
186 }
187
188 /// Ensures that at least `count` spare units are available.
189 ///
190 /// # Parameters
191 ///
192 /// * `count` - Number of spare units required.
193 ///
194 /// # Errors
195 ///
196 /// Returns allocation errors mapped to [`ErrorKind::OutOfMemory`], or I/O
197 /// errors from the wrapped output while delivering pending units.
198 pub fn ensure_spare_capacity(&mut self, count: usize) -> Result<()> {
199 self.output.try_reserve_capacity(count).map_err(allocation_error)?;
200 self.output.ensure_spare_capacity(count)
201 }
202
203 /// Consumes this adapter without flushing the wrapped output.
204 ///
205 /// This method does not call [`Self::flush`] and performs no I/O. `Pending`
206 /// units were not reported as written and may be retried. `Indeterminate`
207 /// means an inner write panicked and may have produced an external prefix;
208 /// do not replay it automatically.
209 ///
210 /// # Returns
211 ///
212 /// The wrapped output and pending or indeterminate units.
213 #[must_use = "the returned output and recovery status must be handled"]
214 #[inline]
215 pub fn into_parts(self) -> (O, BufferedOutputRecovery<O::Item>) {
216 self.output.into_parts()
217 }
218
219 /// Flushes buffered units without finishing any encoder stream.
220 ///
221 /// # Errors
222 ///
223 /// Returns errors from the wrapped output while flushing pending units.
224 pub fn flush(&mut self) -> Result<()> {
225 self.output.flush()
226 }
227
228 /// Encodes one codec value into this buffered unit output.
229 ///
230 /// The method grows the persistent internal buffer when necessary, then
231 /// writes the complete encoded value into its spare window.
232 ///
233 /// # Type Parameters
234 ///
235 /// * `C` - Codec producing the wrapped output unit type.
236 /// * `M` - Mapper from codec errors into I/O errors.
237 ///
238 /// # Parameters
239 ///
240 /// * `codec` - Codec used for this single-value encode.
241 /// * `value` - Value to encode.
242 /// * `map_error` - Mapper for codec-domain encode errors.
243 ///
244 /// # Errors
245 ///
246 /// Returns I/O errors from the wrapped output, `InvalidInput` when the
247 /// codec output bound overflows or the value is outside the codec domain,
248 /// or the error returned by `map_error` for codec encode, reset, and finish
249 /// failures.
250 ///
251 /// # Panics
252 ///
253 /// Panics when the codec violates its declared reset, value-width, or
254 /// finish bounds, or when `encode` writes a length different from
255 /// `encode_len` in the same reset state.
256 pub fn write_encoded_with<C, M>(&mut self, codec: &mut C, value: &C::Value, mut map_error: M) -> Result<()>
257 where
258 C: Codec<Unit = O::Item>,
259 M: FnMut(C::EncodeError) -> Error,
260 {
261 let max_units = map_encode_value_result(
262 max_complete_encode_units::<C>().map_err(TranscodeEncodeErrorOf::<C>::from),
263 &mut map_error,
264 )?;
265 self.ensure_spare_capacity(max_units)?;
266 let (units, output_index, available) = self.output.spare_raw_parts_mut();
267 debug_assert!(
268 available >= max_units,
269 "reserved spare buffer is smaller than codec upper bound",
270 );
271 let written = map_encode_value_result(
272 encode_complete_value_into_reserved(codec, value, units, output_index, max_units),
273 &mut map_error,
274 )?;
275 // SAFETY: The spare buffer has the conservative complete lifecycle
276 // capacity, and the helper reports how many initialized units it
277 // actually wrote.
278 unsafe {
279 self.output.advance(written);
280 }
281 Ok(())
282 }
283
284 /// Runs encoder reset and buffers any stream-prefix units.
285 ///
286 /// This method reserves enough persistent buffer capacity for all reset
287 /// output before calling `encoder`. Preparing that space may deliver
288 /// previously buffered units to the wrapped output and can return an I/O
289 /// error before `encoder.reset` runs. This delivery does not call the
290 /// wrapped output's `flush` method.
291 ///
292 /// # Type Parameters
293 ///
294 /// * `E` - Transcoder producing the wrapped output unit type.
295 /// * `M` - Mapper from transcoder errors into I/O errors.
296 /// * `Value` - Source value type accepted by the transcoder.
297 ///
298 /// # Parameters
299 ///
300 /// * `encoder` - Transcoder whose stream prefix is being collected.
301 /// * `map_error` - Mapper for reset failures.
302 ///
303 /// # Errors
304 ///
305 /// Returns capacity errors, allocation errors, or reset errors mapped by
306 /// `map_error`.
307 ///
308 /// # Panics
309 ///
310 /// Panics when `encoder` writes more than its declared reset bound.
311 pub fn reset<E, M, Value>(&mut self, encoder: &mut E, map_error: &mut M) -> Result<()>
312 where
313 E: Transcoder<Input = Value, Output = O::Item>,
314 M: FnMut(E::Error) -> Error,
315 {
316 let required = encoder.max_reset_output_len().map_err(capacity_error_to_invalid_data)?;
317 self.ensure_spare_capacity(required)?;
318 let (units, output_index, available) = self.output.spare_raw_parts_mut();
319 debug_assert!(
320 available >= required,
321 "insufficient reset capacity reserved in spare output buffer",
322 );
323 let written = encoder.reset(units, output_index).map_err(&mut *map_error)?;
324 assert!(written <= required, "reset wrote beyond its bound");
325 // SAFETY: The encoder reported initialized units within the spare
326 // range reserved above.
327 unsafe {
328 self.output.advance(written);
329 }
330 Ok(())
331 }
332
333 /// Encodes at most one step of the selected input range.
334 ///
335 /// Unlike [`Self::transcode`], this method does not reserve output space
336 /// for the entire range and calls the encoder exactly once. The returned
337 /// progress is relative to this call's input and output windows. Advance
338 /// the input index by [`TranscodeProgress::read`]; if the status is
339 /// `NeedOutput`, provide the requested spare capacity before retrying.
340 /// Written units have already been committed to this adapter's pending
341 /// buffer and must not be advanced again. A zero count validates the range
342 /// and returns complete progress without delivering pending units or
343 /// calling the encoder.
344 ///
345 /// # Parameters
346 ///
347 /// * `encoder` - Encoder that processes one progress step.
348 /// * `map_error` - Maps encoder errors to I/O errors.
349 /// * `input` - Source values.
350 /// * `input_index` - Start index inside `input`.
351 /// * `count` - Number of values available from `input_index`.
352 ///
353 /// # Returns
354 ///
355 /// Progress for the single encoder call, including consumed input,
356 /// committed output, and whether more output capacity is needed.
357 ///
358 /// # Errors
359 ///
360 /// Returns invalid input ranges, capacity, encoder, or output errors. An
361 /// invalid encoder progress report is returned as `ErrorKind::InvalidData`.
362 /// An error does not provide general transactional rollback or complete
363 /// progress. The encoder may already have advanced, but units written by
364 /// its failing call are not committed to this adapter's pending output.
365 /// Do not replay the original input range without an encoder-specific
366 /// recovery protocol. Earlier pending units retain the wrapped output's
367 /// recovery contract; reset starts a new logical stream and does not undo
368 /// output already delivered.
369 ///
370 /// # Examples
371 ///
372 /// ```
373 /// use std::io::Cursor;
374 ///
375 /// # use core::convert::Infallible;
376 /// # use core::num::NonZeroUsize;
377 /// # use qubit_codec::Codec;
378 /// # use qubit_codec::CodecTranscodeEncoder;
379 /// # use qubit_codec::DecodeFailure;
380 /// use qubit_codec::TranscodeEncodeOutput;
381 /// use qubit_codec::TranscodeEncoder;
382 /// use qubit_codec::TranscodeStatus;
383 ///
384 /// # struct ByteCodec;
385 /// # impl Codec for ByteCodec {
386 /// # type Value = u8;
387 /// # type Unit = u8;
388 /// # type DecodeError = Infallible;
389 /// # type EncodeError = Infallible;
390 /// # const MIN_UNITS_PER_VALUE: usize = 1;
391 /// # const MAX_ENCODE_UNITS_PER_VALUE: usize = 1;
392 /// # const MAX_DECODE_UNITS_PER_VALUE: usize = 1;
393 /// # unsafe fn decode(
394 /// # &mut self,
395 /// # input: &[u8],
396 /// # index: usize,
397 /// # ) -> Result<(u8, NonZeroUsize), DecodeFailure<Infallible>> {
398 /// # Ok((input[index], NonZeroUsize::MIN))
399 /// # }
400 /// # unsafe fn encode(
401 /// # &mut self,
402 /// # value: &u8,
403 /// # output: &mut [u8],
404 /// # index: usize,
405 /// # ) -> Result<usize, Infallible> {
406 /// # output[index] = *value;
407 /// # Ok(1)
408 /// # }
409 /// # }
410 /// fn encode<E>(encoder: &mut E, values: &[E::Input]) -> std::io::Result<Vec<u8>>
411 /// where
412 /// E: TranscodeEncoder<Output = u8>,
413 /// {
414 /// let mut output = TranscodeEncodeOutput::with_capacity(Cursor::new(Vec::new()), 8);
415 /// let mut map_error = |_| std::io::Error::other("encode error");
416 /// output.reset(encoder, &mut map_error)?;
417 /// let mut offset = 0;
418 /// while offset < values.len() {
419 /// let progress = output.transcode_step(
420 /// encoder,
421 /// &mut map_error,
422 /// values,
423 /// offset,
424 /// values.len() - offset,
425 /// )?;
426 /// offset += progress.read();
427 /// if let TranscodeStatus::NeedOutput { required, .. } = progress.status() {
428 /// output.ensure_spare_capacity(required.get())?;
429 /// }
430 /// }
431 /// output.finish(encoder, &mut map_error)?;
432 /// let (cursor, _) = output.into_parts();
433 /// Ok(cursor.into_inner())
434 /// }
435 ///
436 /// let mut encoder = CodecTranscodeEncoder::new(ByteCodec);
437 /// assert_eq!(encode(&mut encoder, &[1, 2, 3]).unwrap(), vec![1, 2, 3]);
438 /// let mut empty_encoder = CodecTranscodeEncoder::new(ByteCodec);
439 /// assert_eq!(encode(&mut empty_encoder, &[]).unwrap(), Vec::<u8>::new());
440 /// ```
441 pub fn transcode_step<E, M, Value>(
442 &mut self,
443 encoder: &mut E,
444 map_error: &mut M,
445 input: &[Value],
446 input_index: usize,
447 count: usize,
448 ) -> Result<TranscodeProgress>
449 where
450 E: TranscodeEncoder<Input = Value, Output = O::Item>,
451 M: FnMut(E::Error) -> Error,
452 {
453 let input_end = SliceRange::checked_range_end(
454 input.len(),
455 input_index,
456 count,
457 "encode input range exceeds source buffer",
458 )?;
459 if count == 0 {
460 return Ok(TranscodeProgress::complete(0, 0));
461 }
462 let required = encoder
463 .max_transcode_output_len(1)
464 .map_err(capacity_error_to_invalid_data)?
465 .max(1);
466 self.ensure_spare_capacity(required)?;
467 let (units, output_index, available_output) = self.output.spare_raw_parts_mut();
468 let progress = encoder
469 .transcode(&input[..input_end], input_index, units, output_index)
470 .map_err(&mut *map_error)?;
471 let progress = validate_encode_progress(progress, input_index, count, output_index, available_output)?;
472 // SAFETY: Validated progress fits the spare output window.
473 unsafe {
474 self.output.advance(progress.written());
475 }
476 Ok(progress)
477 }
478
479 /// Encodes values from an indexed input range using a streaming
480 /// [`Transcoder`].
481 ///
482 /// This streaming path reserves the encoder's conservative output bound
483 /// for the whole batch before calling it. Preparing that space may deliver
484 /// previously buffered units to the wrapped output and can return an I/O
485 /// error before consuming source values. Split large batches into smaller
486 /// calls when you need to limit the memory required for one operation.
487 ///
488 /// # Type Parameters
489 ///
490 /// * `E` - Encoder producing the wrapped output unit type.
491 /// * `M` - Mapper from encoder errors into I/O errors.
492 /// * `Value` - Source value type accepted by the encoder.
493 ///
494 /// # Parameters
495 ///
496 /// * `encoder` - Streaming encoder used for this operation.
497 /// * `map_error` - Function mapping transcode errors into I/O errors.
498 /// * `input` - Source values.
499 /// * `input_index` - Start index inside `input`.
500 /// * `count` - Maximum number of values to encode.
501 ///
502 /// # Returns
503 ///
504 /// The number of source values consumed.
505 ///
506 /// # Errors
507 ///
508 /// Returns invalid input ranges, capacity, transcode, or output errors. An
509 /// output-bound contract violation is reported as `ErrorKind::InvalidData`.
510 /// An error does not provide general transactional rollback or complete
511 /// progress. The encoder may already have advanced, while units written by
512 /// its failing call are not committed to this adapter's pending output.
513 /// Do not replay the original input range unless the concrete encoder
514 /// provides an explicit recovery protocol. Previously committed pending
515 /// output remains subject to the wrapped output's recovery contract, and
516 /// reset starts a new logical stream without undoing output already
517 /// delivered.
518 ///
519 /// # Examples
520 ///
521 /// A value that only implements [`Transcoder`] is not an encoder and cannot
522 /// be passed to this method.
523 ///
524 /// ```compile_fail
525 /// use std::io::Error;
526 /// use std::io::sink;
527 ///
528 /// use qubit_codec::CapacityError;
529 /// use qubit_codec::TranscodeEncodeError;
530 /// use qubit_codec::TranscodeEncodeOutput;
531 /// use qubit_codec::TranscodeProgress;
532 /// use qubit_codec::Transcoder;
533 ///
534 /// struct GenericTranscoder;
535 ///
536 /// impl Transcoder for GenericTranscoder {
537 /// type Input = u8;
538 /// type Output = u8;
539 /// type Error = TranscodeEncodeError<(), u8>;
540 ///
541 /// fn max_transcode_output_len(
542 /// &self,
543 /// input_len: usize,
544 /// ) -> Result<usize, CapacityError> {
545 /// Ok(input_len)
546 /// }
547 ///
548 /// fn reset(
549 /// &mut self,
550 /// _output: &mut [u8],
551 /// _output_index: usize,
552 /// ) -> Result<usize, Self::Error> {
553 /// Ok(0)
554 /// }
555 ///
556 /// fn transcode(
557 /// &mut self,
558 /// input: &[u8],
559 /// input_index: usize,
560 /// _output: &mut [u8],
561 /// _output_index: usize,
562 /// ) -> Result<TranscodeProgress, Self::Error> {
563 /// Ok(TranscodeProgress::complete(input.len() - input_index, 0))
564 /// }
565 ///
566 /// fn finish(
567 /// &mut self,
568 /// _output: &mut [u8],
569 /// _output_index: usize,
570 /// ) -> Result<usize, Self::Error> {
571 /// Ok(0)
572 /// }
573 /// }
574 ///
575 /// let mut output = TranscodeEncodeOutput::with_capacity(sink(), 1);
576 /// let mut transcoder = GenericTranscoder;
577 /// let mut map_error = |_| Error::other("transcode error");
578 /// let _ = output.transcode(
579 /// &mut transcoder,
580 /// &mut map_error,
581 /// &[0_u8],
582 /// 0,
583 /// 1,
584 /// );
585 /// ```
586 pub fn transcode<E, M, Value>(
587 &mut self,
588 encoder: &mut E,
589 map_error: &mut M,
590 input: &[Value],
591 input_index: usize,
592 count: usize,
593 ) -> Result<usize>
594 where
595 E: TranscodeEncoder<Input = Value, Output = O::Item>,
596 M: FnMut(E::Error) -> Error,
597 {
598 let input_end = SliceRange::checked_range_end(
599 input.len(),
600 input_index,
601 count,
602 "encode input range exceeds source buffer",
603 )?;
604 if count == 0 {
605 return Ok(0);
606 }
607 let required = encoder
608 .max_transcode_output_len(count)
609 .map_err(capacity_error_to_invalid_data)?
610 .max(1);
611 self.ensure_spare_capacity(required)?;
612 let input = &input[..input_end];
613 let mut read_total = 0;
614 while read_total < count {
615 let (units, output_index, available_output) = self.output.spare_raw_parts_mut();
616 let remaining_input = count - read_total;
617 let progress = encoder
618 .transcode(input, input_index + read_total, units, output_index)
619 .map_err(&mut *map_error)?;
620 let progress = validate_encode_progress(
621 progress,
622 input_index + read_total,
623 remaining_input,
624 output_index,
625 available_output,
626 )?;
627 let read = progress.read();
628 let written = progress.written();
629 // SAFETY: The progress bounds check above proved that the encoder
630 // initialized no more than the available spare output window.
631 unsafe {
632 self.output.advance(written);
633 }
634 read_total += read;
635 if progress.is_complete() {
636 return Ok(read_total);
637 }
638 if let TranscodeStatus::NeedOutput { required, .. } = progress.status()
639 && (read_total == count || available_output - written < required.get() || (read == 0 && written == 0))
640 {
641 return Err(Error::new(
642 ErrorKind::InvalidData,
643 "encoder output bound was insufficient",
644 ));
645 }
646 }
647 Ok(read_total)
648 }
649
650 /// Finishes the encoder and flushes the wrapped unit output.
651 ///
652 /// This method writes final units directly into the internal spare buffer,
653 /// growing it when [`Transcoder::max_finish_output_len`] exceeds the
654 /// current capacity.
655 ///
656 /// # Type Parameters
657 ///
658 /// * `E` - Transcoder producing the wrapped output unit type.
659 /// * `M` - Mapper from transcoder errors into I/O errors.
660 /// * `Value` - Source value type accepted by the transcoder.
661 ///
662 /// # Parameters
663 ///
664 /// * `encoder` - Encoder whose final units are being collected.
665 /// * `map_error` - Function mapping transcode errors into I/O errors.
666 ///
667 /// # Errors
668 ///
669 /// Returns capacity, transcode finalization, or wrapped output flush
670 /// errors.
671 ///
672 /// # Panics
673 ///
674 /// Panics when the encoder exceeds its declared finish-output bound.
675 pub fn finish<E, M, Value>(&mut self, encoder: &mut E, map_error: &mut M) -> Result<()>
676 where
677 E: Transcoder<Input = Value, Output = O::Item>,
678 M: FnMut(E::Error) -> Error,
679 {
680 self.finish_to_buffer(encoder, map_error)?;
681 self.output.flush()
682 }
683
684 /// Finishes the encoder while retaining final units in the output buffer.
685 ///
686 /// This method separates encoder finalization from output delivery. It is
687 /// useful when a caller must record successful finalization before a later
688 /// flush can fail. Call [`Self::flush`] to deliver the retained units.
689 ///
690 /// # Type Parameters
691 ///
692 /// * `E` - Transcoder producing the wrapped output unit type.
693 /// * `M` - Mapper from transcoder errors into I/O errors.
694 /// * `Value` - Source value type accepted by the transcoder.
695 ///
696 /// # Parameters
697 ///
698 /// * `encoder` - Encoder whose final units are being collected.
699 /// * `map_error` - Function mapping transcode errors into I/O errors.
700 ///
701 /// # Errors
702 ///
703 /// Returns capacity planning, allocation, or transcoder finalization
704 /// errors. It does not perform output I/O; use [`Self::finish`] to deliver
705 /// the buffered final units and flush the wrapped output.
706 ///
707 /// # Panics
708 ///
709 /// Panics when `encoder` writes more units than its declared finish bound.
710 pub fn finish_to_buffer<E, M, Value>(&mut self, encoder: &mut E, map_error: &mut M) -> Result<()>
711 where
712 E: Transcoder<Input = Value, Output = O::Item>,
713 M: FnMut(E::Error) -> Error,
714 {
715 let required = match encoder.max_finish_output_len() {
716 Ok(required) => required,
717 Err(error) => return Err(capacity_error_to_invalid_data(error)),
718 };
719 let pending = self.output.capacity() - self.output.spare_capacity();
720 let capacity = pending
721 .checked_add(required)
722 .ok_or_else(|| capacity_error_to_invalid_data(CapacityError::OutputLengthOverflow))?;
723 self.output.try_reserve_capacity(capacity).map_err(allocation_error)?;
724 let (units, output_index, available) = self.output.spare_raw_parts_mut();
725 debug_assert!(
726 available >= required,
727 "insufficient finish capacity reserved in spare output buffer",
728 );
729 let written = encoder.finish(units, output_index).map_err(&mut *map_error)?;
730 assert!(written <= required, "finish wrote beyond its bound");
731 // SAFETY: The encoder reported initialized units within the spare
732 // range that was reserved above.
733 unsafe {
734 self.output.advance(written);
735 }
736 Ok(())
737 }
738}
739
740impl<O> TranscodeEncodeOutput<O>
741where
742 O: SeekableByteOutput,
743{
744 /// Flushes pending bytes, then seeks the wrapped byte output.
745 ///
746 /// # Parameters
747 ///
748 /// * `position` - Target seek position.
749 ///
750 /// # Returns
751 ///
752 /// The new stream position reported by the wrapped output.
753 ///
754 /// # Errors
755 ///
756 /// Returns flush or seek errors from the wrapped output.
757 pub fn seek(&mut self, position: SeekFrom) -> Result<u64> {
758 self.output.seek_to(position)
759 }
760}
761
762impl<O> Write for TranscodeEncodeOutput<O>
763where
764 O: ByteOutput,
765{
766 /// Writes raw bytes through the internal buffer without encoding them.
767 ///
768 /// # Parameters
769 ///
770 /// * `input` - Bytes to append to the buffered unit output.
771 ///
772 /// # Returns
773 ///
774 /// The number of bytes accepted, which may be shorter than `input`.
775 ///
776 /// # Errors
777 ///
778 /// Propagates wrapped-output errors when buffer delivery is needed.
779 #[inline]
780 fn write(&mut self, input: &[u8]) -> Result<usize> {
781 Output::write(&mut self.output, input)
782 }
783
784 /// Writes all raw bytes through the internal buffer without encoding them.
785 ///
786 /// # Parameters
787 ///
788 /// * `input` - Bytes that must all be accepted before success.
789 ///
790 /// # Errors
791 ///
792 /// Propagates output errors and returns `WriteZero` if output stops
793 /// progressing.
794 ///
795 /// # Panics
796 ///
797 /// Panics when the wrapped output reports more bytes than supplied.
798 fn write_all(&mut self, input: &[u8]) -> Result<()> {
799 let mut written = 0;
800 while written < input.len() {
801 let count = match Output::write(&mut self.output, &input[written..]) {
802 Ok(count) => count,
803 Err(error) if error.kind() == ErrorKind::Interrupted => continue,
804 Err(error) => return Err(error),
805 };
806 if count == 0 {
807 return Err(Error::from(ErrorKind::WriteZero));
808 }
809 assert!(
810 count <= input.len() - written,
811 "Output::write returned a count beyond the input length",
812 );
813 written += count;
814 }
815 Ok(())
816 }
817
818 /// Flushes buffered bytes to the wrapped output without finishing an
819 /// encoder.
820 ///
821 /// # Errors
822 ///
823 /// Propagates wrapped-output flush errors.
824 #[inline]
825 fn flush(&mut self) -> Result<()> {
826 TranscodeEncodeOutput::flush(self)
827 }
828}
829
830impl<O> Seek for TranscodeEncodeOutput<O>
831where
832 O: SeekableByteOutput,
833{
834 /// Flushes pending bytes, then seeks the wrapped byte output.
835 ///
836 /// # Parameters
837 ///
838 /// * `position` - Target position relative to the selected seek origin.
839 ///
840 /// # Returns
841 ///
842 /// The new absolute byte position.
843 ///
844 /// # Errors
845 ///
846 /// Propagates flush or seek errors from the wrapped output.
847 #[inline]
848 fn seek(&mut self, position: SeekFrom) -> Result<u64> {
849 self.seek(position)
850 }
851}
852
853impl<O> fmt::Debug for TranscodeEncodeOutput<O>
854where
855 O: Output,
856 O::Item: Copy + Default,
857 BufferedOutput<O>: fmt::Debug,
858{
859 /// Formats the owned buffer and underlying output for diagnostics.
860 ///
861 /// # Parameters
862 ///
863 /// * `formatter` - Destination and formatting options.
864 ///
865 /// # Errors
866 ///
867 /// Returns a formatting error if the destination rejects output.
868 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
869 formatter
870 .debug_struct("TranscodeEncodeOutput")
871 .field("output", &self.output)
872 .finish()
873 }
874}