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" )] |
23 | extern 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. |
29 | pub 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. |
41 | pub 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" )] |
53 | impl<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" )] |
63 | impl<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" ))] |
78 | impl<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" ))] |
88 | impl<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)] |
105 | pub struct EndOfFile(()); |
106 | |
107 | #[cfg (not(feature = "std" ))] |
108 | impl 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)] |
127 | pub struct OutOfSpace(()); |
128 | |
129 | #[cfg (not(feature = "std" ))] |
130 | impl 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" ))] |
152 | impl 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)] |
168 | mod 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 | |