1use thiserror::Error;
4
5#[derive(Clone, Copy, Debug, Eq, PartialEq)]
6pub(crate) enum DecodedPageKind {
7 Leaf,
8 Internal,
9}
10
11#[derive(Clone, Copy, Debug, Eq, PartialEq)]
12pub(crate) struct DecodedPageShape {
13 pub(crate) kind: DecodedPageKind,
14 pub(crate) items: usize,
15 pub(crate) nested_bytes: u64,
16}
17
18#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
20pub struct DecodeLimits {
21 pub maximum_object_bytes: u64,
23 pub maximum_name_bytes: u32,
25 pub maximum_page_items: u32,
27 pub maximum_page_bytes: u32,
29 pub maximum_page_height: u16,
31 pub maximum_visited_pages: u32,
33}
34
35impl Default for DecodeLimits {
36 fn default() -> Self {
37 Self {
38 maximum_object_bytes: 64 * 1024 * 1024,
39 maximum_name_bytes: 255,
40 maximum_page_items: 1_024,
41 maximum_page_bytes: 256 * 1024,
42 maximum_page_height: 64,
43 maximum_visited_pages: 4_096,
44 }
45 }
46}
47
48impl DecodeLimits {
49 pub(crate) fn maximum_page_object_bytes(self) -> u64 {
50 self.maximum_object_bytes
51 .min(u64::from(self.maximum_page_bytes))
52 }
53
54 pub(crate) fn page_limits_valid(self, minimum_items: u32) -> bool {
55 self.maximum_page_items >= minimum_items
56 && self.maximum_page_bytes != 0
57 && self.maximum_page_height != 0
58 && self.maximum_visited_pages != 0
59 }
60}
61
62pub(crate) struct Encoder {
63 bytes: Vec<u8>,
64}
65
66impl Encoder {
67 pub(crate) fn new(domain: &[u8], version: u16) -> Self {
68 let mut bytes = Vec::with_capacity(domain.len() + 2);
69 bytes.extend_from_slice(domain);
70 bytes.extend_from_slice(&version.to_le_bytes());
71 Self { bytes }
72 }
73
74 pub(crate) fn with_exact_capacity(
75 domain: &[u8],
76 version: u16,
77 capacity: usize,
78 ) -> Result<Self, CanonicalDecodeError> {
79 let minimum = domain
80 .len()
81 .checked_add(2)
82 .ok_or(CanonicalDecodeError::LengthOverflow)?;
83 if capacity < minimum {
84 return Err(CanonicalDecodeError::LengthOverflow);
85 }
86 let mut bytes = Vec::new();
87 bytes
88 .try_reserve_exact(capacity)
89 .map_err(|_| CanonicalDecodeError::AllocationFailed)?;
90 bytes.extend_from_slice(domain);
91 bytes.extend_from_slice(&version.to_le_bytes());
92 Ok(Self { bytes })
93 }
94
95 pub(crate) fn u8(&mut self, value: u8) {
96 self.bytes.push(value);
97 }
98
99 pub(crate) fn u32(&mut self, value: u32) {
100 self.bytes.extend_from_slice(&value.to_le_bytes());
101 }
102
103 pub(crate) fn u64(&mut self, value: u64) {
104 self.bytes.extend_from_slice(&value.to_le_bytes());
105 }
106
107 pub(crate) fn i64(&mut self, value: i64) {
108 self.bytes.extend_from_slice(&value.to_le_bytes());
109 }
110
111 pub(crate) fn fixed(&mut self, value: &[u8]) {
112 self.bytes.extend_from_slice(value);
113 }
114
115 pub(crate) fn bounded_bytes(&mut self, value: &[u8]) -> Result<(), CanonicalDecodeError> {
116 let length =
117 u32::try_from(value.len()).map_err(|_| CanonicalDecodeError::LengthOverflow)?;
118 self.u32(length);
119 self.fixed(value);
120 Ok(())
121 }
122
123 pub(crate) fn finish(self) -> Vec<u8> {
124 self.bytes
125 }
126}
127
128pub(crate) struct Decoder<'a> {
129 bytes: &'a [u8],
130 cursor: usize,
131}
132
133impl<'a> Decoder<'a> {
134 pub(crate) fn new(
135 bytes: &'a [u8],
136 domain: &[u8],
137 expected_version: u16,
138 maximum_object_bytes: u64,
139 ) -> Result<Self, CanonicalDecodeError> {
140 let observed = u64::try_from(bytes.len()).unwrap_or(u64::MAX);
141 if observed > maximum_object_bytes {
142 return Err(CanonicalDecodeError::ObjectTooLarge {
143 observed,
144 maximum: maximum_object_bytes,
145 });
146 }
147 let header_length = domain
148 .len()
149 .checked_add(2)
150 .ok_or(CanonicalDecodeError::LengthOverflow)?;
151 let domain_prefix = bytes
152 .get(..domain.len())
153 .ok_or(CanonicalDecodeError::WrongDomain)?;
154 if bytes.len() < header_length || domain_prefix != domain {
155 return Err(CanonicalDecodeError::WrongDomain);
156 }
157 let version_bytes: [u8; 2] = bytes
158 .get(domain.len()..header_length)
159 .ok_or(CanonicalDecodeError::Truncated)?
160 .try_into()
161 .map_err(|_| CanonicalDecodeError::Truncated)?;
162 let version = u16::from_le_bytes(version_bytes);
163 if version != expected_version {
164 return Err(CanonicalDecodeError::UnsupportedVersion(version));
165 }
166 Ok(Self {
167 bytes,
168 cursor: header_length,
169 })
170 }
171
172 pub(crate) fn u8(&mut self) -> Result<u8, CanonicalDecodeError> {
173 let value = *self
174 .bytes
175 .get(self.cursor)
176 .ok_or(CanonicalDecodeError::Truncated)?;
177 self.cursor = self
178 .cursor
179 .checked_add(1)
180 .ok_or(CanonicalDecodeError::LengthOverflow)?;
181 Ok(value)
182 }
183
184 pub(crate) fn u32(&mut self) -> Result<u32, CanonicalDecodeError> {
185 let bytes: [u8; 4] = self
186 .take(4)?
187 .try_into()
188 .map_err(|_| CanonicalDecodeError::Truncated)?;
189 Ok(u32::from_le_bytes(bytes))
190 }
191
192 pub(crate) fn u64(&mut self) -> Result<u64, CanonicalDecodeError> {
193 let bytes: [u8; 8] = self
194 .take(8)?
195 .try_into()
196 .map_err(|_| CanonicalDecodeError::Truncated)?;
197 Ok(u64::from_le_bytes(bytes))
198 }
199
200 pub(crate) fn i64(&mut self) -> Result<i64, CanonicalDecodeError> {
201 let bytes: [u8; 8] = self
202 .take(8)?
203 .try_into()
204 .map_err(|_| CanonicalDecodeError::Truncated)?;
205 Ok(i64::from_le_bytes(bytes))
206 }
207
208 pub(crate) fn fixed<const N: usize>(&mut self) -> Result<[u8; N], CanonicalDecodeError> {
209 self.take(N)?
210 .try_into()
211 .map_err(|_| CanonicalDecodeError::Truncated)
212 }
213
214 pub(crate) fn bounded_bytes(&mut self, maximum: u32) -> Result<Vec<u8>, CanonicalDecodeError> {
215 let length = self.u32()?;
216 if length > maximum {
217 return Err(CanonicalDecodeError::FieldTooLarge {
218 observed: length,
219 maximum,
220 });
221 }
222 let length = usize::try_from(length).map_err(|_| CanonicalDecodeError::LengthOverflow)?;
223 let source = self.take(length)?;
224 let mut value = Vec::new();
225 value
226 .try_reserve_exact(length)
227 .map_err(|_| CanonicalDecodeError::AllocationFailed)?;
228 value.extend_from_slice(source);
229 Ok(value)
230 }
231
232 pub(crate) fn skip_bounded_bytes(
233 &mut self,
234 maximum: u32,
235 ) -> Result<usize, CanonicalDecodeError> {
236 let length = self.u32()?;
237 if length > maximum {
238 return Err(CanonicalDecodeError::FieldTooLarge {
239 observed: length,
240 maximum,
241 });
242 }
243 let length = usize::try_from(length).map_err(|_| CanonicalDecodeError::LengthOverflow)?;
244 self.take(length)?;
245 Ok(length)
246 }
247
248 pub(crate) fn take_exact(&mut self, length: usize) -> Result<&'a [u8], CanonicalDecodeError> {
249 self.take(length)
250 }
251
252 fn take(&mut self, length: usize) -> Result<&'a [u8], CanonicalDecodeError> {
253 let end = self
254 .cursor
255 .checked_add(length)
256 .ok_or(CanonicalDecodeError::LengthOverflow)?;
257 let value = self
258 .bytes
259 .get(self.cursor..end)
260 .ok_or(CanonicalDecodeError::Truncated)?;
261 self.cursor = end;
262 Ok(value)
263 }
264
265 pub(crate) fn finish(self) -> Result<(), CanonicalDecodeError> {
266 if self.cursor == self.bytes.len() {
267 Ok(())
268 } else {
269 Err(CanonicalDecodeError::TrailingBytes)
270 }
271 }
272}
273
274#[derive(Clone, Debug, Eq, Error, PartialEq)]
276pub enum CanonicalDecodeError {
277 #[error("canonical object domain is invalid")]
279 WrongDomain,
280 #[error("unsupported canonical object version {0}")]
282 UnsupportedVersion(u16),
283 #[error("canonical object is truncated")]
285 Truncated,
286 #[error("canonical object has {observed} bytes; maximum is {maximum}")]
288 ObjectTooLarge {
289 observed: u64,
291 maximum: u64,
293 },
294 #[error("canonical field has {observed} bytes; maximum is {maximum}")]
296 FieldTooLarge {
297 observed: u32,
299 maximum: u32,
301 },
302 #[error("canonical object length overflowed")]
304 LengthOverflow,
305 #[error("canonical codec allocation failed")]
307 AllocationFailed,
308 #[error("canonical object has trailing bytes")]
310 TrailingBytes,
311 #[error("unknown {field} tag {tag}")]
313 UnknownTag {
314 field: &'static str,
316 tag: u8,
318 },
319 #[error("canonical object invariant failed: {0}")]
321 Invariant(String),
322}
323
324#[cfg(test)]
325#[path = "tests/codec.rs"]
326mod tests;