Skip to main content

bytesbuf/
view_read.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4use std::io::{self, BufRead, Read};
5
6use crate::BytesView;
7
8impl Read for BytesView {
9    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
10        if self.is_empty() {
11            return Ok(0);
12        }
13
14        let to_read = buf.len().min(self.len());
15        self.copy_to_slice(&mut buf[..to_read]);
16        Ok(to_read)
17    }
18}
19
20/// Because [`BytesView`] is already buffered, it implements [`BufRead`] directly
21/// without needing an intermediate buffer. Prefer this over wrapping in [`std::io::BufReader`].
22impl BufRead for BytesView {
23    fn fill_buf(&mut self) -> io::Result<&[u8]> {
24        Ok(self.first_slice())
25    }
26
27    fn consume(&mut self, amount: usize) {
28        self.advance(amount);
29    }
30}
31
32#[cfg_attr(coverage_nightly, coverage(off))]
33#[cfg(test)]
34mod tests {
35    use std::io::{BufRead, Read};
36
37    use crate::BytesView;
38    use crate::mem::testing::TransparentMemory;
39
40    #[test]
41    fn smoke_test() {
42        let memory = TransparentMemory::new();
43        let mut view = BytesView::copied_from_slice(b"Hello, world", &memory);
44
45        let mut buffer = [0u8; 5];
46        let bytes_read = view.read(&mut buffer).unwrap();
47
48        // We use white-box knowledge to know that we always read as much as is available,
49        // there are no partial reads unless at end of data. This simplifies the test logic.
50        assert_eq!(bytes_read, 5);
51        assert_eq!(&buffer, b"Hello");
52
53        let bytes_read = view.read(&mut buffer).unwrap();
54
55        assert_eq!(bytes_read, 5);
56        assert_eq!(&buffer, b", wor");
57
58        let bytes_read = view.read(&mut buffer).unwrap();
59        assert_eq!(bytes_read, 2);
60        assert_eq!(&buffer[..2], b"ld");
61
62        let bytes_read = view.read(&mut buffer).unwrap();
63        assert_eq!(bytes_read, 0);
64    }
65
66    #[test]
67    fn buf_read_fill_buf_and_consume() {
68        let memory = TransparentMemory::new();
69        let mut view = BytesView::copied_from_slice(b"Hello, world", &memory);
70
71        // fill_buf returns the first contiguous slice without consuming it.
72        let buf = view.fill_buf().unwrap();
73        assert_eq!(buf, b"Hello, world");
74
75        // Calling fill_buf again returns the same data (no consumption).
76        let buf = view.fill_buf().unwrap();
77        assert_eq!(buf, b"Hello, world");
78
79        // Consume some bytes and verify the remainder.
80        BufRead::consume(&mut view, 7);
81        let buf = view.fill_buf().unwrap();
82        assert_eq!(buf, b"world");
83
84        // Consume remaining bytes.
85        BufRead::consume(&mut view, 5);
86        let buf = view.fill_buf().unwrap();
87        assert!(buf.is_empty());
88    }
89
90    #[test]
91    fn buf_read_read_line() {
92        let memory = TransparentMemory::new();
93        let mut view = BytesView::copied_from_slice(b"first\nsecond\n", &memory);
94
95        let mut line = String::new();
96        let bytes_read = view.read_line(&mut line).unwrap();
97        assert_eq!(bytes_read, 6);
98        assert_eq!(line, "first\n");
99
100        line.clear();
101        let bytes_read = view.read_line(&mut line).unwrap();
102        assert_eq!(bytes_read, 7);
103        assert_eq!(line, "second\n");
104
105        line.clear();
106        let bytes_read = view.read_line(&mut line).unwrap();
107        assert_eq!(bytes_read, 0);
108        assert!(line.is_empty());
109    }
110
111    #[test]
112    fn buf_read_on_empty_view() {
113        let memory = TransparentMemory::new();
114        let mut view = BytesView::copied_from_slice(b"", &memory);
115
116        let buf = view.fill_buf().unwrap();
117        assert!(buf.is_empty());
118    }
119}