Coverage Report

Created: 2025-02-21 07:11

/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
}