Skip to main content

reifydb_codec/key/
deserializer.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2026 ReifyDB
3
4use arrow_buffer::i256;
5use reifydb_value::{
6	Result,
7	error::{Error, TypeError},
8	value::{
9		Value,
10		blob::Blob,
11		constraint::precision::Precision,
12		date::Date,
13		datetime::DateTime,
14		decimal::Decimal,
15		dictionary::DictionaryEntryId,
16		duration::Duration,
17		identity::IdentityId,
18		ordered_f32::OrderedF32,
19		ordered_f64::OrderedF64,
20		time::Time,
21		uuid::{Uuid4, Uuid7},
22	},
23};
24use uuid::Uuid;
25
26use super::{
27	CONTAINER_END, decode_bool, decode_f32, decode_f64, decode_fixed, decode_i8, decode_i16, decode_i32,
28	decode_i64, decode_i128, decode_i256, decode_u8, decode_u16, decode_u32, decode_u64, decode_u128,
29	decode_u128_varint,
30};
31use crate::{
32	error::DecodeError,
33	tag::{TypeTag, ValueKind},
34	unscaled::{NARROW, check_unscaled, decode_params, width},
35};
36
37pub struct KeyDeserializer<'a> {
38	buffer: &'a [u8],
39	position: usize,
40}
41
42impl<'a> KeyDeserializer<'a> {
43	pub fn from_bytes(buffer: &'a [u8]) -> Self {
44		Self {
45			buffer,
46			position: 0,
47		}
48	}
49
50	pub fn remaining(&self) -> usize {
51		self.buffer.len().saturating_sub(self.position)
52	}
53
54	pub fn is_empty(&self) -> bool {
55		self.remaining() == 0
56	}
57
58	pub fn position(&self) -> usize {
59		self.position
60	}
61
62	pub fn remaining_bytes(&self) -> &'a [u8] {
63		&self.buffer[self.position..]
64	}
65
66	fn read_exact(&mut self, count: usize) -> Result<&'a [u8]> {
67		if self.remaining() < count {
68			return Err(Error::from(TypeError::SerdeKeycode {
69				message: format!(
70					"unexpected end of key at position {}: need {} bytes, have {}",
71					self.position,
72					count,
73					self.remaining()
74				),
75			}));
76		}
77		let start = self.position;
78		self.position += count;
79		Ok(&self.buffer[start..self.position])
80	}
81
82	pub fn read_bool(&mut self) -> Result<bool> {
83		let bytes = self.read_exact(1)?;
84		decode_bool(bytes[0])
85	}
86
87	pub fn read_f32(&mut self) -> Result<f32> {
88		let bytes = self.read_exact(4)?;
89		Ok(decode_f32(bytes.try_into()?))
90	}
91
92	pub fn read_f64(&mut self) -> Result<f64> {
93		let bytes = self.read_exact(8)?;
94		Ok(decode_f64(bytes.try_into()?))
95	}
96
97	pub fn read_i8(&mut self) -> Result<i8> {
98		let bytes = self.read_exact(1)?;
99		Ok(decode_i8(bytes.try_into()?))
100	}
101
102	pub fn read_i16(&mut self) -> Result<i16> {
103		let bytes = self.read_exact(2)?;
104		Ok(decode_i16(bytes.try_into()?))
105	}
106
107	pub fn read_i32(&mut self) -> Result<i32> {
108		let bytes = self.read_exact(4)?;
109		Ok(decode_i32(bytes.try_into()?))
110	}
111
112	pub fn read_i64(&mut self) -> Result<i64> {
113		let bytes = self.read_exact(8)?;
114		Ok(decode_i64(bytes.try_into()?))
115	}
116
117	pub fn read_i128(&mut self) -> Result<i128> {
118		let bytes = self.read_exact(16)?;
119		Ok(decode_i128(bytes.try_into()?))
120	}
121
122	pub fn read_u8(&mut self) -> Result<u8> {
123		let bytes = self.read_exact(1)?;
124		Ok(decode_u8(bytes[0]))
125	}
126
127	pub fn read_u16(&mut self) -> Result<u16> {
128		let bytes = self.read_exact(2)?;
129		Ok(decode_u16(bytes.try_into()?))
130	}
131
132	pub fn read_u32(&mut self) -> Result<u32> {
133		let bytes = self.read_exact(4)?;
134		Ok(decode_u32(bytes.try_into()?))
135	}
136
137	pub fn read_u64(&mut self) -> Result<u64> {
138		let bytes = self.read_exact(8)?;
139		Ok(decode_u64(bytes.try_into()?))
140	}
141
142	pub fn read_u128(&mut self) -> Result<u128> {
143		let bytes = self.read_exact(16)?;
144		Ok(decode_u128(bytes.try_into()?))
145	}
146
147	pub fn read_fixed<const N: usize>(&mut self) -> Result<[u8; N]> {
148		let bytes = self.read_exact(N)?;
149		Ok(decode_fixed(bytes.try_into()?))
150	}
151
152	pub fn read_u128_varint(&mut self) -> Result<u128> {
153		let mut slice = &self.buffer[self.position..];
154		let u = decode_u128_varint(&mut slice)?;
155		self.position = self.buffer.len() - slice.len();
156		Ok(u)
157	}
158
159	pub fn read_bytes(&mut self) -> Result<Vec<u8>> {
160		let mut result = Vec::new();
161		loop {
162			if self.remaining() < 1 {
163				return Err(Error::from(TypeError::SerdeKeycode {
164					message: format!(
165						"unexpected end of key at position {}: bytes not terminated",
166						self.position
167					),
168				}));
169			}
170			let byte = self.buffer[self.position];
171			self.position += 1;
172
173			if byte == 0xff {
174				if self.remaining() < 1 {
175					return Err(Error::from(TypeError::SerdeKeycode {
176						message: format!(
177							"unexpected end of key at position {}: incomplete escape sequence",
178							self.position
179						),
180					}));
181				}
182				let next_byte = self.buffer[self.position];
183				self.position += 1;
184
185				if next_byte == 0x00 {
186					result.push(0x00);
187				} else if next_byte == 0xff {
188					break;
189				} else {
190					return Err(Error::from(TypeError::SerdeKeycode {
191						message: format!(
192							"invalid escape sequence at position {}: 0xff 0x{:02x}",
193							self.position - 1,
194							next_byte
195						),
196					}));
197				}
198			} else {
199				result.push(!byte);
200			}
201		}
202		Ok(result)
203	}
204
205	pub fn read_str(&mut self) -> Result<String> {
206		let bytes = self.read_bytes()?;
207		String::from_utf8(bytes).map_err(|e| {
208			Error::from(TypeError::SerdeKeycode {
209				message: format!("invalid UTF-8 in key at position {}: {}", self.position, e),
210			})
211		})
212	}
213
214	pub fn read_date(&mut self) -> Result<Date> {
215		let days = self.read_i32()?;
216		Date::from_days_since_epoch(days).ok_or_else(|| {
217			Error::from(TypeError::SerdeKeycode {
218				message: format!(
219					"invalid date at position {}: {} days since epoch",
220					self.position, days
221				),
222			})
223		})
224	}
225
226	pub fn read_datetime(&mut self) -> Result<DateTime> {
227		let nanos = self.read_i64()?;
228		Ok(DateTime::from_nanos(nanos))
229	}
230
231	pub fn read_time(&mut self) -> Result<Time> {
232		let nanos = self.read_u64()?;
233		Time::from_nanos_since_midnight(nanos).ok_or_else(|| {
234			Error::from(TypeError::SerdeKeycode {
235				message: format!(
236					"invalid time at position {}: {} nanos since midnight",
237					self.position, nanos
238				),
239			})
240		})
241	}
242
243	pub fn read_duration(&mut self) -> Result<Duration> {
244		let months = self.read_i32()?;
245		let days = self.read_i32()?;
246		let nanos = self.read_i64()?;
247		Ok(Duration::new(months, days, nanos)?)
248	}
249
250	pub fn read_identity_id(&mut self) -> Result<IdentityId> {
251		let bytes = self.read_bytes()?;
252		let uuid = Uuid::from_slice(&bytes).map_err(|e| {
253			Error::from(TypeError::SerdeKeycode {
254				message: format!("invalid IdentityId at position {}: {}", self.position, e),
255			})
256		})?;
257		let version = uuid.get_version_num();
258		if version != 7 && version != 0 {
259			return Err(Error::from(TypeError::SerdeKeycode {
260				message: format!(
261					"invalid IdentityId version {} at position {}",
262					version, self.position
263				),
264			}));
265		}
266		Ok(IdentityId::from(Uuid7::from(uuid)))
267	}
268
269	pub fn read_uuid4(&mut self) -> Result<Uuid4> {
270		let bytes = self.read_bytes()?;
271		let uuid = Uuid::from_slice(&bytes).map_err(|e| {
272			Error::from(TypeError::SerdeKeycode {
273				message: format!("invalid Uuid4 at position {}: {}", self.position, e),
274			})
275		})?;
276		let version = uuid.get_version_num();
277		if version != 4 && version != 0 {
278			return Err(Error::from(TypeError::SerdeKeycode {
279				message: format!("invalid Uuid4 version {} at position {}", version, self.position),
280			}));
281		}
282		Ok(Uuid4::from(uuid))
283	}
284
285	pub fn read_uuid7(&mut self) -> Result<Uuid7> {
286		let bytes = self.read_bytes()?;
287		let uuid = Uuid::from_slice(&bytes).map_err(|e| {
288			Error::from(TypeError::SerdeKeycode {
289				message: format!("invalid Uuid7 at position {}: {}", self.position, e),
290			})
291		})?;
292		let version = uuid.get_version_num();
293		if version != 7 && version != 0 {
294			return Err(Error::from(TypeError::SerdeKeycode {
295				message: format!("invalid Uuid7 version {} at position {}", version, self.position),
296			}));
297		}
298		Ok(Uuid7::from(uuid))
299	}
300
301	pub fn read_blob(&mut self) -> Result<Blob> {
302		let bytes = self.read_bytes()?;
303		Ok(Blob::from(bytes))
304	}
305
306	pub fn read_decimal(&mut self) -> Result<Decimal> {
307		let precision = self.read_u8()?;
308		let scale = self.read_u8()?;
309		let unscaled = self.read_unscaled(ValueKind::Decimal, precision, scale)?;
310		Ok(Decimal::from_parts(unscaled, scale).expect("a checked unscaled value is within 76 digits"))
311	}
312
313	fn read_unscaled(&mut self, kind: ValueKind, precision: u8, scale: u8) -> Result<i256> {
314		let position = self.position;
315		let (precision, _) =
316			decode_params(precision, scale).map_err(|error| unscaled_error(position, error))?;
317		let unscaled = self.read_payload(precision)?;
318		check_unscaled(kind, unscaled, precision).map_err(|error| unscaled_error(position, error))
319	}
320
321	fn read_payload(&mut self, precision: Precision) -> Result<i256> {
322		if width(precision) == NARROW {
323			Ok(i256::from_i128(self.read_i128()?))
324		} else {
325			let bytes = self.read_exact(32)?;
326			Ok(decode_i256(bytes.try_into()?))
327		}
328	}
329
330	fn at_container_end(&mut self) -> Result<bool> {
331		if self.remaining() < 1 {
332			return Err(Error::from(TypeError::SerdeKeycode {
333				message: format!(
334					"unexpected end of key at position {}: container not terminated",
335					self.position
336				),
337			}));
338		}
339		if self.buffer[self.position] == CONTAINER_END {
340			self.position += 1;
341			return Ok(true);
342		}
343		Ok(false)
344	}
345
346	fn read_container_items(&mut self) -> Result<Vec<Value>> {
347		let mut items = Vec::new();
348		while !self.at_container_end()? {
349			items.push(self.read_value()?);
350		}
351		Ok(items)
352	}
353
354	fn read_record_fields(&mut self) -> Result<Vec<(String, Value)>> {
355		let mut fields = Vec::new();
356		while !self.at_container_end()? {
357			let name = self.read_str()?;
358			fields.push((name, self.read_value()?));
359		}
360		Ok(fields)
361	}
362
363	pub fn read_value(&mut self) -> Result<Value> {
364		if self.remaining() < 1 {
365			return Err(Error::from(TypeError::SerdeKeycode {
366				message: format!(
367					"unexpected end of key at position {}: cannot read value type",
368					self.position
369				),
370			}));
371		}
372
373		let type_marker = self.buffer[self.position];
374		self.position += 1;
375
376		let kind = ValueKind::from_byte(type_marker).ok_or_else(|| {
377			Error::from(TypeError::SerdeKeycode {
378				message: format!(
379					"unknown value type marker 0x{:02x} at position {}",
380					type_marker,
381					self.position - 1
382				),
383			})
384		})?;
385
386		match kind {
387			ValueKind::None => {
388				if self.remaining() < 1 {
389					return Ok(Value::none());
390				}
391				let inner_marker = self.buffer[self.position];
392				self.position += 1;
393				let inner = TypeTag::from_byte(inner_marker)
394					.map_err(|e| {
395						Error::from(TypeError::SerdeKeycode {
396							message: format!(
397								"invalid none inner type byte 0x{:02x} at position {}: {}",
398								inner_marker,
399								self.position - 1,
400								e
401							),
402						})
403					})?
404					.to_type()
405					.map_err(|e| {
406						Error::from(TypeError::SerdeKeycode {
407							message: format!(
408								"invalid none inner type byte 0x{:02x} at position {}: {}",
409								inner_marker,
410								self.position - 1,
411								e
412							),
413						})
414					})?;
415				Ok(Value::none_of(inner))
416			}
417			ValueKind::Float4 => {
418				let f = self.read_f32()?;
419				Ok(Value::Float4(OrderedF32::try_from(f).map_err(|e| {
420					Error::from(TypeError::SerdeKeycode {
421						message: format!("invalid f32 at position {}: {}", self.position, e),
422					})
423				})?))
424			}
425			ValueKind::Float8 => {
426				let f = self.read_f64()?;
427				Ok(Value::Float8(OrderedF64::try_from(f).map_err(|e| {
428					Error::from(TypeError::SerdeKeycode {
429						message: format!("invalid f64 at position {}: {}", self.position, e),
430					})
431				})?))
432			}
433			ValueKind::Boolean => Ok(Value::Boolean(self.read_bool()?)),
434			ValueKind::Int1 => Ok(Value::Int1(self.read_i8()?)),
435			ValueKind::Int2 => Ok(Value::Int2(self.read_i16()?)),
436			ValueKind::Int4 => Ok(Value::Int4(self.read_i32()?)),
437			ValueKind::Int8 => Ok(Value::Int8(self.read_i64()?)),
438			ValueKind::Int16 => Ok(Value::Int16(self.read_i128()?)),
439			ValueKind::Utf8 => Ok(Value::Utf8(self.read_str()?)),
440			ValueKind::Uint1 => Ok(Value::Uint1(self.read_u8()?)),
441			ValueKind::Uint2 => Ok(Value::Uint2(self.read_u16()?)),
442			ValueKind::Uint4 => Ok(Value::Uint4(self.read_u32()?)),
443			ValueKind::Uint8 => Ok(Value::Uint8(self.read_u64()?)),
444			ValueKind::Uint16 => Ok(Value::Uint16(self.read_u128()?)),
445			ValueKind::Date => Ok(Value::Date(self.read_date()?)),
446			ValueKind::DateTime => Ok(Value::DateTime(self.read_datetime()?)),
447			ValueKind::Time => Ok(Value::Time(self.read_time()?)),
448			ValueKind::Duration => Ok(Value::Duration(self.read_duration()?)),
449			ValueKind::IdentityId => Ok(Value::IdentityId(self.read_identity_id()?)),
450			ValueKind::Uuid4 => Ok(Value::Uuid4(self.read_uuid4()?)),
451			ValueKind::Uuid7 => Ok(Value::Uuid7(self.read_uuid7()?)),
452			ValueKind::Blob => Ok(Value::Blob(self.read_blob()?)),
453			ValueKind::Decimal => Ok(Value::Decimal(self.read_decimal()?)),
454			ValueKind::List => Ok(Value::List(self.read_container_items()?)),
455			ValueKind::Tuple => Ok(Value::Tuple(self.read_container_items()?)),
456			ValueKind::Record => Ok(Value::Record(self.read_record_fields()?)),
457			ValueKind::Any | ValueKind::Type | ValueKind::Digest => {
458				Err(Error::from(TypeError::SerdeKeycode {
459					message: format!(
460						"value kind {:?} cannot be deserialized from keys (position {})",
461						kind,
462						self.position - 1
463					),
464				}))
465			}
466			ValueKind::DictionaryId => {
467				let sub = self.read_exact(1)?[0];
468				match sub {
469					0x00 => Ok(Value::DictionaryId(DictionaryEntryId::U1(self.read_u8()?))),
470					0x01 => Ok(Value::DictionaryId(DictionaryEntryId::U2(self.read_u16()?))),
471					0x02 => Ok(Value::DictionaryId(DictionaryEntryId::U4(self.read_u32()?))),
472					0x03 => Ok(Value::DictionaryId(DictionaryEntryId::U8(self.read_u64()?))),
473					0x04 => Ok(Value::DictionaryId(DictionaryEntryId::U16(self.read_u128()?))),
474					_ => Err(Error::from(TypeError::SerdeKeycode {
475						message: format!(
476							"unknown DictionaryEntryId sub-marker 0x{:02x} at position {}",
477							sub,
478							self.position - 1
479						),
480					})),
481				}
482			}
483		}
484	}
485
486	pub fn read_raw(&mut self, count: usize) -> Result<&'a [u8]> {
487		self.read_exact(count)
488	}
489}
490
491fn unscaled_error(position: usize, error: DecodeError) -> Error {
492	Error::from(TypeError::SerdeKeycode {
493		message: format!("invalid fixed-width number at position {position}: {error}"),
494	})
495}