Skip to main content

bonerjams_db/rpc/
string_reader.rs

1//! Provides a wrapper for strings so that they can be consumed
2//! via the std::io::Read trait. This is especially useful when
3//! writing tests.
4//!
5//! # Examples
6//!
7//! ```
8//!    use std::io::{Read, BufRead, BufReader};
9//!    use stringreader::StringReader;
10//!
11//!    let mut streader = StringReader::new("Line 1\nLine 2");
12//!    let mut bufreader = BufReader::new(streader);
13//!    let mut buffer = String::new();
14//!
15//!    bufreader.read_line(&mut buffer).unwrap();
16//!    println!("{}", buffer);
17//! ```
18//!
19//! Prints "Line 1\n"
20
21use std::io::Read;
22use std::io::Result;
23use std::slice::Iter;
24
25pub struct StringReader<'a> {
26    iter: Iter<'a, u8>,
27}
28
29impl<'a> StringReader<'a> {
30    /// Wrap a string in a `StringReader`, which implements `std::io::Read`.
31    pub fn new(data: &'a str) -> Self {
32        Self {
33            iter: data.as_bytes().iter(),
34        }
35    }
36}
37
38impl<'a> Read for StringReader<'a> {
39    fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
40        for (i, item) in buf.iter_mut().enumerate() {
41            if let Some(x) = self.iter.next() {
42                *item = *x;
43            } else {
44                return Ok(i);
45            }
46        }
47        Ok(buf.len())
48    }
49}
50
51#[cfg(test)]
52mod test {
53    use super::*;
54    use std::io::{BufRead, BufReader};
55
56    #[test]
57    fn test() {
58        let data = "abc\ndef";
59        let mut reader = BufReader::new(StringReader::new(data));
60        let mut buffer = String::new();
61
62        buffer.clear();
63        reader.read_line(&mut buffer).unwrap();
64        assert_eq!("abc\n", buffer);
65
66        buffer.clear();
67        reader.read_line(&mut buffer).unwrap();
68        assert_eq!("def", buffer);
69    }
70}