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