mycelium_util/io/
util.rs

1use crate::io::{self, ErrorKind, Initializer, Read, Write};
2use core::{fmt, mem::MaybeUninit};
3
4/// Copies the entire contents of a reader into a writer.
5///
6/// This function will continuously read data from `reader` and then
7/// write it into `writer` in a streaming fashion until `reader`
8/// returns EOF.
9///
10/// On success, the total number of bytes that were copied from
11/// `reader` to `writer` is returned.
12///
13/// # Errors
14///
15/// This function will return an error immediately if any call to `read` or
16/// `write` returns an error. All instances of `ErrorKind::Interrupted` are
17/// handled by this function and the underlying operation is retried.
18pub fn copy<R, W>(reader: &mut R, writer: &mut W) -> io::Result<u64>
19where
20    R: ?Sized + Read,
21    W: ?Sized + Write,
22{
23    let mut buf = MaybeUninit::<[u8; super::DEFAULT_BUF_SIZE]>::uninit();
24    // FIXME(eliza): the stdlib has a scary comment that says we haven't decided
25    // if this is okay or not...
26    unsafe {
27        reader.initializer().initialize(&mut *buf.as_mut_ptr());
28    }
29
30    let mut written = 0;
31    loop {
32        let len = match reader.read(unsafe { &mut *buf.as_mut_ptr() }) {
33            Ok(0) => return Ok(written),
34            Ok(len) => len,
35            Err(ref e) if e.kind() == ErrorKind::Interrupted => continue,
36            Err(e) => return Err(e),
37        };
38        writer.write_all(unsafe { &(&*buf.as_ptr())[..len] })?;
39        written += len as u64;
40    }
41}
42
43/// A reader which is always at EOF.
44///
45/// This struct is generally created by calling [`empty`]. Please see
46/// the documentation of [`empty()`][`empty`] for more details.
47///
48/// [`empty`]: fn.empty.html
49pub struct Empty {
50    _priv: (),
51}
52
53/// Constructs a new handle to an empty reader.
54///
55/// All reads from the returned reader will return `Ok(0)`.
56///
57pub fn empty() -> Empty {
58    Empty { _priv: () }
59}
60
61impl Read for Empty {
62    #[inline]
63    fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> {
64        Ok(0)
65    }
66
67    #[inline]
68    unsafe fn initializer(&self) -> Initializer {
69        Initializer::nop()
70    }
71}
72
73// impl BufRead for Empty {
74//     #[inline]
75//     fn fill_buf(&mut self) -> io::Result<&[u8]> {
76//         Ok(&[])
77//     }
78//     #[inline]
79//     fn consume(&mut self, _n: usize) {}
80// }
81
82impl fmt::Debug for Empty {
83    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
84        f.pad("Empty { .. }")
85    }
86}
87
88/// A reader which yields one byte over and over and over and over and over and...
89///
90/// This struct is generally created by calling [`repeat`][repeat]. Please
91/// see the documentation of `repeat()` for more details.
92///
93/// [repeat]: fn.repeat.html
94pub struct Repeat {
95    byte: u8,
96}
97
98/// Creates an instance of a reader that infinitely repeats one byte.
99///
100/// All reads from this reader will succeed by filling the specified buffer with
101/// the given byte.
102pub fn repeat(byte: u8) -> Repeat {
103    Repeat { byte }
104}
105
106impl Read for Repeat {
107    #[inline]
108    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
109        for slot in &mut *buf {
110            *slot = self.byte;
111        }
112        Ok(buf.len())
113    }
114
115    #[inline]
116    unsafe fn initializer(&self) -> Initializer {
117        Initializer::nop()
118    }
119}
120
121impl fmt::Debug for Repeat {
122    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
123        f.pad("Repeat { .. }")
124    }
125}
126
127/// A writer which will move data into the void.
128///
129/// This struct is generally created by calling [`sink`][sink]. Please
130/// see the documentation of `sink()` for more details.
131///
132/// [sink]: fn.sink.html
133pub struct Sink {
134    _priv: (),
135}
136
137/// Creates an instance of a writer which will successfully consume all data.
138///
139/// All calls to `write` on the returned instance will return `Ok(buf.len())`
140/// and the contents of the buffer will not be inspected.
141pub fn sink() -> Sink {
142    Sink { _priv: () }
143}
144
145impl Write for Sink {
146    #[inline]
147    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
148        Ok(buf.len())
149    }
150
151    #[inline]
152    fn flush(&mut self) -> io::Result<()> {
153        Ok(())
154    }
155}
156
157impl fmt::Debug for Sink {
158    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
159        f.pad("Sink { .. }")
160    }
161}
162
163#[cfg(all(test, not(loom)))]
164mod tests {
165    use crate::io::prelude::*;
166    use crate::io::{copy, empty, repeat, sink};
167
168    #[test]
169    fn copy_copies() {
170        let mut r = repeat(0).take(4);
171        let mut w = sink();
172        assert_eq!(copy(&mut r, &mut w).unwrap(), 4);
173
174        let mut r = repeat(0).take(1 << 17);
175        assert_eq!(
176            copy(&mut r as &mut dyn Read, &mut w as &mut dyn Write).unwrap(),
177            1 << 17
178        );
179    }
180
181    #[test]
182    fn sink_sinks() {
183        let mut s = sink();
184        assert_eq!(s.write(&[]).unwrap(), 0);
185        assert_eq!(s.write(&[0]).unwrap(), 1);
186        assert_eq!(s.write(&[0; 1024]).unwrap(), 1024);
187        assert_eq!(s.by_ref().write(&[0; 1024]).unwrap(), 1024);
188    }
189
190    #[test]
191    fn empty_reads() {
192        let mut e = empty();
193        assert_eq!(e.read(&mut []).unwrap(), 0);
194        assert_eq!(e.read(&mut [0]).unwrap(), 0);
195        assert_eq!(e.read(&mut [0; 1024]).unwrap(), 0);
196        assert_eq!(e.by_ref().read(&mut [0; 1024]).unwrap(), 0);
197    }
198
199    #[test]
200    fn repeat_repeats() {
201        let mut r = repeat(4);
202        let mut b = [0; 1024];
203        assert_eq!(r.read(&mut b).unwrap(), 1024);
204        assert!(b.iter().all(|b| *b == 4));
205    }
206
207    #[test]
208    fn take_some_bytes() {
209        assert_eq!(repeat(4).take(100).bytes().count(), 100);
210        assert_eq!(repeat(4).take(100).bytes().next().unwrap().unwrap(), 4);
211        assert_eq!(
212            repeat(1).take(10).chain(repeat(2).take(10)).bytes().count(),
213            20
214        );
215    }
216}