nostd/io/
impls.rs

1// Copyright (C) Brendan Molloy <brendan@bbqsrc.net>
2// SPDX-License-Identifier: MIT OR Apache-2.0
3//
4// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
5// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
6// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
7// option. This file may not be copied, modified, or distributed
8// except according to those terms.
9
10use super::{
11    error::{Error, ErrorKind, Result},
12    traits::{BufRead, Read, Seek, SeekFrom, Write},
13};
14use core::{cmp, fmt};
15
16// =============================================================================
17// Forwarding implementations
18
19impl<R: Read + ?Sized> Read for &mut R {
20    #[inline]
21    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
22        (**self).read(buf)
23    }
24
25    #[inline]
26    fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> {
27        (**self).read_exact(buf)
28    }
29}
30
31impl<W: Write + ?Sized> Write for &mut W {
32    #[inline]
33    fn write(&mut self, buf: &[u8]) -> Result<usize> {
34        (**self).write(buf)
35    }
36
37    #[inline]
38    fn flush(&mut self) -> Result<()> {
39        (**self).flush()
40    }
41
42    #[inline]
43    fn write_all(&mut self, buf: &[u8]) -> Result<()> {
44        (**self).write_all(buf)
45    }
46
47    #[inline]
48    fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> Result<()> {
49        (**self).write_fmt(fmt)
50    }
51}
52
53impl<S: Seek + ?Sized> Seek for &mut S {
54    #[inline]
55    fn seek(&mut self, pos: SeekFrom) -> Result<u64> {
56        (**self).seek(pos)
57    }
58}
59
60impl<B: BufRead + ?Sized> BufRead for &mut B {
61    #[inline]
62    fn fill_buf(&mut self) -> Result<&[u8]> {
63        (**self).fill_buf()
64    }
65
66    #[inline]
67    fn consume(&mut self, amt: usize) {
68        (**self).consume(amt)
69    }
70}
71
72// =============================================================================
73// In-memory buffer implementations
74
75/// Read is implemented for `&[u8]` by copying from the slice.
76///
77/// Note that reading updates the slice to point to the yet unread part.
78/// The slice will be empty when EOF is reached.
79impl Read for &[u8] {
80    #[inline]
81    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
82        let amt = cmp::min(buf.len(), self.len());
83        let (a, b) = self.split_at(amt);
84
85        // First check if the amount of bytes we want to read is small:
86        // `copy_from_slice` will generally expand to a call to `memcpy`, and
87        // for a single byte the overhead is significant.
88        if amt == 1 {
89            buf[0] = a[0];
90        } else {
91            buf[..amt].copy_from_slice(a);
92        }
93
94        *self = b;
95        Ok(amt)
96    }
97
98    #[inline]
99    fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> {
100        if buf.len() > self.len() {
101            return Err(Error::new(
102                ErrorKind::UnexpectedEof,
103                "failed to fill whole buffer",
104            ));
105        }
106        let (a, b) = self.split_at(buf.len());
107
108        // First check if the amount of bytes we want to read is small:
109        // `copy_from_slice` will generally expand to a call to `memcpy`, and
110        // for a single byte the overhead is significant.
111        if buf.len() == 1 {
112            buf[0] = a[0];
113        } else {
114            buf.copy_from_slice(a);
115        }
116
117        *self = b;
118        Ok(())
119    }
120}
121
122impl BufRead for &[u8] {
123    #[inline]
124    fn fill_buf(&mut self) -> Result<&[u8]> {
125        Ok(*self)
126    }
127
128    #[inline]
129    fn consume(&mut self, amt: usize) {
130        *self = &self[amt..];
131    }
132}
133
134/// Write is implemented for `&mut [u8]` by copying into the slice, overwriting
135/// its data.
136///
137/// Note that writing updates the slice to point to the yet unwritten part.
138/// The slice will be empty when it has been completely overwritten.
139impl Write for &mut [u8] {
140    #[inline]
141    fn write(&mut self, data: &[u8]) -> Result<usize> {
142        let amt = cmp::min(data.len(), self.len());
143        let (a, b) = core::mem::take(self).split_at_mut(amt);
144        a.copy_from_slice(&data[..amt]);
145        *self = b;
146        Ok(amt)
147    }
148
149    #[inline]
150    fn write_all(&mut self, data: &[u8]) -> Result<()> {
151        if self.write(data)? == data.len() {
152            Ok(())
153        } else {
154            Err(Error::new(
155                ErrorKind::WriteZero,
156                "failed to write whole buffer",
157            ))
158        }
159    }
160
161    #[inline]
162    fn flush(&mut self) -> Result<()> {
163        Ok(())
164    }
165}
166
167/// Write is implemented for `Vec<u8>` by appending to the vector.
168/// The vector will grow as needed.
169#[cfg(feature = "alloc")]
170impl Write for crate::vec::Vec<u8> {
171    #[inline]
172    fn write(&mut self, buf: &[u8]) -> Result<usize> {
173        self.extend_from_slice(buf);
174        Ok(buf.len())
175    }
176
177    #[inline]
178    fn write_all(&mut self, buf: &[u8]) -> Result<()> {
179        self.extend_from_slice(buf);
180        Ok(())
181    }
182
183    #[inline]
184    fn flush(&mut self) -> Result<()> {
185        Ok(())
186    }
187}