1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
use std::io::{Error, Read};
use std::mem::swap;

/// from https://github.com/C4K3/peekable-reader-rs/blob/master/src/lib.rs

/// A wrapper around any struct implementing the `Read` trait, additionally
/// allowing for `peek` operations to be performed. Therefore, the
/// `PeekableReader` struct also implements the `Read` trait.
///
/// The primary invariant of the `PeekableReader` is that after calling the
/// `peek` method, the next `read_byte` call will return the same result as
/// the `peek` does. When the result is a byte (read off the wrapped reader),
/// any read-type method of the `Reader` trait will include the byte as the
/// first one. On the other hand, if the result is an `io::Error`, the error
/// will be returned regardless of which read-type method of the `Reader` is
/// invoked. Consecutive `peek`s before any read-type operation is used
/// always return the same `io::Result`.
///
/// When using peek_u8 you will get a Result<u8, &Error>, while when you call
/// any of the `Read` functions you will get an io::Result<u8>, thereby
/// consuming the io::Error (if any.)
pub struct PeekableReader<R> {
    inner: R,
    peeked_result: Option<Result<u8, Error>>,
}

/// A wrapper around any struct implementing the `Read` trait, additionally
/// allowing for `peek` operations to be performed. Therefore, the
/// `PeekableReader` struct also implements the `Read` trait.
///
/// The primary invariant of the `PeekableReader` is that after calling the
/// `peek` method, the next `read_byte` call will return the same result as
/// the `peek` does. When the result is a byte (read off the wrapped reader),
/// any read-type method of the `Reader` trait will include the byte as the
/// first one. On the other hand, if the result is an `io::Error`, the error
/// will be returned regardless of which read-type method of the `Reader` is
/// invoked. Consecutive `peek`s before any read-type operation is used
/// always return the same `io::Result`.
///
pub trait Peekable: Read {
    /// When using peek_u8 you will get a Result<u8, &Error>, while when you call
    /// any of the `Read` functions you will get an io::Result<u8>, thereby
    /// consuming the io::Error (if any.)
    fn peek_u8(&mut self) -> Result<u8, &Error>;
}

impl<R: Read> Peekable for PeekableReader<R> {
    /// Returns the `io::Result` which the Reader will return on the next
    /// `get_byte` call.
    ///
    /// If the `io::Result` is indeed an `io::Error`, the error will be returned
    /// for any subsequent read operation invoked upon the `Read`er.
    fn peek_u8(&mut self) -> Result<u8, &Error> {
        // Return either the currently cached peeked byte or obtain a new one
        // from the underlying reader.
        match self.peeked_result {
            Some(Ok(x)) => Ok(x),
            Some(Err(ref e)) => Err(e),
            None => {
                // First get the result of the read from the underlying reader
                let mut tmp: [u8; 1] = [0];
                self.peeked_result = match self.inner.read_exact(&mut tmp) {
                    Ok(()) => Some(Ok(tmp[0])),
                    Err(e) => Some(Err(e)),
                };

                // Now just return that
                let tmp: Result<u8, &Error> = match self.peeked_result {
                    Some(Ok(x)) => Ok(x),
                    Some(Err(ref e)) => Err(e),
                    None => unreachable!(),
                };
                tmp
            }
        }
    }
}

impl<R: Read> PeekableReader<R> {
    /// Initializes a new `PeekableReader` which wraps the given underlying
    /// reader.
    pub fn new(reader: R) -> PeekableReader<R> {
        PeekableReader {
            inner: reader,
            peeked_result: None,
        }
    }
}

impl<R: Read> Read for PeekableReader<R> {
    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Error> {
        if buf.is_empty() {
            return Ok(0);
        }

        // First, put the byte that was read off the underlying reader in a
        // (possible) previous peek operation (if such a byte is indeed cached)
        let mut tmp = None;
        swap(&mut tmp, &mut self.peeked_result);
        let offset = match tmp {
            Some(Err(e)) => {
                return Err(e);
            }
            Some(Ok(b)) => {
                buf[0] = b;
                1
            }
            None => 0,
        };

        if offset == 1 && buf.len() == 1 {
            // We've filled the buffer by using the previously peeked byte
            Ok(1)
        } else {
            // We are still missing more bytes, so we read them from the
            // underlying reader and place them directly in the correct place
            // in the buffer.
            Ok((self.inner.read(&mut buf[offset..]))? + offset)
        }
    }
}

#[cfg(test)]
mod tests {
    use super::*;
    use crate::vlq_encode::ReadSigmaVlqExt;
    use std::io::Cursor;

    #[test]
    fn test_peek_u8() {
        let mut r = PeekableReader::new(Cursor::new(vec![0, 1]));
        assert_eq!(r.peek_u8().unwrap(), 0);
        assert_eq!(r.get_u8().unwrap(), 0);
        assert_eq!(r.peek_u8().unwrap(), 1);
        assert_eq!(r.get_u8().unwrap(), 1);
    }
}