1use std::fmt;
4
5#[derive(Debug, Clone, PartialEq, Eq)]
7pub struct Error {
8 pub offset: usize,
10 pub message: String,
12}
13
14impl fmt::Display for Error {
15 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
16 write!(formatter, "{} at byte {}", self.message, self.offset)
17 }
18}
19impl std::error::Error for Error {}
20
21pub type Result<T> = std::result::Result<T, Error>;
23
24pub struct Reader<'a> {
26 bytes: &'a [u8],
27 pub offset: usize,
29}
30
31impl<'a> Reader<'a> {
32 pub fn new(bytes: &'a [u8]) -> Self {
34 Self { bytes, offset: 0 }
35 }
36 pub fn remaining(&self) -> usize {
38 self.bytes.len() - self.offset
39 }
40 pub fn raw(&mut self, size: usize) -> Result<&'a [u8]> {
42 if size > self.remaining() {
43 return self.fail("Truncated record");
44 }
45 let start = self.offset;
46 self.offset += size;
47 Ok(&self.bytes[start..self.offset])
48 }
49 pub fn fail<T>(&self, message: impl Into<String>) -> Result<T> {
51 Err(Error {
52 offset: self.offset,
53 message: message.into(),
54 })
55 }
56 pub fn u8(&mut self) -> Result<u8> {
58 Ok(self.raw(1)?[0])
59 }
60 pub fn i8(&mut self) -> Result<i8> {
62 Ok(self.u8()? as i8)
63 }
64 pub fn u16(&mut self) -> Result<u16> {
66 let bytes = self.raw(2)?;
67 Ok(u16::from_le_bytes([bytes[0], bytes[1]]))
68 }
69 pub fn i16(&mut self) -> Result<i16> {
71 Ok(self.u16()? as i16)
72 }
73 pub fn u32(&mut self) -> Result<u32> {
75 let bytes = self.raw(4)?;
76 Ok(u32::from_le_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]))
77 }
78 pub fn i32(&mut self) -> Result<i32> {
80 Ok(self.u32()? as i32)
81 }
82 pub fn f32(&mut self) -> Result<f32> {
84 Ok(f32::from_bits(self.u32()?))
85 }
86 pub fn count(&mut self, maximum: usize, stride: usize) -> Result<usize> {
88 let value = self.i32()?;
89 if value < 0 {
90 return self.fail("Negative count");
91 }
92 let count = value as usize;
93 if count > maximum
94 || count
95 .checked_mul(stride)
96 .is_none_or(|size| size > self.remaining())
97 {
98 return self.fail("Invalid count or truncated array");
99 }
100 Ok(count)
101 }
102 pub fn string(&mut self, maximum: usize) -> Result<Vec<u8>> {
104 let size = self.count(maximum, 1)?;
105 Ok(self.raw(size)?.to_vec())
106 }
107 pub fn end(&self) -> Result<()> {
109 if self.remaining() == 0 {
110 Ok(())
111 } else {
112 self.fail("Trailing bytes")
113 }
114 }
115}
116
117pub struct Writer {
119 bytes: Vec<u8>,
120 maximum: usize,
121}
122
123impl Default for Writer {
124 fn default() -> Self {
125 Self::new(256 * 1024 * 1024)
126 }
127}
128
129impl Writer {
130 pub fn new(maximum: usize) -> Self {
132 Self {
133 bytes: Vec::new(),
134 maximum,
135 }
136 }
137 pub fn raw(&mut self, bytes: &[u8]) -> Result<()> {
139 if bytes.len() > self.maximum.saturating_sub(self.bytes.len()) {
140 return Err(Error {
141 offset: self.bytes.len(),
142 message: "Output byte budget exceeded".into(),
143 });
144 }
145 self.bytes.try_reserve(bytes.len()).map_err(|_| Error {
146 offset: self.bytes.len(),
147 message: "Allocation failed".into(),
148 })?;
149 self.bytes.extend_from_slice(bytes);
150 Ok(())
151 }
152 pub fn u8(&mut self, value: u8) -> Result<()> {
154 self.raw(&[value])
155 }
156 pub fn i8(&mut self, value: i8) -> Result<()> {
158 self.u8(value as u8)
159 }
160 pub fn u16(&mut self, value: u16) -> Result<()> {
162 self.raw(&value.to_le_bytes())
163 }
164 pub fn i16(&mut self, value: i16) -> Result<()> {
166 self.raw(&value.to_le_bytes())
167 }
168 pub fn u32(&mut self, value: u32) -> Result<()> {
170 self.raw(&value.to_le_bytes())
171 }
172 pub fn i32(&mut self, value: i32) -> Result<()> {
174 self.raw(&value.to_le_bytes())
175 }
176 pub fn f32(&mut self, value: f32) -> Result<()> {
178 self.u32(value.to_bits())
179 }
180 pub fn string(&mut self, bytes: &[u8]) -> Result<()> {
182 let length = i32::try_from(bytes.len()).map_err(|_| Error {
183 offset: self.bytes.len(),
184 message: "String too long".into(),
185 })?;
186 self.i32(length)?;
187 self.raw(bytes)
188 }
189 pub fn finish(self) -> Vec<u8> {
191 self.bytes
192 }
193}
194
195#[cfg(test)]
196mod tests {
197 use super::*;
198
199 #[test]
200 fn bit_exact_and_bounded() -> Result<()> {
201 let mut writer = Writer::default();
202 writer.i32(-17)?;
203 writer.u32(0x7fa12345)?;
204 writer.string(&[0, 255, 128])?;
205 let bytes = writer.finish();
206 let mut reader = Reader::new(&bytes);
207 assert_eq!(reader.i32()?, -17);
208 assert_eq!(reader.u32()?, 0x7fa12345);
209 assert_eq!(reader.string(100)?, [0, 255, 128]);
210 reader.end()?;
211 assert!(reader.u8().is_err());
212 assert!(Reader::new(&[255; 4]).count(100, 1).is_err());
213 assert!(Writer::new(2).u32(1).is_err());
214 Ok(())
215 }
216}