use crate::cmp::{max, min}; use crate::collections::VecDeque; use crate::io; use crate::io::*; #[test] fn copy_copies() { let mut r = repeat(0).take(4); let mut w = sink(); assert_eq!(copy(&mut r, &mut w).unwrap(), 4); let mut r = repeat(0).take(1 << 17); assert_eq!(copy(&mut r as &mut dyn Read, &mut w as &mut dyn Write).unwrap(), 1 << 17); } struct ShortReader { cap: usize, read_size: usize, observed_buffer: usize, } impl Read for ShortReader { fn read(&mut self, buf: &mut [u8]) -> Result { let bytes = min(self.cap, self.read_size).min(buf.len()); self.cap -= bytes; self.observed_buffer = max(self.observed_buffer, buf.len()); Ok(bytes) } } struct WriteObserver { observed_buffer: usize, } impl Write for WriteObserver { fn write(&mut self, buf: &[u8]) -> Result { self.observed_buffer = max(self.observed_buffer, buf.len()); Ok(buf.len()) } fn flush(&mut self) -> Result<()> { Ok(()) } } #[test] fn copy_specializes_bufwriter() { let cap = 117 * 1024; let buf_sz = 16 * 1024; let mut r = ShortReader { cap, observed_buffer: 0, read_size: 1337 }; let mut w = BufWriter::with_capacity(buf_sz, WriteObserver { observed_buffer: 0 }); assert_eq!( copy(&mut r, &mut w).unwrap(), cap as u64, "expected the whole capacity to be copied" ); assert_eq!(r.observed_buffer, buf_sz, "expected a large buffer to be provided to the reader"); assert!(w.get_mut().observed_buffer > DEFAULT_BUF_SIZE, "expected coalesced writes"); } #[test] fn copy_specializes_bufreader() { let mut source = vec![0; 768 * 1024]; source[1] = 42; let mut buffered = BufReader::with_capacity(256 * 1024, Cursor::new(&mut source)); let mut sink = Vec::new(); assert_eq!(crate::io::copy(&mut buffered, &mut sink).unwrap(), source.len() as u64); assert_eq!(source.as_slice(), sink.as_slice()); let buf_sz = 71 * 1024; assert!(buf_sz > DEFAULT_BUF_SIZE, "test precondition"); let mut buffered = BufReader::with_capacity(buf_sz, Cursor::new(&mut source)); let mut sink = WriteObserver { observed_buffer: 0 }; assert_eq!(crate::io::copy(&mut buffered, &mut sink).unwrap(), source.len() as u64); assert_eq!( sink.observed_buffer, buf_sz, "expected a large buffer to be provided to the writer" ); } #[test] fn copy_specializes_from_vecdeque() { let mut source = VecDeque::with_capacity(100 * 1024); for _ in 0..20 * 1024 { source.push_front(0); } for _ in 0..20 * 1024 { source.push_back(0); } let mut sink = WriteObserver { observed_buffer: 0 }; assert_eq!(40 * 1024u64, io::copy(&mut source, &mut sink).unwrap()); assert_eq!(20 * 1024, sink.observed_buffer); } #[test] fn copy_specializes_from_slice() { let mut source = [1; 60 * 1024].as_slice(); let mut sink = WriteObserver { observed_buffer: 0 }; assert_eq!(60 * 1024u64, io::copy(&mut source, &mut sink).unwrap()); assert_eq!(60 * 1024, sink.observed_buffer); } #[cfg(unix)] mod io_benches { use crate::fs::File; use crate::fs::OpenOptions; use crate::io::prelude::*; use crate::io::BufReader; use test::Bencher; #[bench] fn bench_copy_buf_reader(b: &mut Bencher) { let mut file_in = File::open("/dev/zero").expect("opening /dev/zero failed"); // use dyn to avoid specializations unrelated to readbuf let dyn_in = &mut file_in as &mut dyn Read; let mut reader = BufReader::with_capacity(256 * 1024, dyn_in.take(0)); let mut writer = OpenOptions::new().write(true).open("/dev/null").expect("opening /dev/null failed"); const BYTES: u64 = 1024 * 1024; b.bytes = BYTES; b.iter(|| { reader.get_mut().set_limit(BYTES); crate::io::copy(&mut reader, &mut writer).unwrap() }); } }