1// SPDX-License-Identifier: Apache-2.0
2
3//! Simple, Low-level I/O traits
4//!
5//! This crate provides two simple traits: `Read` and `Write`. These traits
6//! mimic their counterparts in `std::io`, but are trimmed for simplicity
7//! and can be used in `no_std` and `no_alloc` environments. Since this
8//! crate contains only traits, inline functions and unit structs, it should
9//! be a zero-cost abstraction.
10//!
11//! If the `std` feature is enabled, we provide blanket implementations for
12//! all `std::io` types. If the `alloc` feature is enabled, we provide
13//! implementations for `Vec<u8>`. In all cases, you get implementations
14//! for byte slices. You can, of course, implement the traits for your own
15//! types.
16
17#![cfg_attr(not(feature = "std"), no_std)]
18#![deny(missing_docs)]
19#![deny(clippy::all)]
20#![deny(clippy::cargo)]
21
22#[cfg(feature = "alloc")]
23extern crate alloc;
24
25/// A trait indicating a type that can read bytes
26///
27/// Note that this is similar to `std::io::Read`, but simplified for use in a
28/// `no_std` context.
29pub trait Read {
30 /// The error type
31 type Error;
32
33 /// Reads exactly `data.len()` bytes or fails
34 fn read_exact(&mut self, data: &mut [u8]) -> Result<(), Self::Error>;
35}
36
37/// A trait indicating a type that can write bytes
38///
39/// Note that this is similar to `std::io::Write`, but simplified for use in a
40/// `no_std` context.
41pub trait Write {
42 /// The error type
43 type Error;
44
45 /// Writes all bytes from `data` or fails
46 fn write_all(&mut self, data: &[u8]) -> Result<(), Self::Error>;
47
48 /// Flushes all output
49 fn flush(&mut self) -> Result<(), Self::Error>;
50}
51
52#[cfg(feature = "std")]
53impl<T: std::io::Read> Read for T {
54 type Error = std::io::Error;
55
56 #[inline]
57 fn read_exact(&mut self, data: &mut [u8]) -> Result<(), Self::Error> {
58 self.read_exact(data)
59 }
60}
61
62#[cfg(feature = "std")]
63impl<T: std::io::Write> Write for T {
64 type Error = std::io::Error;
65
66 #[inline]
67 fn write_all(&mut self, data: &[u8]) -> Result<(), Self::Error> {
68 self.write_all(data)
69 }
70
71 #[inline]
72 fn flush(&mut self) -> Result<(), Self::Error> {
73 self.flush()
74 }
75}
76
77#[cfg(not(feature = "std"))]
78impl<R: Read + ?Sized> Read for &mut R {
79 type Error = R::Error;
80
81 #[inline]
82 fn read_exact(&mut self, data: &mut [u8]) -> Result<(), Self::Error> {
83 (**self).read_exact(data)
84 }
85}
86
87#[cfg(not(feature = "std"))]
88impl<W: Write + ?Sized> Write for &mut W {
89 type Error = W::Error;
90
91 #[inline]
92 fn write_all(&mut self, data: &[u8]) -> Result<(), Self::Error> {
93 (**self).write_all(data)
94 }
95
96 #[inline]
97 fn flush(&mut self) -> Result<(), Self::Error> {
98 (**self).flush()
99 }
100}
101
102/// An error indicating there are no more bytes to read
103#[cfg(not(feature = "std"))]
104#[derive(Debug)]
105pub struct EndOfFile(());
106
107#[cfg(not(feature = "std"))]
108impl Read for &[u8] {
109 type Error = EndOfFile;
110
111 #[inline]
112 fn read_exact(&mut self, data: &mut [u8]) -> Result<(), Self::Error> {
113 if data.len() > self.len() {
114 return Err(EndOfFile(()));
115 }
116
117 let (prefix, suffix) = self.split_at(data.len());
118 data.copy_from_slice(prefix);
119 *self = suffix;
120 Ok(())
121 }
122}
123
124/// An error indicating that the output cannot accept more bytes
125#[cfg(not(feature = "std"))]
126#[derive(Debug)]
127pub struct OutOfSpace(());
128
129#[cfg(not(feature = "std"))]
130impl Write for &mut [u8] {
131 type Error = OutOfSpace;
132
133 #[inline]
134 fn write_all(&mut self, data: &[u8]) -> Result<(), Self::Error> {
135 if data.len() > self.len() {
136 return Err(OutOfSpace(()));
137 }
138
139 let (prefix, suffix) = core::mem::take(self).split_at_mut(data.len());
140 prefix.copy_from_slice(data);
141 *self = suffix;
142 Ok(())
143 }
144
145 #[inline]
146 fn flush(&mut self) -> Result<(), Self::Error> {
147 Ok(())
148 }
149}
150
151#[cfg(all(not(feature = "std"), feature = "alloc"))]
152impl Write for alloc::vec::Vec<u8> {
153 type Error = core::convert::Infallible;
154
155 #[inline]
156 fn write_all(&mut self, data: &[u8]) -> Result<(), Self::Error> {
157 self.extend_from_slice(data);
158 Ok(())
159 }
160
161 #[inline]
162 fn flush(&mut self) -> Result<(), Self::Error> {
163 Ok(())
164 }
165}
166
167#[cfg(test)]
168mod test {
169 use super::*;
170
171 #[test]
172 fn read_eof() {
173 let mut reader = &[1u8; 0][..];
174 let mut buffer = [0u8; 1];
175
176 reader.read_exact(&mut buffer[..]).unwrap_err();
177 }
178
179 #[test]
180 fn read_one() {
181 let mut reader = &[1u8; 1][..];
182 let mut buffer = [0u8; 1];
183
184 reader.read_exact(&mut buffer[..]).unwrap();
185 assert_eq!(buffer[0], 1);
186
187 reader.read_exact(&mut buffer[..]).unwrap_err();
188 }
189
190 #[test]
191 fn read_two() {
192 let mut reader = &[1u8; 2][..];
193 let mut buffer = [0u8; 1];
194
195 reader.read_exact(&mut buffer[..]).unwrap();
196 assert_eq!(buffer[0], 1);
197
198 reader.read_exact(&mut buffer[..]).unwrap();
199 assert_eq!(buffer[0], 1);
200
201 reader.read_exact(&mut buffer[..]).unwrap_err();
202 }
203
204 #[test]
205 #[cfg(feature = "std")]
206 fn read_std() {
207 let mut reader = std::io::repeat(1);
208 let mut buffer = [0u8; 2];
209
210 reader.read_exact(&mut buffer[..]).unwrap();
211 assert_eq!(buffer[0], 1);
212 assert_eq!(buffer[1], 1);
213 }
214
215 #[test]
216 fn write_oos() {
217 let mut writer = &mut [0u8; 0][..];
218
219 writer.write_all(&[1u8; 1][..]).unwrap_err();
220 }
221
222 #[test]
223 fn write_one() {
224 let mut buffer = [0u8; 1];
225 let mut writer = &mut buffer[..];
226
227 writer.write_all(&[1u8; 1][..]).unwrap();
228 writer.write_all(&[1u8; 1][..]).unwrap_err();
229 assert_eq!(buffer[0], 1);
230 }
231
232 #[test]
233 fn write_two() {
234 let mut buffer = [0u8; 2];
235 let mut writer = &mut buffer[..];
236
237 writer.write_all(&[1u8; 1][..]).unwrap();
238 writer.write_all(&[1u8; 1][..]).unwrap();
239 writer.write_all(&[1u8; 1][..]).unwrap_err();
240 assert_eq!(buffer[0], 1);
241 assert_eq!(buffer[1], 1);
242 }
243
244 #[test]
245 #[cfg(feature = "alloc")]
246 fn write_vec() {
247 let mut buffer = alloc::vec::Vec::new();
248
249 buffer.write_all(&[1u8; 1][..]).unwrap();
250 buffer.write_all(&[1u8; 1][..]).unwrap();
251
252 assert_eq!(buffer.len(), 2);
253 assert_eq!(buffer[0], 1);
254 assert_eq!(buffer[1], 1);
255 }
256
257 #[test]
258 #[cfg(feature = "std")]
259 fn write_std() {
260 let mut writer = std::io::sink();
261
262 writer.write_all(&[1u8; 1][..]).unwrap();
263 writer.write_all(&[1u8; 1][..]).unwrap();
264 }
265}
266