buffer_io/
lib.rs

1#[macro_use]
2pub mod buffer {
3    use std::io::{Read, Seek, SeekFrom, Write};
4    /// Specifies the position in a stream to use for seeking.
5    #[derive(PartialEq)]
6    pub enum SeekOrigin {
7        /// Specifies the beginning of a stream.
8        Begin,
9        /// Specifies the current position within a stream.
10        Current,
11        /// Specifies the end of a stream.
12        End,
13    }
14
15    /// Endianness refers to the order of bytes (or sometimes bits) within a binary representation of a number.
16    #[derive(PartialEq)]
17    pub enum Endianness {
18        /// The least significant byte (LSB) value, 0Dh, is at the lowest address.
19        /// The other bytes follow in increasing order of significance.
20        /// This is akin to right-to-left reading in hexadecimal order.
21        Little,
22        /// The most significant byte (MSB) value, 0Ah, is at the lowest address.
23        /// The other bytes follow in decreasing order of significance.
24        /// This is akin to left-to-right reading in hexadecimal order.
25        Big,
26    }
27
28    /// Writes primitive types in binary to a stream and supports writing strings in a specific encoding.
29    pub struct BufferWriter<W: Write> {
30        pub writer: W,
31    }
32
33    impl<W: Write> BufferWriter<W>
34    where
35        W: Seek + Read + Write,
36    {
37        /// Creates a new BufferWriter instance
38        pub fn new(writer: W) -> Self {
39            BufferWriter { writer: writer }
40        }
41        /// Gets the position within the current stream.
42        pub fn position(&mut self) -> Result<u64, BufferError> {
43            self.seek(0, SeekOrigin::Current)
44        }
45        /// Gets the length in bytes of the stream.
46        pub fn len(&mut self) -> Result<u64, BufferError> {
47            let old_pos = self.position()?;
48            let len = self.seek(0, SeekOrigin::End)?;
49            if old_pos != len {
50                self.seek(old_pos as i64, SeekOrigin::Begin)?;
51            }
52            Ok(len)
53        }
54        pub fn to_vec(&mut self) -> Result<Vec<u8>, BufferError> {
55            let mut out: Vec<u8> = vec![];
56            self.seek(0, SeekOrigin::Begin)?;
57            self.writer.read_to_end(&mut out).unwrap();
58            Ok(out)
59        }
60        pub fn seek(&mut self, position: i64, origin: SeekOrigin) -> Result<u64, BufferError> {
61            match origin {
62                SeekOrigin::Begin => self.writer.seek(SeekFrom::Start(position as u64)),
63                SeekOrigin::Current => self.writer.seek(SeekFrom::Current(position)),
64                SeekOrigin::End => self.writer.seek(SeekFrom::End(position)),
65            }
66            .map(|o| o)
67            .map_err(|_e| BufferError::IndexOutOfRange { index: position })
68        }
69
70        /// Writes a four-byte unsigned integer to the current stream
71        /// and advances the stream position by four bytes.
72        pub fn write_u32(&mut self, value: u32) -> Result<u64, BufferError> {
73            let data = &[
74                (value >> 0) as u8,
75                (value >> 8) as u8,
76                (value >> 16) as u8,
77                (value >> 24) as u8,
78            ];
79            self.writer
80                .write(data)
81                .map(|o| o as u64)
82                .map_err(|_e| BufferError::IOFailure)
83        }
84
85        /// Writes an eight-byte unsigned integer to the current stream
86        /// and advances the stream position by eight bytes.
87        pub fn write_u64(&mut self, value: u64) -> Result<u64, BufferError> {
88            let data = &[
89                (value >> 0) as u8,
90                (value >> 8) as u8,
91                (value >> 16) as u8,
92                (value >> 24) as u8,
93                (value >> 32) as u8,
94                (value >> 40) as u8,
95                (value >> 48) as u8,
96                (value >> 56) as u8,
97            ];
98            self.writer
99                .write(data)
100                .map(|o| o as u64)
101                .map_err(|_e| BufferError::IOFailure)
102        }
103
104        /// Writes a four-byte signed integer to the current stream
105        /// and advances the stream position by four bytes.
106        pub fn write_i32(&mut self, value: i32) -> Result<u64, BufferError> {
107            let data = &[
108                (value >> 0) as u8,
109                (value >> 8) as u8,
110                (value >> 16) as u8,
111                (value >> 24) as u8,
112            ];
113            self.writer
114                .write(data)
115                .map(|o| o as u64)
116                .map_err(|_e| BufferError::IOFailure)
117        }
118
119        /// Writes a two-byte unsigned integer to the current stream
120        /// and advances the stream position by two bytes.
121        pub fn write_u16(&mut self, value: u16) -> Result<u64, BufferError> {
122            let data = &[(value >> 0) as u8, (value >> 8) as u8];
123            self.writer
124                .write(data)
125                .map(|o| o as u64)
126                .map_err(|_e| BufferError::IOFailure)
127        }
128
129        /// Writes an unsigned byte to the current stream
130        /// and advances the stream position by one byte.
131        pub fn write_u8(&mut self, value: u8) -> Result<u64, BufferError> {
132            self.writer
133                .write(&[value])
134                .map(|o| o as u64)
135                .map_err(|_e| BufferError::IOFailure)
136        }
137
138        /// Write out an int 7 bits at a time. The high bit of the byte,
139        /// when on, tells reader to continue reading more bytes.
140        pub fn write_7bit_int(&mut self, value: i32) -> Result<(), BufferError> {
141            let mut v = value as u32;
142            while v >= 0x80 {
143                self.write_u8((v | 0x80) as u8)?;
144                v >>= 7;
145            }
146            self.write_u8(v as u8)?;
147            Ok(())
148        }
149
150        /// Writes a length-prefixed string to this stream in UTF8-encoding
151        /// and advances the current position of the stream in accordance with the encoding
152        /// used and the specific characters being written to the stream.
153        pub fn write_string(&mut self, value: String) -> Result<u64, BufferError> {
154            let bytes = value.as_bytes();
155            self.write_7bit_int(bytes.len() as i32)?;
156            self.writer
157                .write(bytes)
158                .map(|o| o as u64)
159                .map_err(|_e| BufferError::IOFailure)
160        }
161
162        /// Writes a section of a bytes to the current stream, and advances the current position of the stream
163        pub fn write_bytes(&mut self, value: &Vec<u8>) -> Result<u64, BufferError> {
164            self.writer
165                .write(value)
166                .map(|o| o as u64)
167                .map_err(|_e| BufferError::IOFailure)
168        }
169    }
170
171    /// Reads primitive data types as binary values in a specific encoding.
172    pub struct BufferReader<R: Read> {
173        pub reader: R,
174    }
175
176    impl<R: Read> BufferReader<R>
177    where
178        R: Seek + Read + Write,
179    {
180        /// Creates a new BufferReader
181        pub fn new(reader: R) -> Self {
182            BufferReader { reader: reader }
183        }
184        /// Gets the position within the current stream.
185        pub fn position(&mut self) -> Result<u64, BufferError> {
186            self.seek(0, SeekOrigin::Current)
187        }
188        /// Gets the length in bytes of the stream.
189        pub fn len(&mut self) -> Result<u64, BufferError> {
190            let old_pos = self.position()?;
191            let len = self.seek(0, SeekOrigin::End)?;
192            if old_pos != len {
193                self.seek(old_pos as i64, SeekOrigin::Begin)?;
194            }
195            Ok(len)
196        }
197        pub fn seek(&mut self, position: i64, origin: SeekOrigin) -> Result<u64, BufferError> {
198            match origin {
199                SeekOrigin::Begin => self.reader.seek(SeekFrom::Start(position as u64)),
200                SeekOrigin::Current => self.reader.seek(SeekFrom::Current(position)),
201                SeekOrigin::End => self.reader.seek(SeekFrom::End(position)),
202            }
203            .map(|o| o as u64)
204            .map_err(|_e| BufferError::IndexOutOfRange { index: position })
205        }
206
207        /// Reads in a 32-bit integer in compressed format.
208        pub fn read_7bit_int(&mut self) -> Result<i32, BufferError> {
209            let mut count: i32 = 0;
210            let mut shift = 0;
211            let mut b: u8 = 0;
212            while {
213                // Check for a corrupted stream.  Read a max of 5 bytes.
214                // In a future version, add a DataFormatException.
215                if shift == 5 * 7 {
216                    // 5 bytes max per Int32, shift += 7
217                    // too many bytes in what should have been a 7 bit encoded i32.
218                    return Err(BufferError::IOFailure);
219                }
220                // read_u8 handles end of stream cases for us.
221                b = self.read_u8()?;
222                count |= ((b & 0x7F) as i32) << shift;
223                shift += 7;
224                (b & 0x80) != 0
225            } {}
226            Ok(count)
227        }
228        /// Reads a null-terminated string from the buffer
229        pub fn read_string(&mut self) -> Result<String, BufferError> {
230            let string_length = self.read_7bit_int()?;
231            if string_length < 0 {
232                return Err(BufferError::IOFailure);
233            }
234            if string_length == 0 {
235                return Ok(String::default());
236            }
237            let chars = self.read_bytes(string_length as u64)?;
238            String::from_utf8(chars)
239                .map(|o| o)
240                .map_err(|_e| BufferError::IOFailure)
241        }
242
243        /// Reads a 4-byte unsigned integer from the current vector
244        /// and advances the position of the cursor by four bytes.
245        pub fn read_u32(&mut self) -> Result<u32, BufferError> {
246            let size = std::mem::size_of::<u32>() as u64;
247            if self.position()? + size > self.len()? {
248                return Err(BufferError::EndOfStream);
249            }
250            let mut buffer = [0u8; 4];
251            self.reader
252                .read_exact(&mut buffer)
253                .map_err(|e| BufferError::ReadFailure(e))
254                .map(|_b| {
255                    ((buffer[0] as u32) << 0)
256                        | ((buffer[1] as u32) << 8)
257                        | ((buffer[2] as u32) << 16)
258                        | ((buffer[3] as u32) << 24)
259                })
260        }
261
262        /// Reads a 8-byte unsigned integer from the current vector
263        /// and advances the position of the cursor by eight bytes.
264        pub fn read_u64(&mut self) -> Result<u64, BufferError> {
265            let size = std::mem::size_of::<u64>() as u64;
266            if self.position()? + size > self.len()? {
267                return Err(BufferError::EndOfStream);
268            }
269            let mut buffer = vec![0u8; 8];
270            self.reader
271                .read_exact(&mut buffer)
272                .map_err(|e| BufferError::ReadFailure(e))
273                .map(|_b| {
274                    let lo = (buffer[0] as u32)
275                        | (buffer[1] as u32) << 8
276                        | (buffer[2] as u32) << 16
277                        | (buffer[3] as u32) << 24;
278                    let hi = (buffer[4] as u32)
279                        | (buffer[5] as u32) << 8
280                        | (buffer[6] as u32) << 16
281                        | (buffer[7] as u32) << 24;
282
283                    (hi as u64) << 32 | lo as u64
284                })
285        }
286
287        /// Reads a 4-byte signed integer from the current vector
288        /// and advances the current position of the cursor by four bytes.
289        pub fn read_i32(&mut self) -> Result<i32, BufferError> {
290            let size = std::mem::size_of::<i32>() as u64;
291            if self.position()? + size > self.len()? {
292                return Err(BufferError::EndOfStream);
293            }
294            let mut buffer = [0u8; 4];
295            self.reader
296                .read_exact(&mut buffer)
297                .map_err(|e| BufferError::ReadFailure(e))
298                .map(|_b| {
299                    ((buffer[0] as i32) << 0)
300                        | ((buffer[1] as i32) << 8)
301                        | ((buffer[2] as i32) << 16)
302                        | ((buffer[3] as i32) << 24)
303                })
304        }
305
306        /// Reads a 2-byte unsigned integer from the current vector using little-endian encoding
307        /// and advances the position of the cursor by two bytes.
308        pub fn read_u16(&mut self) -> Result<u16, BufferError> {
309            let size = std::mem::size_of::<u16>() as u64;
310            if self.position()? + size > self.len()? {
311                return Err(BufferError::EndOfStream);
312            }
313            let mut buffer = [0u8; 2];
314            self.reader
315                .read_exact(&mut buffer)
316                .map_err(|e| BufferError::ReadFailure(e))
317                .map(|_b| (buffer[0] as u16) | (buffer[1] as u16))
318        }
319
320        /// Reads the next byte from the current vector
321        /// and advances the current position of the cursor by one byte.
322        pub fn read_u8(&mut self) -> Result<u8, BufferError> {
323            let size = std::mem::size_of::<u8>() as u64;
324            if self.position()? + size > self.len()? {
325                return Err(BufferError::EndOfStream);
326            }
327            let mut buffer = [0u8; 1];
328            self.reader
329                .read_exact(&mut buffer)
330                .map_err(|e| BufferError::ReadFailure(e))
331                .map(|_b| buffer[0])
332        }
333
334        /// Reads the specified number of bytes from the current stream
335        /// into a byte array and advances the current position by that number of bytes.
336        pub fn read_bytes(&mut self, count: u64) -> Result<Vec<u8>, BufferError> {
337            if self.position()? + count > self.len()? {
338                return Err(BufferError::EndOfStream);
339            }
340            let mut buffer = vec![0u8; count as usize];
341            self.reader
342                .read_exact(&mut buffer)
343                .map_err(|e| BufferError::ReadFailure(e))
344                .map(|_b| buffer)
345        }
346
347        /// Reads the specified number of bytes at a pointer from the current stream
348        /// into a byte array without advancing the current position.
349        pub fn read_bytes_at(&mut self, offset: u64, count: u64) -> Result<Vec<u8>, BufferError> {
350            if offset + count > self.len()? {
351                return Err(BufferError::EndOfStream);
352            }
353            let current_pos = self.position()?;
354            self.seek(offset as i64, SeekOrigin::Begin)?;
355            let buffer = self.read_bytes(count)?;
356            self.seek(current_pos as i64, SeekOrigin::Begin)?;
357            Ok(buffer)
358        }
359    }
360
361    #[derive(Debug, thiserror::Error)]
362    pub enum BufferError {
363        #[error("seek index ({index}) was out of range. Must be non-negative and less than the size of the collection.")]
364        IndexOutOfRange { index: i64 },
365        #[error("attempted to read past the end of a stream.")]
366        EndOfStream,
367        #[error("unable to read bytes from buffer: {0:?}")]
368        ReadFailure(#[from] std::io::Error),
369        #[error("unable to write data to buffer.")]
370        IOFailure,
371    }
372}
373
374#[cfg(test)]
375mod tests {
376    #[test]
377    fn it_works() {
378        use crate::buffer::{BufferReader, BufferWriter, SeekOrigin};
379        use std::io::Cursor;
380        let mut buffer = BufferWriter::new(Cursor::new(Vec::new()));
381        buffer.write_u32(9001).unwrap();
382        buffer.write_u32(9002).unwrap();
383        buffer.write_string("Hello World!".to_string()).unwrap();
384        buffer.seek(0, SeekOrigin::Begin).unwrap();
385        buffer.write_u32(9003).unwrap();
386        let data = buffer.to_vec().unwrap();
387        let mut reader = BufferReader::new(Cursor::new(data));
388        assert_eq!(9003, reader.read_u32().unwrap());
389        assert_eq!(9002, reader.read_u32().unwrap());
390        assert_eq!("Hello World!", reader.read_string().unwrap());
391    }
392}