Skip to main content

qubit_io/std_io/impls/
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
9//! Standard [`Write`](std::io::Write) implementations of item output traits.
10
11use std::io::Result;
12use std::io::Write;
13
14use crate::Output;
15use crate::traits::validate_write_count;
16use crate::util::UncheckedSlice;
17
18/// Bridges byte-oriented standard writers to item-oriented output.
19impl<W> Output for W
20where
21    W: Write + ?Sized,
22{
23    /// Bytes written by the standard Write implementation.
24    type Item = u8;
25
26    /// Writes bytes from a caller-validated indexed input range.
27    ///
28    /// # Parameters
29    ///
30    /// - `input`: Source byte slice.
31    /// - `index`: Start offset inside `input`.
32    /// - `count`: Maximum number of bytes to write.
33    ///
34    /// # Returns
35    ///
36    /// The number of bytes reported by the standard writer.
37    ///
38    /// # Errors
39    ///
40    /// Returns the error reported by the standard writer.
41    ///
42    /// # Panics
43    ///
44    /// Panics in debug builds if the requested source range does not fit.
45    ///
46    /// # Safety
47    ///
48    /// The caller must ensure that index through index plus count is a valid
49    /// range inside input without overflowing.
50    #[inline(always)]
51    unsafe fn write_unchecked(&mut self, input: &[u8], index: usize, count: usize) -> Result<usize> {
52        // SAFETY: The caller guarantees that the range is valid inside input.
53        let source = unsafe { UncheckedSlice::subslice(input, index, count) };
54        Write::write(self, source)
55    }
56
57    /// Writes bytes from the complete input slice.
58    ///
59    /// # Parameters
60    ///
61    /// - `input`: Source byte slice.
62    ///
63    /// # Returns
64    ///
65    /// The number of bytes written from `input`.
66    ///
67    /// # Errors
68    ///
69    /// Returns [`std::io::ErrorKind::InvalidData`] if the writer reports more
70    /// bytes than `input` contains, or the error reported by the standard
71    /// writer.
72    #[inline(always)]
73    fn write(&mut self, input: &[Self::Item]) -> Result<usize> {
74        let written = Write::write(self, input)?;
75        validate_write_count(written, input.len())?;
76        Ok(written)
77    }
78
79    /// Writes from the buffers in order using the standard writer's vectored
80    /// method. A single descriptor uses stack storage; multiple descriptors
81    /// may allocate descriptor storage, and the writer may allocate
82    /// independently. Short progress and writer errors are returned without
83    /// retrying or undoing underlying side effects.
84    ///
85    /// # Parameters
86    ///
87    /// - `buffers`: Ordered source byte slices.
88    ///
89    /// # Returns
90    ///
91    /// The number of bytes reported by the standard writer, up to the total
92    /// buffer length. Returns zero without calling the writer when all buffers
93    /// are empty.
94    ///
95    /// # Errors
96    ///
97    /// Returns [`std::io::ErrorKind::InvalidInput`] if the total buffer length
98    /// overflows, [`std::io::ErrorKind::OutOfMemory`] if multiple-descriptor
99    /// preparation fails before I/O, [`std::io::ErrorKind::InvalidData`] if
100    /// the writer reports more than the total buffer length, or the error
101    /// returned by the standard writer.
102    fn write_vectored(&mut self, buffers: &[&[u8]]) -> Result<usize> {
103        let capacity = crate::util::requested_items(buffers.iter().map(|buffer| buffer.len()))?;
104        if capacity == 0 {
105            return Ok(0);
106        }
107        let count = if let [buffer] = buffers {
108            let slices = [std::io::IoSlice::new(buffer)];
109            Write::write_vectored(self, &slices)?
110        } else {
111            let slices = crate::util::io_slices(buffers)?;
112            Write::write_vectored(self, &slices)?
113        };
114        validate_write_count(count, capacity)?;
115        Ok(count)
116    }
117
118    /// Flushes the standard writer.
119    ///
120    /// # Returns
121    ///
122    /// Returns `Ok(())` after the standard writer is flushed.
123    ///
124    /// # Errors
125    ///
126    /// Returns the error reported by the standard writer.
127    #[inline(always)]
128    fn flush(&mut self) -> Result<()> {
129        Write::flush(self)
130    }
131}