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}