1use core::convert::TryInto;
2
3use serde::{
4 de::{self, DeserializeSeed, MapAccess, SeqAccess, Visitor},
5 forward_to_deserialize_any,
6};
7
8use super::{
9 DecodeLimits, MaxMindDBError,
10 MaxMindDBError::{DecodingError, InvalidDatabaseError, ResourceLimit},
11};
12
13fn to_usize(base: u8, bytes: &[u8]) -> usize {
14 bytes.iter().fold(base as usize, |acc, &b| (acc << 8) | b as usize)
15}
16
17enum Value<'a, 'de> {
18 Bytes(&'de [u8]),
19 String(&'de str),
20 Bool(bool),
21 I32(i32),
22 U16(u16),
23 U32(u32),
24 U64(u64),
25 U128(u128),
26 F64(f64),
27 F32(f32),
28 Map(MapAccessor<'a, 'de>),
29 Array(ArrayAccess<'a, 'de>),
30}
31
32#[derive(Debug)]
41pub struct Decoder<'de> {
42 buf: &'de [u8],
43 current_ptr: usize,
44 limits: DecodeLimits,
45 depth: usize,
46 values_left: usize,
47 payload_left: usize,
48}
49
50impl<'de> Decoder<'de> {
51 pub fn new(buf: &'de [u8], start_ptr: usize) -> Decoder<'de> {
53 Decoder::with_limits(buf, start_ptr, DecodeLimits::default())
54 }
55
56 pub fn with_limits(buf: &'de [u8], start_ptr: usize, limits: DecodeLimits) -> Decoder<'de> {
61 Decoder {
62 buf,
63 current_ptr: start_ptr,
64 values_left: limits.max_values,
65 payload_left: limits.max_payload_bytes,
66 limits,
67 depth: 0,
68 }
69 }
70
71 fn ensure_available(&self, n: usize) -> DecodeResult<()> {
72 match self.current_ptr.checked_add(n) {
73 Some(end) if end <= self.buf.len() => Ok(()),
74 _ => Err(InvalidDatabaseError(format!(
75 "truncated data: expected {} bytes at offset {} but buffer length is {}",
76 n,
77 self.current_ptr,
78 self.buf.len()
79 ))),
80 }
81 }
82
83 fn eat_byte(&mut self) -> DecodeResult<u8> {
84 self.ensure_available(1)?;
85 let b = self.buf[self.current_ptr];
86 self.current_ptr += 1;
87 Ok(b)
88 }
89
90 fn size_from_ctrl_byte(&mut self, ctrl_byte: u8) -> DecodeResult<usize> {
91 let size = (ctrl_byte & 0x1f) as usize;
92
93 let bytes_to_read = size.saturating_sub(28);
94
95 self.ensure_available(bytes_to_read)?;
96 let new_offset = self.current_ptr + bytes_to_read;
97 let size_bytes = &self.buf[self.current_ptr..new_offset];
98 self.current_ptr = new_offset;
99
100 Ok(match size {
101 s if s < 29 => s,
102 29 => 29_usize + size_bytes[0] as usize,
103 30 => 285_usize + to_usize(0, size_bytes),
104 _ => 65_821_usize + to_usize(0, size_bytes),
105 })
106 }
107
108 fn size_and_type(&mut self) -> DecodeResult<(usize, u16)> {
114 let ctrl_byte = self.eat_byte()?;
115 let mut type_num = u16::from(ctrl_byte >> 5);
116 if type_num == 0 {
117 type_num = u16::from(self.eat_byte()?) + 7;
118 }
119 let size = self.size_from_ctrl_byte(ctrl_byte)?;
120 Ok((size, type_num))
121 }
122
123 fn charge_value(&mut self) -> DecodeResult<()> {
125 if self.values_left == 0 {
126 return Err(ResourceLimit(format!(
127 "decoded value count exceeded the configured limit of {}",
128 self.limits.max_values
129 )));
130 }
131 self.values_left -= 1;
132 Ok(())
133 }
134
135 fn charge_payload(&mut self, n: usize) -> DecodeResult<()> {
137 match self.payload_left.checked_sub(n) {
138 Some(rest) => {
139 self.payload_left = rest;
140 Ok(())
141 }
142 None => Err(ResourceLimit(format!(
143 "decoded string/bytes payload exceeded the configured limit of {} bytes",
144 self.limits.max_payload_bytes
145 ))),
146 }
147 }
148
149 fn enter_depth(&mut self) -> DecodeResult<()> {
152 self.depth = self.depth.saturating_add(1);
153 if self.depth > self.limits.max_depth {
154 return Err(ResourceLimit(format!(
155 "data structure nesting exceeded the configured maximum depth of {}",
156 self.limits.max_depth
157 )));
158 }
159 Ok(())
160 }
161
162 fn decode_any<V: Visitor<'de>>(&mut self, visitor: V) -> DecodeResult<V::Value> {
167 self.charge_value()?;
168 let saved_depth = self.depth;
169 self.enter_depth()?;
170 let result = self.decode_any_inner(visitor);
171 self.depth = saved_depth;
172 result
173 }
174
175 fn decode_any_inner<V: Visitor<'de>>(&mut self, visitor: V) -> DecodeResult<V::Value> {
176 let mut restore_ptr = None;
180
181 loop {
182 let (size, type_num) = self.size_and_type()?;
183
184 if type_num == 1 {
185 let target = self.decode_pointer(size)?;
186 let after_pointer = self.current_ptr;
187 if target >= self.buf.len() {
188 return Err(InvalidDatabaseError(format!(
189 "pointer at offset {} points beyond end of buffer ({})",
190 after_pointer - 1,
191 target
192 )));
193 }
194 self.enter_depth()?;
197 if restore_ptr.is_none() {
198 restore_ptr = Some(after_pointer);
199 }
200 self.current_ptr = target;
201 continue;
202 }
203
204 let value = self.decode_value(size, type_num)?;
205 let result = match value {
206 Value::Bool(x) => visitor.visit_bool(x),
207 Value::Bytes(x) => visitor.visit_borrowed_bytes(x),
208 Value::String(x) => visitor.visit_borrowed_str(x),
209 Value::I32(x) => visitor.visit_i32(x),
210 Value::U16(x) => visitor.visit_u16(x),
211 Value::U32(x) => visitor.visit_u32(x),
212 Value::U64(x) => visitor.visit_u64(x),
213 Value::U128(x) => visitor.visit_u128(x),
214 Value::F64(x) => visitor.visit_f64(x),
215 Value::F32(x) => visitor.visit_f32(x),
216 Value::Map(x) => visitor.visit_map(x),
217 Value::Array(x) => visitor.visit_seq(x),
218 };
219
220 if let Some(ptr) = restore_ptr {
221 self.current_ptr = ptr;
222 }
223 return result;
224 }
225 }
226
227 fn decode_value(&mut self, size: usize, type_num: u16) -> DecodeResult<Value<'_, 'de>> {
228 Ok(match type_num {
229 2 => Value::String(self.decode_string(size)?),
230 3 => Value::F64(self.decode_double(size)?),
231 4 => Value::Bytes(self.decode_bytes(size)?),
232 5 => Value::U16(self.decode_uint16(size)?),
233 6 => Value::U32(self.decode_uint32(size)?),
234 7 => self.decode_map(size)?,
235 8 => Value::I32(self.decode_int(size)?),
236 9 => Value::U64(self.decode_uint64(size)?),
237 10 => Value::U128(self.decode_uint128(size)?),
238 11 => self.decode_array(size)?,
239 14 => Value::Bool(self.decode_bool(size)?),
240 15 => Value::F32(self.decode_float(size)?),
241 u => return Err(InvalidDatabaseError(format!("Unknown data type: {u:?}"))),
242 })
243 }
244
245 fn decode_array(&mut self, size: usize) -> DecodeResult<Value<'_, 'de>> {
246 if size > self.values_left {
249 return Err(ResourceLimit(format!(
250 "array of {size} entries exceeds the remaining decoded value budget of {}",
251 self.values_left
252 )));
253 }
254 Ok(Value::Array(ArrayAccess {
255 de: self,
256 count: size,
257 }))
258 }
259
260 fn decode_bool(&mut self, size: usize) -> DecodeResult<bool> {
261 match size {
262 0 | 1 => Ok(size != 0),
263 s => Err(InvalidDatabaseError(format!("bool of size {s:?}"))),
264 }
265 }
266
267 fn decode_bytes(&mut self, size: usize) -> DecodeResult<&'de [u8]> {
268 self.charge_payload(size)?;
269 let new_offset = self
270 .current_ptr
271 .checked_add(size)
272 .ok_or_else(|| InvalidDatabaseError(format!("bytes length {size} overflows the buffer offset")))?;
273 self.ensure_available(size)?;
274 let u8_slice = &self.buf[self.current_ptr..new_offset];
275 self.current_ptr = new_offset;
276
277 Ok(u8_slice)
278 }
279
280 fn decode_float(&mut self, size: usize) -> DecodeResult<f32> {
281 self.ensure_available(size)?;
282 let new_offset = self.current_ptr + size;
283 let value: [u8; 4] = self.buf[self.current_ptr..new_offset]
284 .try_into()
285 .map_err(|_| InvalidDatabaseError(format!("float of size {:?}", new_offset - self.current_ptr)))?;
286 self.current_ptr = new_offset;
287 let float_value = f32::from_be_bytes(value);
288 Ok(float_value)
289 }
290
291 fn decode_double(&mut self, size: usize) -> DecodeResult<f64> {
292 self.ensure_available(size)?;
293 let new_offset = self.current_ptr + size;
294 let value: [u8; 8] = self.buf[self.current_ptr..new_offset]
295 .try_into()
296 .map_err(|_| InvalidDatabaseError(format!("double of size {:?}", new_offset - self.current_ptr)))?;
297 self.current_ptr = new_offset;
298 let float_value = f64::from_be_bytes(value);
299 Ok(float_value)
300 }
301
302 fn decode_uint64(&mut self, size: usize) -> DecodeResult<u64> {
303 match size {
304 s if s <= 8 => {
305 self.ensure_available(size)?;
306 let new_offset = self.current_ptr + size;
307
308 let value = self.buf[self.current_ptr..new_offset]
309 .iter()
310 .fold(0_u64, |acc, &b| (acc << 8) | u64::from(b));
311 self.current_ptr = new_offset;
312 Ok(value)
313 }
314 s => Err(InvalidDatabaseError(format!("u64 of size {s:?}"))),
315 }
316 }
317
318 fn decode_uint128(&mut self, size: usize) -> DecodeResult<u128> {
319 match size {
320 s if s <= 16 => {
321 self.ensure_available(size)?;
322 let new_offset = self.current_ptr + size;
323
324 let value = self.buf[self.current_ptr..new_offset]
325 .iter()
326 .fold(0_u128, |acc, &b| (acc << 8) | u128::from(b));
327 self.current_ptr = new_offset;
328 Ok(value)
329 }
330 s => Err(InvalidDatabaseError(format!("u128 of size {s:?}"))),
331 }
332 }
333
334 fn decode_uint32(&mut self, size: usize) -> DecodeResult<u32> {
335 match size {
336 s if s <= 4 => {
337 self.ensure_available(size)?;
338 let new_offset = self.current_ptr + size;
339
340 let value = self.buf[self.current_ptr..new_offset]
341 .iter()
342 .fold(0_u32, |acc, &b| (acc << 8) | u32::from(b));
343 self.current_ptr = new_offset;
344 Ok(value)
345 }
346 s => Err(InvalidDatabaseError(format!("u32 of size {s:?}"))),
347 }
348 }
349
350 fn decode_uint16(&mut self, size: usize) -> DecodeResult<u16> {
351 match size {
352 s if s <= 2 => {
353 self.ensure_available(size)?;
354 let new_offset = self.current_ptr + size;
355
356 let value = self.buf[self.current_ptr..new_offset]
357 .iter()
358 .fold(0_u16, |acc, &b| (acc << 8) | u16::from(b));
359 self.current_ptr = new_offset;
360 Ok(value)
361 }
362 s => Err(InvalidDatabaseError(format!("u16 of size {s:?}"))),
363 }
364 }
365
366 fn decode_int(&mut self, size: usize) -> DecodeResult<i32> {
367 match size {
368 s if s <= 4 => {
369 self.ensure_available(size)?;
370 let new_offset = self.current_ptr + size;
371
372 let value = self.buf[self.current_ptr..new_offset]
373 .iter()
374 .fold(0_i32, |acc, &b| (acc << 8) | i32::from(b));
375 self.current_ptr = new_offset;
376 Ok(value)
377 }
378 s => Err(InvalidDatabaseError(format!("int32 of size {s:?}"))),
379 }
380 }
381
382 fn decode_map(&mut self, size: usize) -> DecodeResult<Value<'_, 'de>> {
383 let entries = size
384 .checked_mul(2)
385 .ok_or_else(|| InvalidDatabaseError("map size overflow".to_owned()))?;
386 if entries > self.values_left {
390 return Err(ResourceLimit(format!(
391 "map of {size} entries exceeds the remaining decoded value budget of {}",
392 self.values_left
393 )));
394 }
395 Ok(Value::Map(MapAccessor {
396 de: self,
397 count: entries,
398 }))
399 }
400
401 fn decode_pointer(&mut self, size: usize) -> DecodeResult<usize> {
402 let pointer_value_offset = [0, 0, 2048, 526_336, 0];
403 let pointer_size = ((size >> 3) & 0x3) + 1;
404 self.ensure_available(pointer_size)?;
405 let new_offset = self.current_ptr + pointer_size;
406 let pointer_bytes = &self.buf[self.current_ptr..new_offset];
407 self.current_ptr = new_offset;
408
409 let base = if pointer_size == 4 { 0 } else { (size & 0x7) as u8 };
410 let unpacked = to_usize(base, pointer_bytes);
411
412 Ok(unpacked + pointer_value_offset[pointer_size])
413 }
414
415 fn decode_string(&mut self, size: usize) -> DecodeResult<&'de str> {
416 use std::str::from_utf8;
417
418 self.charge_payload(size)?;
419 let new_offset = self
420 .current_ptr
421 .checked_add(size)
422 .ok_or_else(|| InvalidDatabaseError(format!("string length {size} overflows the buffer offset")))?;
423 self.ensure_available(size)?;
424 let bytes = &self.buf[self.current_ptr..new_offset];
425 self.current_ptr = new_offset;
426 match from_utf8(bytes) {
427 Ok(v) => Ok(v),
428 Err(_) => Err(InvalidDatabaseError("error decoding string".to_owned())),
429 }
430 }
431}
432
433pub type DecodeResult<T> = Result<T, MaxMindDBError>;
434
435impl<'de: 'a, 'a> de::Deserializer<'de> for &'a mut Decoder<'de> {
436 type Error = MaxMindDBError;
437
438 fn deserialize_any<V>(self, visitor: V) -> DecodeResult<V::Value>
439 where
440 V: Visitor<'de>,
441 {
442 self.decode_any(visitor)
443 }
444
445 fn deserialize_option<V>(self, visitor: V) -> DecodeResult<V::Value>
446 where
447 V: Visitor<'de>,
448 {
449 visitor.visit_some(self)
450 }
451
452 forward_to_deserialize_any! {
453 bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
454 bytes byte_buf unit unit_struct newtype_struct seq tuple
455 tuple_struct map struct enum identifier ignored_any
456 }
457}
458
459struct ArrayAccess<'a, 'de: 'a> {
460 de: &'a mut Decoder<'de>,
461 count: usize,
462}
463
464impl<'de, 'a> SeqAccess<'de> for ArrayAccess<'a, 'de> {
465 type Error = MaxMindDBError;
466
467 fn next_element_seed<T>(&mut self, seed: T) -> DecodeResult<Option<T::Value>>
468 where
469 T: DeserializeSeed<'de>,
470 {
471 if self.count == 0 {
472 return Ok(None);
473 }
474 self.count -= 1;
475
476 seed.deserialize(&mut *self.de).map(Some)
477 }
478}
479
480struct MapAccessor<'a, 'de: 'a> {
481 de: &'a mut Decoder<'de>,
482 count: usize,
483}
484
485impl<'de, 'a> MapAccess<'de> for MapAccessor<'a, 'de> {
486 type Error = MaxMindDBError;
487
488 fn next_key_seed<K>(&mut self, seed: K) -> DecodeResult<Option<K::Value>>
489 where
490 K: DeserializeSeed<'de>,
491 {
492 if self.count == 0 {
493 return Ok(None);
494 }
495 self.count -= 1;
496
497 seed.deserialize(&mut *self.de).map(Some)
498 }
499
500 fn next_value_seed<V>(&mut self, seed: V) -> DecodeResult<V::Value>
501 where
502 V: DeserializeSeed<'de>,
503 {
504 if self.count == 0 {
505 return Err(DecodingError("no more entries".to_owned()));
506 }
507 self.count -= 1;
508
509 seed.deserialize(&mut *self.de)
510 }
511}