Skip to main content

io_providers/stream/
virtual_provider.rs

1use std::collections::VecDeque;
2use std::io;
3use std::io::{Read, Write};
4use stream;
5
6/// Provides virtual input/output/error streams: input can be provided using
7/// `Virtual::write_input()`, and output can be observed using `Virtual::read_output()` and
8/// `Virtual::read_error()`.
9pub struct Virtual {
10    inputs: ChunkPipe,
11    output: Vec<u8>,
12    error: Vec<u8>,
13}
14
15impl Virtual {
16    /// Creates a new, empty virtual stream provider.
17    pub fn new() -> Virtual {
18        Virtual {
19            inputs: ChunkPipe::new(),
20            output: Vec::new(),
21            error: Vec::new(),
22        }
23    }
24
25    /// Writes the provided buffer to the queue of buffers to be used when input is requested
26    /// from this provider using `Provider::input()`.
27    ///
28    /// In particular, this method does NOT append data to a continuous buffer which is consumed
29    /// by `Provider::input()`; rather, it enqueues a buffer which will be used for a SINGLE call
30    /// to `Provider::input()`. The buffer is then discarded, regardless of how much of it was
31    /// (or was not) read.
32    ///
33    /// This enables precise control over the length of data returned from a call to
34    /// `Provider::input()`.
35    ///
36    /// ## Example
37    ///
38    /// ```
39    /// use io_providers::stream;
40    ///
41    /// let mut streams = stream::Virtual::new();
42    /// streams.write_input("foo".as_bytes());
43    /// streams.write_input("bar".as_bytes());
44    /// // The first read on `streams.input()` will read from "foo"
45    /// // The second read on `streams.input()` will read from "bar"
46    /// ```
47    pub fn write_input(&mut self, input: &[u8]) {
48        self.inputs.write(input).unwrap();
49    }
50
51    /// Gets the data which has been written to the output stream.
52    ///
53    /// ## Example
54    ///
55    /// ```
56    /// use std::io::Write;
57    /// use io_providers::stream;
58    /// use io_providers::stream::Provider;
59    ///
60    /// let mut streams = stream::Virtual::new();
61    /// writeln!(streams.output(), "test1");
62    /// write!(streams.output(), "test2");
63    /// assert_eq!("test1\ntest2", ::std::str::from_utf8(streams.read_output()).unwrap());
64    /// ```
65    pub fn read_output<'a>(&'a self) -> &'a [u8] {
66        &self.output[..]
67    }
68
69    /// Gets the data which has been written to error stream.
70    ///
71    /// ## Example
72    ///
73    /// ```
74    /// use std::io::Write;
75    /// use io_providers::stream;
76    /// use io_providers::stream::Provider;
77    ///
78    /// let mut streams = stream::Virtual::new();
79    /// writeln!(streams.error(), "test1");
80    /// write!(streams.error(), "test2");
81    /// assert_eq!("test1\ntest2", ::std::str::from_utf8(streams.read_error()).unwrap());
82    /// ```
83    pub fn read_error<'a>(&'a self) -> &'a [u8] {
84        &self.error[..]
85    }
86}
87
88impl stream::Provider for Virtual {
89    fn input(&mut self) -> &mut Read {
90        &mut self.inputs
91    }
92
93    fn output(&mut self) -> &mut Write {
94        &mut self.output
95    }
96
97    fn error(&mut self) -> &mut Write {
98        &mut self.error
99    }
100}
101
102/// A `Read` and `Write` implementer where data is written in chunks and each read consumes a
103/// single chunk.
104struct ChunkPipe {
105    items: VecDeque<Vec<u8>>
106}
107
108impl ChunkPipe {
109    /// Creates a new, empty `ChunkPipe`.
110    pub fn new() -> ChunkPipe {
111        ChunkPipe {
112            items: VecDeque::new(),
113        }
114    }
115}
116
117impl Read for ChunkPipe {
118    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
119        if let Some(item) = self.items.pop_front() {
120            io::Cursor::new(item).read(buf)
121        }
122        else {
123            Ok(0)
124        }
125    }
126}
127
128impl Write for ChunkPipe {
129    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
130        let mut vec = Vec::new();
131        let result = vec.write(buf);
132        self.items.push_back(vec);
133        result
134    }
135
136    fn flush(&mut self) -> io::Result<()> {
137        Ok(())
138    }
139}
140
141#[cfg(test)]
142#[allow(non_snake_case)]
143mod tests {
144    use std::io::{Read, Write};
145    use super::{ChunkPipe, Virtual};
146    use stream::Provider;
147
148    #[test]
149    fn chunk_pipe__no_writes__reads_successfully() {
150        let mut buf: Vec<u8> = vec![0; 8];
151        let mut pipe = ChunkPipe::new();
152        pipe.write(&[]).unwrap();
153
154        let result = pipe.read(&mut buf);
155        assert_eq!(0, result.unwrap());
156    }
157
158    #[test]
159    fn chunk_pipe__one_write__reads_successfully() {
160        let data = vec![1, 2, 3];
161        let mut buf1 = vec![0; 4];
162        let mut buf2 = vec![0; 4];
163        let mut pipe = ChunkPipe::new();
164
165        pipe.write(&data[..]).unwrap();
166        let result1 = pipe.read(&mut buf1).unwrap();
167        let result2 = pipe.read(&mut buf2).unwrap();
168
169        assert_eq!(data.len(), result1);
170        assert_eq!(vec![1, 2, 3, 0], buf1);
171        assert_eq!(0, result2);
172    }
173
174    #[test]
175    fn chunk_pipe__two_writes__reads_successfully() {
176        let data1 = vec![1, 2, 3];
177        let data2 = vec![4, 5, 6, 7];
178        let mut buf1 = vec![0; 4];
179        let mut buf2 = vec![0; 3];
180        let mut buf3 = vec![0; 3];
181        let mut pipe = ChunkPipe::new();
182
183        pipe.write(&data1[..]).unwrap();
184        let result1 = pipe.read(&mut buf1).unwrap();
185        pipe.write(&data2[..]).unwrap();
186        let result2 = pipe.read(&mut buf2).unwrap();
187        let result3 = pipe.read(&mut buf3).unwrap();
188
189        assert_eq!(data1.len(), result1);
190        assert_eq!(vec![1, 2, 3, 0], buf1);
191        assert_eq!(buf2.len(), result2);
192        assert_eq!(vec![4, 5, 6], buf2);
193        assert_eq!(0, result3);
194    }
195
196    #[test]
197    fn provider__empty_input__length_zero_read() {
198        let mut provider = Virtual::new();
199        let mut buf = vec![0;4];
200
201        let result = provider.input().read(&mut buf).unwrap();
202
203        assert_eq!(0, result);
204    }
205
206    #[test]
207    fn provider__write_and_read_input__success() {
208        let mut provider = Virtual::new();
209        let expected = "test";
210        let mut actual = String::new();
211        let mut buf = vec![0;4];
212
213        provider.write_input(expected.as_bytes());
214        let result = provider.input().read_to_string(&mut actual).unwrap();
215
216        assert_eq!(expected.len(), result);
217        assert_eq!(expected, actual);
218
219        let result = provider.input().read(&mut buf).unwrap();
220        assert_eq!(0, result);
221    }
222
223    #[test]
224    fn provider__two_input_writes__two_reads() {
225        let mut provider = Virtual::new();
226        let (expected1, expected2) = (vec![1,2,3], vec![4,5,6]);
227        let (mut actual1, mut actual2) = (vec![0;3], vec![0;3]);
228
229        provider.write_input(&expected1[..]);
230        provider.write_input(&expected2[..]);
231        let result1 = provider.input().read(&mut actual1).unwrap();
232        let result2 = provider.input().read(&mut actual2).unwrap();
233
234        assert_eq!(expected1.len(), result1);
235        assert_eq!(expected1, actual1);
236        assert_eq!(expected2.len(), result2);
237        assert_eq!(expected2, actual2);
238    }
239
240    #[test]
241    fn provider__write_read_output__success() {
242        let mut provider = Virtual::new();
243
244        let result1 = provider.output().write(&[1,2]).unwrap();
245        let result2 = provider.output().write(&[3,4]).unwrap();
246        let actual = provider.read_output();
247
248        assert_eq!(2, result1);
249        assert_eq!(2, result2);
250        assert_eq!(&[1,2,3,4], actual);
251    }
252
253    #[test]
254    fn provider__write_read_error__success() {
255        let mut provider = Virtual::new();
256
257        let result1 = provider.error().write(&[1,2]).unwrap();
258        let result2 = provider.error().write(&[3,4]).unwrap();
259        let actual = provider.read_error();
260
261        assert_eq!(2, result1);
262        assert_eq!(2, result2);
263        assert_eq!(&[1,2,3,4], actual);
264    }
265}