/rust/registry/src/index.crates.io-6f17d22bba15001f/ciborium-io-0.2.2/src/lib.rs
Line | Count | Source (jump to first uncovered line) |
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 | 0 | fn read_exact(&mut self, data: &mut [u8]) -> Result<(), Self::Error> { |
58 | 0 | self.read_exact(data) |
59 | 0 | } |
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 | 0 | fn write_all(&mut self, data: &[u8]) -> Result<(), Self::Error> { |
68 | 0 | self.write_all(data) |
69 | 0 | } |
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 | | } |