tiny_std/
io.rs

1#[cfg(feature = "alloc")]
2use alloc::string::String;
3#[cfg(feature = "alloc")]
4use alloc::vec::Vec;
5use core::{fmt, str};
6
7use rusl::error::Errno;
8
9use crate::error::{Error, Result};
10
11#[cfg(feature = "alloc")]
12pub(crate) mod read_buf;
13
14pub trait Read {
15    /// Read into to provided buffer
16    /// # Errors
17    /// Eventual Errors specific to the implementation
18    fn read(&mut self, buf: &mut [u8]) -> Result<usize>;
19
20    /// Reads to the end of this Reader,
21    /// # Errors
22    /// Eventual Errors specific to the implementation
23    #[cfg(feature = "alloc")]
24    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> Result<usize> {
25        default_read_to_end(self, buf)
26    }
27
28    /// Reads to the end of the provided buffer
29    /// # Errors
30    /// Eventual Errors specific to the implementation
31    #[cfg(feature = "alloc")]
32    fn read_to_string(&mut self, buf: &mut String) -> Result<usize> {
33        default_read_to_string(self, buf)
34    }
35
36    /// Reads exactly enough bytes to fill the buffer
37    /// # Errors
38    /// Eventual Errors specific to the implementation
39    fn read_exact(&mut self, buf: &mut [u8]) -> Result<()> {
40        default_read_exact(self, buf)
41    }
42
43    /// Get this reader by mut ref
44    /// # Errors
45    /// Eventual Errors specific to the implementation
46    fn by_ref(&mut self) -> &mut Self
47    where
48        Self: Sized,
49    {
50        self
51    }
52}
53
54// This uses an adaptive system to extend the vector when it fills. We want to
55// avoid paying to allocate and zero a huge chunk of memory if the reader only
56// has 4 bytes while still making large reads if the reader does have a ton
57// of data to return. Simply tacking on an extra DEFAULT_BUF_SIZE space every
58// time is 4,500 times (!) slower than a default reservation size of 32 if the
59// reader has a very small amount of data to return.
60#[cfg(feature = "alloc")]
61pub(crate) fn default_read_to_end<R: Read + ?Sized>(r: &mut R, buf: &mut Vec<u8>) -> Result<usize> {
62    let start_len = buf.len();
63    let start_cap = buf.capacity();
64
65    let mut initialized = 0; // Extra initialized bytes from previous loop iteration
66    loop {
67        if buf.len() == buf.capacity() {
68            buf.reserve(32); // buf is full, need more space
69        }
70
71        let mut read_buf = crate::io::read_buf::ReadBuf::uninit(buf.spare_capacity_mut());
72
73        // SAFETY: These bytes were initialized but not filled in the previous loop
74        unsafe {
75            read_buf.assume_init(initialized);
76        }
77
78        match default_read_buf(|b| r.read(b), &mut read_buf) {
79            Ok(()) => {}
80            Err(ref e) if e.matches_errno(Errno::EINTR) => continue,
81            Err(e) => return Err(e),
82        }
83
84        if read_buf.filled_len() == 0 {
85            return Ok(buf.len() - start_len);
86        }
87
88        // store how much was initialized but not filled
89        initialized = read_buf.initialized_len() - read_buf.filled_len();
90        let new_len = read_buf.filled_len() + buf.len();
91
92        // SAFETY: ReadBuf's invariants mean this much memory is init
93        unsafe {
94            buf.set_len(new_len);
95        }
96
97        if buf.len() == buf.capacity() && buf.capacity() == start_cap {
98            // The buffer might be an exact fit. Let's read into a probe buffer
99            // and see if it returns `Ok(0)`. If so, we've avoided an
100            // unnecessary doubling of the capacity. But if not, append the
101            // probe buffer to the primary buffer and let its capacity grow.
102            let mut probe = [0u8; 32];
103
104            loop {
105                match r.read(&mut probe) {
106                    Ok(0) => return Ok(buf.len() - start_len),
107                    Ok(n) => {
108                        buf.extend_from_slice(&probe[..n]);
109                        break;
110                    }
111                    Err(ref e) if e.matches_errno(Errno::EINTR) => continue,
112                    Err(e) => return Err(e),
113                }
114            }
115        }
116    }
117}
118
119#[cfg(feature = "alloc")]
120pub(crate) fn default_read_to_string<R: Read + ?Sized>(
121    r: &mut R,
122    buf: &mut String,
123) -> Result<usize> {
124    // Note that we do *not* call `r.read_to_end()` here. We are passing
125    // `&mut Vec<u8>` (the raw contents of `buf`) into the `read_to_end`
126    // method to fill it up. An arbitrary implementation could overwrite the
127    // entire contents of the vector, not just append to it (which is what
128    // we are expecting).
129    //
130    // To prevent extraneously checking the UTF-8-ness of the entire buffer
131    // we pass it to our hardcoded `default_read_to_end` implementation which
132    // we know is guaranteed to only read data into the end of the buffer.
133    unsafe { append_to_string(buf, |b| default_read_to_end(r, b)) }
134}
135
136// Several `read_to_string` and `read_line` methods in the standard library will
137// append data into a `String` buffer, but we need to be pretty careful when
138// doing this. The implementation will just call `.as_mut_vec()` and then
139// delegate to a byte-oriented reading method, but we must ensure that when
140// returning we never leave `buf` in a state such that it contains invalid UTF-8
141// in its bounds.
142//
143// To this end, we use an RAII guard (to protect against panics) which updates
144// the length of the string when it is dropped. This guard initially truncates
145// the string to the prior length and only after we've validated that the
146// new contents are valid UTF-8 do we allow it to set a longer length.
147//
148// The unsafety in this function is twofold:
149//
150// 1. We're looking at the raw bytes of `buf`, so we take on the burden of UTF-8
151//    checks.
152// 2. We're passing a raw buffer to the function `f`, and it is expected that
153//    the function only *appends* bytes to the buffer. We'll get undefined
154//    behavior if existing bytes are overwritten to have non-UTF-8 data.
155#[cfg(feature = "alloc")]
156pub(crate) unsafe fn append_to_string<F>(buf: &mut String, f: F) -> Result<usize>
157where
158    F: FnOnce(&mut Vec<u8>) -> Result<usize>,
159{
160    struct Guard<'a> {
161        buf: &'a mut Vec<u8>,
162        len: usize,
163    }
164
165    impl Drop for Guard<'_> {
166        fn drop(&mut self) {
167            unsafe {
168                self.buf.set_len(self.len);
169            }
170        }
171    }
172
173    let mut g = Guard {
174        len: buf.len(),
175        buf: buf.as_mut_vec(),
176    };
177    let ret = f(g.buf);
178    if str::from_utf8(&g.buf[g.len..]).is_err() {
179        ret.and_then(|_| Err(Error::no_code("Stream did not contain valid UTF-8")))
180    } else {
181        g.len = g.buf.len();
182        ret
183    }
184}
185
186pub(crate) fn default_read_exact<R: Read + ?Sized>(this: &mut R, mut buf: &mut [u8]) -> Result<()> {
187    while !buf.is_empty() {
188        match this.read(buf) {
189            Ok(0) => break,
190            Ok(n) => {
191                let tmp = buf;
192                buf = &mut tmp[n..];
193            }
194            Err(ref e) if e.matches_errno(Errno::EINTR) => {}
195            Err(e) => return Err(e),
196        }
197    }
198    if buf.is_empty() {
199        Ok(())
200    } else {
201        Err(Error::no_code("Failed to fill whole buffer"))
202    }
203}
204
205#[cfg(feature = "alloc")]
206pub(crate) fn default_read_buf<F>(read: F, buf: &mut crate::io::read_buf::ReadBuf<'_>) -> Result<()>
207where
208    F: FnOnce(&mut [u8]) -> Result<usize>,
209{
210    let n = read(buf.initialize_unfilled())?;
211    buf.add_filled(n);
212    Ok(())
213}
214
215pub trait Write {
216    /// Tries to write the contents of the provided buffer into this writer
217    /// returning how many bytes were written.
218    /// # Errors
219    /// `Writer` failing to write
220    fn write(&mut self, buf: &[u8]) -> Result<usize>;
221
222    /// Flushes this `Writer`
223    /// # Errors
224    /// Formatting the provided arguments, or the `Writer` failing to write
225    fn flush(&mut self) -> Result<()>;
226
227    /// Writes the full buffer into this `Writer`
228    /// # Errors
229    /// `Writer` failing to write
230    fn write_all(&mut self, mut buf: &[u8]) -> Result<()> {
231        while !buf.is_empty() {
232            match self.write(buf) {
233                Ok(0) => {
234                    return Err(Error::no_code("failed to write whole buffer"));
235                }
236                Ok(n) => buf = &buf[n..],
237                Err(ref e) if e.matches_errno(Errno::EINTR) => {}
238                Err(e) => return Err(e),
239            }
240        }
241        Ok(())
242    }
243
244    /// Writes format arguments into this `Writer`
245    /// # Errors
246    /// Formatting the provided arguments, or the `Writer` failing to write
247    fn write_fmt(&mut self, fmt: fmt::Arguments<'_>) -> Result<()> {
248        // Create a shim which translates a Write to a fmt::Write and saves
249        // off I/O errors. instead of discarding them
250        struct Adapter<'a, T: ?Sized + 'a> {
251            inner: &'a mut T,
252            error: Result<()>,
253        }
254
255        impl<T: Write + ?Sized> fmt::Write for Adapter<'_, T> {
256            fn write_str(&mut self, s: &str) -> fmt::Result {
257                match self.inner.write_all(s.as_bytes()) {
258                    Ok(()) => Ok(()),
259                    Err(e) => {
260                        self.error = Err(e);
261                        Err(fmt::Error)
262                    }
263                }
264            }
265        }
266
267        let mut output = Adapter {
268            inner: self,
269            error: Ok(()),
270        };
271        match fmt::write(&mut output, fmt) {
272            Ok(()) => Ok(()),
273            Err(..) => {
274                // check if the error came from the underlying `Write` or not
275                if output.error.is_err() {
276                    output.error
277                } else {
278                    Err(Error::no_code("formatter error"))
279                }
280            }
281        }
282    }
283
284    /// Get this `Writer` as a mutable reference
285    fn by_ref(&mut self) -> &mut Self
286    where
287        Self: Sized,
288    {
289        self
290    }
291}