From 6d86ac988c8f55306a70c81b861342d8671d3c5c Mon Sep 17 00:00:00 2001 From: Paul Schoenfelder Date: Fri, 6 Sep 2024 17:43:13 -0400 Subject: [PATCH] fix: incorrect read_slice impl for ReadAdapter This commit fixes a bug that is present in the implementation of ByteReader for ReadAdapter. Specifically, it does not consume any input, so calling `read_slice` and then attempting to read the next value in the input, will read the same bytes again. The documented behavior of this function is that any of the `read_*` methods consume the corresponding amount of input. To catch this, and to prevent future regressions, a new test was added that serializes some data to a file using one approach, and deserializes it using the ReadAdapter. This ensures that we don't accidentally make choices in the writer that aren't matched by the reader, and vice versa. Closes #308 --- utils/core/src/serde/byte_reader.rs | 35 ++++++++++++++++++++++++++++- 1 file changed, 34 insertions(+), 1 deletion(-) diff --git a/utils/core/src/serde/byte_reader.rs b/utils/core/src/serde/byte_reader.rs index 966edcfc4..cc87209b6 100644 --- a/utils/core/src/serde/byte_reader.rs +++ b/utils/core/src/serde/byte_reader.rs @@ -504,7 +504,9 @@ impl<'a> ByteReader for ReadAdapter<'a> { // this will return an error if we hit EOF first self.buffer_at_least(len)?; - Ok(&self.buffer()[0..len]) + let slice = &self.buf[self.pos..(self.pos + len)]; + self.pos += len; + Ok(slice) } #[inline] @@ -740,4 +742,35 @@ mod tests { assert_eq!(adapter.read_usize(), Ok(VALUE)); } + + #[test] + fn read_adapter_for_file() { + use crate::ByteWriter; + use std::fs::File; + + let path = std::env::temp_dir().join("read_adapter_for_file.bin"); + + // Encode some data to a buffer, then write that buffer to a file + { + let mut buf = Vec::::with_capacity(256); + buf.write_bytes(b"MAGIC\0"); + buf.write_bool(true); + buf.write_u32(0xbeef); + buf.write_usize(0xfeed); + buf.write_u16(0x5); + + std::fs::write(&path, &buf).unwrap(); + } + + // Open the file, and try to decode the encoded items + let mut file = File::open(&path).unwrap(); + let mut reader = ReadAdapter::new(&mut file); + assert_eq!(reader.peek_u8().unwrap(), b'M'); + assert_eq!(reader.read_slice(6).unwrap(), b"MAGIC\0"); + assert!(reader.read_bool().unwrap()); + assert_eq!(reader.read_u32().unwrap(), 0xbeef); + assert_eq!(reader.read_usize().unwrap(), 0xfeed); + assert_eq!(reader.read_u16().unwrap(), 0x5); + assert!(!reader.has_more_bytes(), "expected there to be no more data in the input"); + } }