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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
use std::fmt::Debug;
use std::io::Read;

use byteorder::ReadBytesExt;

use crate::Error;

/// A reader that can temporarily buffer bytes read.
pub trait Reader<'de>: ReadBytesExt {
    /// Reads exactly `length` bytes.
    ///
    /// If the reader supports borrowing bytes, [`BufferedBytes::Data`] should
    /// be returned. Otherwise, the bytes will be read into `scratch`. `scratch`
    /// should only be assumed to be valid if [`BufferedBytes::Scratch`] is
    /// returned.
    fn buffered_read_bytes(
        &mut self,
        length: usize,
        scratch: &mut Vec<u8>,
    ) -> Result<BufferedBytes<'de>, Error>;
}

/// Bytes that have been read into a buffer.
#[derive(Debug)]
pub enum BufferedBytes<'de> {
    /// The bytes that have been read can be borrowed from the source.
    Data(&'de [u8]),
    /// The bytes that have been read have been stored in the scratch buffer
    /// passed to the function reading bytes.
    Scratch,
}

impl BufferedBytes<'_> {
    /// Resolves the bytes to a byte slice.
    #[inline]
    #[must_use]
    pub fn as_slice<'a>(&'a self, scratch: &'a [u8]) -> &'a [u8] {
        match self {
            BufferedBytes::Data(data) => data,
            BufferedBytes::Scratch => scratch,
        }
    }
}

/// Reads data from a slice.
#[allow(clippy::module_name_repetitions)]
pub struct SliceReader<'a> {
    pub(crate) data: &'a [u8],
}

impl<'a> SliceReader<'a> {
    /// Returns the remaining bytes to read.
    #[must_use]
    #[inline]
    pub const fn len(&self) -> usize {
        self.data.len()
    }

    /// Returns `true` if there are no bytes remaining to read.
    #[must_use]
    #[inline]
    pub const fn is_empty(&self) -> bool {
        self.data.is_empty()
    }
}

impl<'a> Debug for SliceReader<'a> {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
        f.debug_struct("SliceReader")
            .field(
                "preview",
                &format!("{:0x?}", &self.data[..8.min(self.data.len())]),
            )
            .finish()
    }
}

impl<'a> From<&'a [u8]> for SliceReader<'a> {
    #[inline]
    fn from(data: &'a [u8]) -> Self {
        Self { data }
    }
}

impl<'a> From<SliceReader<'a>> for &'a [u8] {
    #[inline]
    fn from(reader: SliceReader<'a>) -> Self {
        reader.data
    }
}

impl<'de> Reader<'de> for SliceReader<'de> {
    #[inline]
    fn buffered_read_bytes(
        &mut self,
        length: usize,
        _scratch: &mut Vec<u8>,
    ) -> Result<BufferedBytes<'de>, Error> {
        if length > self.data.len() {
            self.data = &self.data[self.data.len()..];
            Err(Error::Eof)
        } else {
            let (start, remaining) = self.data.split_at(length);
            self.data = remaining;
            Ok(BufferedBytes::Data(start))
        }
    }
}

impl<'a> Read for SliceReader<'a> {
    #[inline]
    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
        let remaining_length = self.data.len();
        let (to_copy, remaining) = self.data.split_at(remaining_length.min(buf.len()));
        buf[..to_copy.len()].copy_from_slice(to_copy);
        self.data = remaining;
        Ok(to_copy.len())
    }

    #[inline]
    fn read_exact(&mut self, buf: &mut [u8]) -> std::io::Result<()> {
        self.read(buf).map(|_| ())
    }
}

/// A reader over [`ReadBytesExt`].
#[allow(clippy::module_name_repetitions)]
pub struct IoReader<R: ReadBytesExt> {
    pub(crate) reader: R,
}
impl<R: ReadBytesExt> IoReader<R> {
    pub(crate) const fn new(reader: R) -> Self {
        Self { reader }
    }
}

impl<'de, R: ReadBytesExt> Reader<'de> for IoReader<R> {
    #[inline]
    fn buffered_read_bytes(
        &mut self,
        length: usize,
        scratch: &mut Vec<u8>,
    ) -> Result<BufferedBytes<'de>, Error> {
        scratch.resize(length, 0);
        self.reader.read_exact(scratch)?;
        Ok(BufferedBytes::Scratch)
    }
}

impl<R: ReadBytesExt> Read for IoReader<R> {
    #[inline]
    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
        self.reader.read(buf)
    }

    #[inline]
    fn read_vectored(&mut self, bufs: &mut [std::io::IoSliceMut<'_>]) -> std::io::Result<usize> {
        self.reader.read_vectored(bufs)
    }

    #[inline]
    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> std::io::Result<usize> {
        self.reader.read_to_end(buf)
    }

    #[inline]
    fn read_to_string(&mut self, buf: &mut String) -> std::io::Result<usize> {
        self.reader.read_to_string(buf)
    }

    #[inline]
    fn read_exact(&mut self, buf: &mut [u8]) -> std::io::Result<()> {
        self.reader.read_exact(buf)
    }
}

#[test]
fn slice_reader_pub_methods() {
    let mut reader = SliceReader::from(&b"a"[..]);
    assert_eq!(reader.len(), 1);
    assert!(!reader.is_empty());
    reader.read_exact(&mut [0]).unwrap();

    assert_eq!(reader.len(), 0);
    assert!(reader.is_empty());
    assert_eq!(<&[u8]>::from(reader), b"");
}