1use core::fmt;
4
5#[derive(Clone, Copy, Debug, Eq, PartialEq)]
7pub enum ByteErrorKind {
8 Truncated,
10 LengthOverflow,
12 BudgetExceeded,
14 OverlongModifiedUtf8,
16 IllegalZero,
18 InvalidModifiedUtf8,
20 MalformedSurrogate,
22}
23
24#[derive(Clone, Debug, Eq, PartialEq)]
26pub struct ByteError {
27 pub kind: ByteErrorKind,
29 pub offset: usize,
31 pub message: String,
33}
34
35impl ByteError {
36 pub(crate) fn new(kind: ByteErrorKind, offset: usize, message: impl Into<String>) -> Self {
37 Self {
38 kind,
39 offset,
40 message: message.into(),
41 }
42 }
43}
44
45impl fmt::Display for ByteError {
46 fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
47 write!(formatter, "{} at byte {}", self.message, self.offset)
48 }
49}
50
51impl std::error::Error for ByteError {}
52
53#[derive(Clone, Debug)]
55pub struct ByteReader<'a> {
56 bytes: &'a [u8],
57 position: usize,
58 origin: usize,
59 allocation_budget: usize,
60}
61
62impl<'a> ByteReader<'a> {
63 pub fn new(bytes: &'a [u8], allocation_budget: usize) -> Self {
65 Self {
66 bytes,
67 position: 0,
68 origin: 0,
69 allocation_budget,
70 }
71 }
72
73 fn with_origin(bytes: &'a [u8], allocation_budget: usize, origin: usize) -> Self {
74 Self {
75 bytes,
76 position: 0,
77 origin,
78 allocation_budget,
79 }
80 }
81
82 pub fn offset(&self) -> usize {
84 self.origin + self.position
85 }
86
87 pub fn remaining(&self) -> usize {
89 self.bytes.len() - self.position
90 }
91
92 pub fn allocation_budget(&self) -> usize {
94 self.allocation_budget
95 }
96
97 pub fn preflight_allocation(&self, amount: usize) -> Result<(), ByteError> {
99 if amount > self.allocation_budget {
100 return Err(ByteError::new(
101 ByteErrorKind::BudgetExceeded,
102 self.offset(),
103 format!(
104 "declared allocation {amount} exceeds budget {}",
105 self.allocation_budget
106 ),
107 ));
108 }
109 Ok(())
110 }
111
112 pub fn read_u1(&mut self) -> Result<u8, ByteError> {
114 Ok(self.take(1)?[0])
115 }
116
117 pub fn read_u2(&mut self) -> Result<u16, ByteError> {
119 let value: [u8; 2] = self.take(2)?.try_into().expect("exact length");
120 Ok(u16::from_be_bytes(value))
121 }
122
123 pub fn read_u4(&mut self) -> Result<u32, ByteError> {
125 let value: [u8; 4] = self.take(4)?.try_into().expect("exact length");
126 Ok(u32::from_be_bytes(value))
127 }
128
129 pub fn take(&mut self, length: usize) -> Result<&'a [u8], ByteError> {
131 let start = self.position;
132 let end = start.checked_add(length).ok_or_else(|| {
133 ByteError::new(
134 ByteErrorKind::LengthOverflow,
135 self.offset(),
136 "byte length overflow",
137 )
138 })?;
139 let result = self.bytes.get(start..end).ok_or_else(|| {
140 ByteError::new(
141 ByteErrorKind::Truncated,
142 self.origin + self.bytes.len(),
143 format!("needed {length} bytes, only {} remain", self.remaining()),
144 )
145 })?;
146 self.position = end;
147 Ok(result)
148 }
149
150 pub fn sub_reader(&mut self, length: usize) -> Result<ByteReader<'a>, ByteError> {
152 let origin = self.offset();
153 let bytes = self.take(length)?;
154 Ok(Self::with_origin(bytes, self.allocation_budget, origin))
155 }
156}
157
158#[derive(Clone, Debug)]
160pub struct ByteWriter {
161 bytes: Vec<u8>,
162 budget: usize,
163}
164
165impl ByteWriter {
166 pub fn new(budget: usize) -> Self {
168 Self {
169 bytes: Vec::new(),
170 budget,
171 }
172 }
173
174 fn reserve_for(&mut self, additional: usize) -> Result<(), ByteError> {
175 let target = self.bytes.len().checked_add(additional).ok_or_else(|| {
176 ByteError::new(
177 ByteErrorKind::LengthOverflow,
178 self.bytes.len(),
179 "output length overflow",
180 )
181 })?;
182 if target > self.budget {
183 return Err(ByteError::new(
184 ByteErrorKind::BudgetExceeded,
185 self.bytes.len(),
186 format!("output length {target} exceeds budget {}", self.budget),
187 ));
188 }
189 self.bytes.try_reserve_exact(additional).map_err(|error| {
190 ByteError::new(
191 ByteErrorKind::BudgetExceeded,
192 self.bytes.len(),
193 format!("output allocation failed: {error}"),
194 )
195 })
196 }
197
198 pub fn write_u1(&mut self, value: u8) -> Result<(), ByteError> {
200 self.write_bytes(&[value])
201 }
202 pub fn write_u2(&mut self, value: u16) -> Result<(), ByteError> {
204 self.write_bytes(&value.to_be_bytes())
205 }
206 pub fn write_u4(&mut self, value: u32) -> Result<(), ByteError> {
208 self.write_bytes(&value.to_be_bytes())
209 }
210 pub fn write_bytes(&mut self, value: &[u8]) -> Result<(), ByteError> {
212 self.reserve_for(value.len())?;
213 self.bytes.extend_from_slice(value);
214 Ok(())
215 }
216 pub fn as_slice(&self) -> &[u8] {
218 &self.bytes
219 }
220 pub fn into_bytes(self) -> Vec<u8> {
222 self.bytes
223 }
224}