bufreaderwriter/
lib.rs

1//! The `BufReaderWriterRand<RW>` and `BufReaderWriterSeq<RW>` are convenience structs that facilitate automatic
2//! switching between buffered reading and writing from a single underlying IO instance. `BufReaderWriterRand` is
3//! for random access IO (i.e. Read + Write + Seek, such as `std::fs::File`), while `BufReaderWriterSeq` is for sequential
4//! IO (i.e. Read + Write, such as `std::net::TcpStream`).
5//!
6//! Both structs move the underlying IO instance between a BufReader and BufWriter as needed.  However, when switching from
7//! reading to writing, `BufReaderWriterRand` discards any buffered data and seeks the underlying IO instance back to the
8//! current BufReader position, while `BufReaderWriterSeq` saves any buffered data and makes it available for subsequent
9//! reads.
10//!
11//! # Example
12//!
13//! ```no_run
14//! # use std::io::{self, Read, Seek, SeekFrom, Write};
15//! use bufreaderwriter::rand::BufReaderWriterRand;
16//! use tempfile::tempfile;
17//!
18//! fn main() -> io::Result<()> {
19//!     let mut brw = BufReaderWriterRand::new_writer(tempfile()?);
20//!     let data = "The quick brown fox jumps over the lazy dog".to_owned();
21//!     brw.write(data.as_bytes())?;
22//!
23//!     brw.seek(SeekFrom::Start(0))?;
24//!     let mut bin = vec![0; data.len()];
25//!     brw.read(&mut bin)?;
26//!     Ok(())
27//! }
28//! ```
29
30pub mod rand;
31pub mod seq;
32
33#[cfg(test)]
34mod tests {
35    use crate::rand::BufReaderWriterRand;
36    use crate::seq::BufReaderWriterSeq;
37    use std::io::{Read, Seek, SeekFrom, Write};
38    use std::net::{TcpListener, TcpStream};
39    use std::thread;
40    use std::time::Duration;
41    use tempfile::tempfile;
42
43    #[test]
44    fn testrand() {
45        let file = tempfile().expect("Error creating temp file");
46        let mut brw = BufReaderWriterRand::writer_with_capacity(3333, file);
47        assert_eq!(3333, brw.capacity());
48
49        let data = "The quick brown fox jumps over the lazy dog".to_owned();
50        let data_len = data.len();
51
52        for _ in 0..1000 {
53            assert_eq!(data_len, brw.write(data.as_bytes()).expect("Write error"));
54        }
55
56        brw.seek(SeekFrom::Start(0)).expect("Seek error");
57        for _ in 0..1000 {
58            let mut bin = vec![0; data_len];
59            let mut r = 0;
60            while r < data_len {
61                r += brw.read(&mut bin[r..]).expect("Read error");
62            }
63            assert_eq!(data.as_str(), std::str::from_utf8(&bin).unwrap());
64        }
65
66        brw.get_mut().set_len(3).expect("Error truncating file");
67        brw.seek(SeekFrom::End(0)).expect("Seek error");
68        brw.write(" dog".as_bytes()).expect("Write error");
69
70        brw.seek(SeekFrom::Start(0)).expect("Seek error");
71        let mut bin = vec![0; 7];
72        assert_eq!(7, brw.read(&mut bin).expect("Read error"));
73        assert_eq!("The dog".to_owned(), String::from_utf8(bin).unwrap());
74
75        let _f = brw.into_inner().expect("Error extracting underlying file");
76    }
77
78    #[test]
79    fn testseq() {
80        let data = "The quick brown fox jumps over the lazy dog".to_owned();
81        let data_len = data.len();
82
83        let handle = thread::spawn(|| {
84            let tcp = TcpListener::bind("127.0.0.1:8080").expect("TcpListener error");
85            match tcp.accept() {
86                Ok((mut socket, _addr)) => {
87                    socket
88                        .set_read_timeout(Some(Duration::new(2, 0)))
89                        .expect("Read timeout");
90                    let mut buf = vec![0_u8; 100];
91                    loop {
92                        match socket.read(&mut buf[..]) {
93                            Ok(n) => {
94                                socket.write(&buf[0..n]).expect("write io error");
95                            }
96                            Err(e) => match e.kind() {
97                                std::io::ErrorKind::TimedOut => break,
98                                _ => panic!("listener read error {}", e),
99                            },
100                        }
101                    }
102                }
103                Err(e) => panic!("TCP Listen error {}", e),
104            }
105        });
106
107        let socket2 = TcpStream::connect("127.0.0.1:8080").expect("TcpStream error");
108        let mut brw = BufReaderWriterSeq::writer_with_capacity(3333, socket2);
109        assert_eq!(3333, brw.capacity());
110
111        thread::sleep(Duration::new(1, 0));
112        assert_eq!(data_len, brw.write(data.as_bytes()).expect("Write error"));
113
114        let mut buf = vec![0_u8; 10];
115        let _n = brw.read(&mut buf[..]).expect("read io error");
116        assert_eq!(std::str::from_utf8(&buf).unwrap(), &data[0..10]);
117
118        let _n = brw.write(data.as_bytes()).expect("write io error");
119        assert_eq!(brw.buffer().map_or(0, |b| b.len()) > 0, true);
120
121        let mut buf = vec![0_u8; 5];
122        let _n = brw.read(&mut buf[..]).expect("read io error");
123        assert_eq!(brw.buffer().unwrap().len() > 0, true);
124        let outdata = std::str::from_utf8(&buf).unwrap();
125        assert_eq!(outdata, &data[10..15]);
126
127        let mut buf = vec![0_u8; 2 * data_len];
128        let n = brw.read(&mut buf[..]).expect("read io error");
129        assert_eq!(n, (2* data_len) - 15);
130        let outdata = std::str::from_utf8(&buf).unwrap();
131        assert_eq!(&outdata[0..data_len - 15], &data[15..]);
132        assert_eq!(&outdata[data_len - 15..n], &data);
133
134        handle.join().expect("Join thread error");
135    }
136}