buffered_reader/
dup.rs

1use std::io;
2use std::fmt;
3use std::cmp;
4
5use super::*;
6
7/// Duplicates the underlying `BufferedReader` without consuming any
8/// of the data.
9///
10/// Note: this will likely cause the underlying stream to buffer as
11/// much data as you read.  Thus, it should only be used for peeking
12/// at the underlying `BufferedReader`.
13#[derive(Debug)]
14pub struct Dup<T: BufferedReader<C>, C: fmt::Debug + Sync + Send> {
15    // The number of bytes that have been consumed.
16    cursor: usize,
17
18    // The user settable cookie.
19    cookie: C,
20
21    reader: T,
22}
23
24assert_send_and_sync!(Dup<T, C>
25                      where T: BufferedReader<C>,
26                            C: fmt::Debug);
27
28impl<T: BufferedReader<C>, C: fmt::Debug + Sync + Send> fmt::Display for Dup<T, C> {
29    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
30        f.debug_struct("Dup")
31            .field("cursor", &self.cursor)
32            .finish()
33    }
34}
35
36impl<T: BufferedReader<()>> Dup<T, ()> {
37    /// Instantiates a new `Dup` buffered reader.
38    ///
39    /// `reader` is the `BufferedReader` to duplicate.
40    pub fn new(reader: T) -> Self {
41        Self::with_cookie(reader, ())
42    }
43}
44
45impl<T: BufferedReader<C>, C: fmt::Debug + Sync + Send> Dup<T, C> {
46    /// Like [`Self::new`], but uses a cookie.
47    ///
48    /// The cookie can be retrieved using the [`BufferedReader::cookie_ref`] and
49    /// [`BufferedReader::cookie_mut`] methods, and set using the [`BufferedReader::cookie_set`] method.
50    pub fn with_cookie(reader: T, cookie: C) -> Self {
51        Dup {
52            reader,
53            cursor: 0,
54            cookie,
55        }
56    }
57
58    /// Returns the number of bytes that this reader has consumed.
59    pub fn total_out(&self) -> usize {
60        self.cursor
61    }
62
63    /// Resets the cursor to the beginning of the stream.
64    pub fn rewind(&mut self) {
65        self.cursor = 0;
66    }
67}
68
69impl<T: BufferedReader<C>, C: fmt::Debug + Sync + Send> io::Read for Dup<T, C> {
70    fn read(&mut self, buf: &mut [u8]) -> Result<usize, io::Error> {
71        let data = self.reader.data(self.cursor + buf.len())?;
72        assert!(data.len() >= self.cursor);
73        let data = &data[self.cursor..];
74
75        let amount = cmp::min(buf.len(), data.len());
76        buf[..amount].copy_from_slice(&data[..amount]);
77
78        self.cursor += amount;
79
80        Ok(amount)
81    }
82}
83
84impl<T: BufferedReader<C>, C: fmt::Debug + Send + Sync> BufferedReader<C> for Dup<T, C> {
85    fn buffer(&self) -> &[u8] {
86        let data = self.reader.buffer();
87        assert!(data.len() >= self.cursor);
88        &data[self.cursor..]
89    }
90
91    fn data(&mut self, amount: usize) -> Result<&[u8], io::Error> {
92        let data = self.reader.data(self.cursor + amount)?;
93        assert!(data.len() >= self.cursor);
94        Ok(&data[self.cursor..])
95    }
96
97    fn consume(&mut self, amount: usize) -> &[u8] {
98        let data = self.reader.buffer();
99        assert!(data.len() >= self.cursor + amount);
100        let data = &data[self.cursor..];
101        self.cursor += amount;
102        data
103    }
104
105    fn data_consume(&mut self, amount: usize) -> Result<&[u8], io::Error> {
106        let data = self.reader.data(self.cursor + amount)?;
107        assert!(data.len() >= self.cursor);
108        let data = &data[self.cursor..];
109        self.cursor += cmp::min(data.len(), amount);
110        Ok(data)
111    }
112
113    fn data_consume_hard(&mut self, amount: usize) -> Result<&[u8], io::Error> {
114        let data = self.reader.data_hard(self.cursor + amount)?;
115        assert!(data.len() >= self.cursor + amount);
116        let data = &data[self.cursor..];
117        self.cursor += amount;
118        Ok(data)
119    }
120
121    fn get_mut(&mut self) -> Option<&mut dyn BufferedReader<C>> {
122        Some(&mut self.reader)
123    }
124
125    fn get_ref(&self) -> Option<&dyn BufferedReader<C>> {
126        Some(&self.reader)
127    }
128
129    fn into_inner<'b>(self: Box<Self>) -> Option<Box<dyn BufferedReader<C> + 'b>>
130            where Self: 'b {
131        Some(self.reader.into_boxed())
132    }
133
134    fn cookie_set(&mut self, cookie: C) -> C {
135        use std::mem;
136
137        mem::replace(&mut self.cookie, cookie)
138    }
139
140    fn cookie_ref(&self) -> &C {
141        &self.cookie
142    }
143
144    fn cookie_mut(&mut self) -> &mut C {
145        &mut self.cookie
146    }
147}
148
149#[cfg(test)]
150mod test {
151    use super::*;
152
153    #[test]
154    fn buffered_reader_memory_test () {
155        let data = crate::BUFFERED_READER_TEST_DATA;
156        let reader = Memory::new(data);
157        let mut reader = Dup::new(reader);
158
159        buffered_reader_test_data_check(&mut reader);
160
161        let consumed = reader.total_out();
162        assert_eq!(consumed, data.len());
163
164        // Since we haven't consumed the inner buffer, this should
165        // still work.
166        let mut reader = Box::new(reader).into_inner().unwrap();
167
168        // Try to read consumed + 1 bytes (which shouldn't be
169        // possible).
170        assert_eq!(consumed, reader.data(consumed + 1).unwrap().len());
171
172        buffered_reader_test_data_check(&mut reader);
173    }
174
175    // Test that buffer() returns the same data as data().
176    #[test]
177    fn buffer_test() {
178        // Test vector.  A Dup returns all unconsumed
179        // data.  So, use a relatively small buffer size.
180        let size = default_buf_size();
181        let mut input = Vec::with_capacity(size);
182        let mut v = 0u8;
183        for _ in 0..size {
184            input.push(v);
185            if v == std::u8::MAX {
186                v = 0;
187            } else {
188                v += 1;
189            }
190        }
191
192        let reader = Memory::new(&input[..]);
193        let mut reader = Dup::new(reader);
194
195        for i in 0..input.len() {
196            let data = reader.data(default_buf_size() + 1).unwrap().to_vec();
197            assert!(!data.is_empty());
198            assert_eq!(data, reader.buffer());
199            // And, we may as well check to make sure we read the
200            // right data.
201            assert_eq!(data, &input[i..i+data.len()]);
202
203            // Consume one byte and see what happens.
204            reader.consume(1);
205        }
206    }
207}