Skip to main content

reifydb_core/util/encoding/keycode/
deserializer.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2026 ReifyDB
3
4use num_bigint::{BigInt, Sign};
5use reifydb_value::{
6	Result,
7	error::{Error, TypeError},
8	value::{
9		Value,
10		blob::Blob,
11		date::Date,
12		datetime::DateTime,
13		decimal::Decimal,
14		dictionary::DictionaryEntryId,
15		duration::Duration,
16		identity::IdentityId,
17		int::Int,
18		ordered_f32::OrderedF32,
19		ordered_f64::OrderedF64,
20		row_number::RowNumber,
21		time::Time,
22		uint::Uint,
23		uuid::{Uuid4, Uuid7},
24		value_type::ValueType,
25	},
26};
27use uuid::Uuid;
28
29use super::{catalog, decode_i64_varint, decode_u64_varint, decode_u128_varint, deserialize};
30use crate::interface::catalog::{id::IndexId, shape::ShapeId};
31
32pub struct KeyDeserializer<'a> {
33	buffer: &'a [u8],
34	position: usize,
35}
36
37impl<'a> KeyDeserializer<'a> {
38	pub fn from_bytes(buffer: &'a [u8]) -> Self {
39		Self {
40			buffer,
41			position: 0,
42		}
43	}
44
45	pub fn remaining(&self) -> usize {
46		self.buffer.len().saturating_sub(self.position)
47	}
48
49	pub fn is_empty(&self) -> bool {
50		self.remaining() == 0
51	}
52
53	pub fn position(&self) -> usize {
54		self.position
55	}
56
57	pub fn remaining_bytes(&self) -> &'a [u8] {
58		&self.buffer[self.position..]
59	}
60
61	fn read_exact(&mut self, count: usize) -> Result<&'a [u8]> {
62		if self.remaining() < count {
63			return Err(Error::from(TypeError::SerdeKeycode {
64				message: format!(
65					"unexpected end of key at position {}: need {} bytes, have {}",
66					self.position,
67					count,
68					self.remaining()
69				),
70			}));
71		}
72		let start = self.position;
73		self.position += count;
74		Ok(&self.buffer[start..self.position])
75	}
76
77	pub fn read_bool(&mut self) -> Result<bool> {
78		let bytes = self.read_exact(1)?;
79		deserialize::<bool>(bytes)
80	}
81
82	pub fn read_f32(&mut self) -> Result<f32> {
83		let bytes = self.read_exact(4)?;
84		deserialize::<f32>(bytes)
85	}
86
87	pub fn read_f64(&mut self) -> Result<f64> {
88		let bytes = self.read_exact(8)?;
89		deserialize::<f64>(bytes)
90	}
91
92	pub fn read_i8(&mut self) -> Result<i8> {
93		let bytes = self.read_exact(1)?;
94		deserialize::<i8>(bytes)
95	}
96
97	pub fn read_i16(&mut self) -> Result<i16> {
98		let bytes = self.read_exact(2)?;
99		deserialize::<i16>(bytes)
100	}
101
102	pub fn read_i32(&mut self) -> Result<i32> {
103		let bytes = self.read_exact(4)?;
104		deserialize::<i32>(bytes)
105	}
106
107	pub fn read_i64(&mut self) -> Result<i64> {
108		let mut slice = &self.buffer[self.position..];
109		let i = decode_i64_varint(&mut slice)?;
110		self.position = self.buffer.len() - slice.len();
111		Ok(i)
112	}
113
114	pub fn read_i128(&mut self) -> Result<i128> {
115		let bytes = self.read_exact(16)?;
116		deserialize::<i128>(bytes)
117	}
118
119	pub fn read_u8(&mut self) -> Result<u8> {
120		let bytes = self.read_exact(1)?;
121		deserialize::<u8>(bytes)
122	}
123
124	pub fn read_u16(&mut self) -> Result<u16> {
125		let bytes = self.read_exact(2)?;
126		deserialize::<u16>(bytes)
127	}
128
129	pub fn read_u32(&mut self) -> Result<u32> {
130		let mut slice = &self.buffer[self.position..];
131		let u = decode_u64_varint(&mut slice)?;
132		self.position = self.buffer.len() - slice.len();
133		Ok(u as u32)
134	}
135
136	pub fn read_u64(&mut self) -> Result<u64> {
137		let mut slice = &self.buffer[self.position..];
138		let u = decode_u64_varint(&mut slice)?;
139		self.position = self.buffer.len() - slice.len();
140		Ok(u)
141	}
142
143	pub fn read_u128(&mut self) -> Result<u128> {
144		let bytes = self.read_exact(16)?;
145		deserialize::<u128>(bytes)
146	}
147
148	pub fn read_u128_varint(&mut self) -> Result<u128> {
149		let mut slice = &self.buffer[self.position..];
150		let u = decode_u128_varint(&mut slice)?;
151		self.position = self.buffer.len() - slice.len();
152		Ok(u)
153	}
154
155	pub fn read_bytes(&mut self) -> Result<Vec<u8>> {
156		let mut result = Vec::new();
157		loop {
158			if self.remaining() < 1 {
159				return Err(Error::from(TypeError::SerdeKeycode {
160					message: format!(
161						"unexpected end of key at position {}: bytes not terminated",
162						self.position
163					),
164				}));
165			}
166			let byte = self.buffer[self.position];
167			self.position += 1;
168
169			if byte == 0xff {
170				if self.remaining() < 1 {
171					return Err(Error::from(TypeError::SerdeKeycode {
172						message: format!(
173							"unexpected end of key at position {}: incomplete escape sequence",
174							self.position
175						),
176					}));
177				}
178				let next_byte = self.buffer[self.position];
179				self.position += 1;
180
181				if next_byte == 0x00 {
182					result.push(0xff);
183				} else if next_byte == 0xff {
184					break;
185				} else {
186					return Err(Error::from(TypeError::SerdeKeycode {
187						message: format!(
188							"invalid escape sequence at position {}: 0xff 0x{:02x}",
189							self.position - 1,
190							next_byte
191						),
192					}));
193				}
194			} else {
195				result.push(byte);
196			}
197		}
198		Ok(result)
199	}
200
201	pub fn read_str(&mut self) -> Result<String> {
202		let bytes = self.read_bytes()?;
203		String::from_utf8(bytes).map_err(|e| {
204			Error::from(TypeError::SerdeKeycode {
205				message: format!("invalid UTF-8 in key at position {}: {}", self.position, e),
206			})
207		})
208	}
209
210	pub fn read_shape_id(&mut self) -> Result<ShapeId> {
211		let mut slice = &self.buffer[self.position..];
212		let shape_id = catalog::deserialize_shape_id(&mut slice)?;
213		self.position = self.buffer.len() - slice.len();
214		Ok(shape_id)
215	}
216
217	pub fn read_index_id(&mut self) -> Result<IndexId> {
218		let mut slice = &self.buffer[self.position..];
219		let index_id = catalog::deserialize_index_id(&mut slice)?;
220		self.position = self.buffer.len() - slice.len();
221		Ok(index_id)
222	}
223
224	pub fn read_date(&mut self) -> Result<Date> {
225		let days = self.read_i32()?;
226		Date::from_days_since_epoch(days).ok_or_else(|| {
227			Error::from(TypeError::SerdeKeycode {
228				message: format!(
229					"invalid date at position {}: {} days since epoch",
230					self.position, days
231				),
232			})
233		})
234	}
235
236	pub fn read_datetime(&mut self) -> Result<DateTime> {
237		let nanos = self.read_u64()?;
238		Ok(DateTime::from_nanos(nanos))
239	}
240
241	pub fn read_time(&mut self) -> Result<Time> {
242		let nanos = self.read_u64()?;
243		Time::from_nanos_since_midnight(nanos).ok_or_else(|| {
244			Error::from(TypeError::SerdeKeycode {
245				message: format!(
246					"invalid time at position {}: {} nanos since midnight",
247					self.position, nanos
248				),
249			})
250		})
251	}
252
253	pub fn read_duration(&mut self) -> Result<Duration> {
254		let months = self.read_i32()?;
255		let days = self.read_i32()?;
256		let nanos = self.read_i64()?;
257		Ok(Duration::new(months, days, nanos)?)
258	}
259
260	pub fn read_row_number(&mut self) -> Result<RowNumber> {
261		let value = self.read_u64()?;
262		Ok(RowNumber(value))
263	}
264
265	pub fn read_identity_id(&mut self) -> Result<IdentityId> {
266		let bytes = self.read_bytes()?;
267		let uuid = Uuid::from_slice(&bytes).map_err(|e| {
268			Error::from(TypeError::SerdeKeycode {
269				message: format!("invalid IdentityId at position {}: {}", self.position, e),
270			})
271		})?;
272		Ok(IdentityId::from(Uuid7::from(uuid)))
273	}
274
275	pub fn read_uuid4(&mut self) -> Result<Uuid4> {
276		let bytes = self.read_bytes()?;
277		let uuid = Uuid::from_slice(&bytes).map_err(|e| {
278			Error::from(TypeError::SerdeKeycode {
279				message: format!("invalid Uuid4 at position {}: {}", self.position, e),
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		Ok(Uuid7::from(uuid))
293	}
294
295	pub fn read_blob(&mut self) -> Result<Blob> {
296		let bytes = self.read_bytes()?;
297		Ok(Blob::from(bytes))
298	}
299
300	pub fn read_int(&mut self) -> Result<Int> {
301		let sign = self.read_exact(1)?[0];
302		let len = self.read_u32()? as usize;
303		let bytes = self.read_exact(len)?;
304
305		let sign = match sign {
306			0 => Sign::Minus,
307			_ => Sign::Plus,
308		};
309
310		Ok(Int(BigInt::from_bytes_be(sign, bytes)))
311	}
312
313	pub fn read_uint(&mut self) -> Result<Uint> {
314		let len = self.read_u32()? as usize;
315		let bytes = self.read_exact(len)?;
316		Ok(Uint(BigInt::from_bytes_be(Sign::Plus, bytes)))
317	}
318
319	pub fn read_decimal(&mut self) -> Result<Decimal> {
320		let s = self.read_str()?;
321		s.parse::<Decimal>().map_err(|e| {
322			Error::from(TypeError::SerdeKeycode {
323				message: format!("invalid Decimal at position {}: {}", self.position, e),
324			})
325		})
326	}
327
328	pub fn read_value(&mut self) -> Result<Value> {
329		if self.remaining() < 1 {
330			return Err(Error::from(TypeError::SerdeKeycode {
331				message: format!(
332					"unexpected end of key at position {}: cannot read value type",
333					self.position
334				),
335			}));
336		}
337
338		let type_marker = self.buffer[self.position];
339		self.position += 1;
340
341		match type_marker {
342			0x00 => {
343				if self.remaining() < 1 {
344					return Ok(Value::none());
345				}
346				let inner_marker = self.buffer[self.position];
347				self.position += 1;
348				let inner = match inner_marker {
349					0x01 => ValueType::Boolean,
350					0x02 => ValueType::Float4,
351					0x03 => ValueType::Float8,
352					0x04 => ValueType::Int1,
353					0x05 => ValueType::Int2,
354					0x06 => ValueType::Int4,
355					0x07 => ValueType::Int8,
356					0x08 => ValueType::Int16,
357					0x09 => ValueType::Utf8,
358					0x0a => ValueType::Uint1,
359					0x0b => ValueType::Uint2,
360					0x0c => ValueType::Uint4,
361					0x0d => ValueType::Uint8,
362					0x0e => ValueType::Uint16,
363					0x0f => ValueType::Date,
364					0x10 => ValueType::DateTime,
365					0x11 => ValueType::Time,
366					0x12 => ValueType::Duration,
367					0x14 => ValueType::IdentityId,
368					0x15 => ValueType::Uuid4,
369					0x16 => ValueType::Uuid7,
370					0x17 => ValueType::Blob,
371					0x18 => ValueType::Int,
372					0x19 => ValueType::Uint,
373					0x1a => ValueType::Decimal,
374					0x1b => ValueType::DictionaryId,
375					_ => ValueType::Any,
376				};
377				Ok(Value::none_of(inner))
378			}
379			0x01 => {
380				let b = self.read_bool()?;
381				Ok(Value::Boolean(b))
382			}
383			0x02 => {
384				let f = self.read_f32()?;
385				Ok(Value::Float4(OrderedF32::try_from(f).map_err(|e| {
386					Error::from(TypeError::SerdeKeycode {
387						message: format!("invalid f32 at position {}: {}", self.position, e),
388					})
389				})?))
390			}
391			0x03 => {
392				let f = self.read_f64()?;
393				Ok(Value::Float8(OrderedF64::try_from(f).map_err(|e| {
394					Error::from(TypeError::SerdeKeycode {
395						message: format!("invalid f64 at position {}: {}", self.position, e),
396					})
397				})?))
398			}
399			0x04 => {
400				let i = self.read_i8()?;
401				Ok(Value::Int1(i))
402			}
403			0x05 => {
404				let i = self.read_i16()?;
405				Ok(Value::Int2(i))
406			}
407			0x06 => {
408				let i = self.read_i32()?;
409				Ok(Value::Int4(i))
410			}
411			0x07 => {
412				let i = self.read_i64()?;
413				Ok(Value::Int8(i))
414			}
415			0x08 => {
416				let i = self.read_i128()?;
417				Ok(Value::Int16(i))
418			}
419			0x09 => {
420				let s = self.read_str()?;
421				Ok(Value::Utf8(s))
422			}
423			0x0a => {
424				let u = self.read_u8()?;
425				Ok(Value::Uint1(u))
426			}
427			0x0b => {
428				let u = self.read_u16()?;
429				Ok(Value::Uint2(u))
430			}
431			0x0c => {
432				let u = self.read_u32()?;
433				Ok(Value::Uint4(u))
434			}
435			0x0d => {
436				let u = self.read_u64()?;
437				Ok(Value::Uint8(u))
438			}
439			0x0e => {
440				let u = self.read_u128()?;
441				Ok(Value::Uint16(u))
442			}
443			0x0f => {
444				let d = self.read_date()?;
445				Ok(Value::Date(d))
446			}
447			0x10 => {
448				let dt = self.read_datetime()?;
449				Ok(Value::DateTime(dt))
450			}
451			0x11 => {
452				let t = self.read_time()?;
453				Ok(Value::Time(t))
454			}
455			0x12 => {
456				let i = self.read_duration()?;
457				Ok(Value::Duration(i))
458			}
459
460			0x13 => panic!("ValueType code 0x13 (RowNumber) is no longer supported"),
461			0x14 => {
462				let id = self.read_identity_id()?;
463				Ok(Value::IdentityId(id))
464			}
465			0x15 => {
466				let u = self.read_uuid4()?;
467				Ok(Value::Uuid4(u))
468			}
469			0x16 => {
470				let u = self.read_uuid7()?;
471				Ok(Value::Uuid7(u))
472			}
473			0x17 => {
474				let b = self.read_blob()?;
475				Ok(Value::Blob(b))
476			}
477			0x18 => {
478				let i = self.read_int()?;
479				Ok(Value::Int(i))
480			}
481			0x19 => {
482				let u = self.read_uint()?;
483				Ok(Value::Uint(u))
484			}
485			0x1a => {
486				let d = self.read_decimal()?;
487				Ok(Value::Decimal(d))
488			}
489			0x1b => {
490				let sub = self.read_exact(1)?[0];
491				match sub {
492					0x00 => Ok(Value::DictionaryId(DictionaryEntryId::U1(self.read_u8()?))),
493					0x01 => Ok(Value::DictionaryId(DictionaryEntryId::U2(self.read_u16()?))),
494					0x02 => Ok(Value::DictionaryId(DictionaryEntryId::U4(self.read_u32()?))),
495					0x03 => Ok(Value::DictionaryId(DictionaryEntryId::U8(self.read_u64()?))),
496					0x04 => Ok(Value::DictionaryId(DictionaryEntryId::U16(self.read_u128()?))),
497					_ => Err(Error::from(TypeError::SerdeKeycode {
498						message: format!(
499							"unknown DictionaryEntryId sub-marker 0x{:02x} at position {}",
500							sub,
501							self.position - 1
502						),
503					})),
504				}
505			}
506			_ => Err(Error::from(TypeError::SerdeKeycode {
507				message: format!(
508					"unknown value type marker 0x{:02x} at position {}",
509					type_marker,
510					self.position - 1
511				),
512			})),
513		}
514	}
515
516	pub fn read_raw(&mut self, count: usize) -> Result<&'a [u8]> {
517		self.read_exact(count)
518	}
519}
520
521#[cfg(test)]
522pub mod tests {
523	use std::f64::consts::E;
524
525	use reifydb_value::value::{
526		date::Date, datetime::DateTime, duration::Duration, row_number::RowNumber, time::Time,
527	};
528
529	use crate::{
530		encoded::key::EncodedKey,
531		interface::catalog::{id::IndexId, shape::ShapeId},
532		util::encoding::keycode::{deserializer::KeyDeserializer, serializer::KeySerializer},
533	};
534
535	#[test]
536	fn test_read_bool() {
537		let mut ser = KeySerializer::new();
538		ser.extend_bool(true).extend_bool(false);
539		let bytes = ser.finish();
540
541		let mut de = KeyDeserializer::from_bytes(&bytes);
542		assert_eq!(de.read_bool().unwrap(), true);
543		assert_eq!(de.read_bool().unwrap(), false);
544		assert!(de.is_empty());
545	}
546
547	#[test]
548	fn test_read_integers() {
549		let mut ser = KeySerializer::new();
550		ser.extend_i8(-42i8).extend_i16(-1000i16).extend_i32(100000i32).extend_i64(-1000000000i64);
551		let bytes = ser.finish();
552
553		let mut de = KeyDeserializer::from_bytes(&bytes);
554		assert_eq!(de.read_i8().unwrap(), -42);
555		assert_eq!(de.read_i16().unwrap(), -1000);
556		assert_eq!(de.read_i32().unwrap(), 100000);
557		assert_eq!(de.read_i64().unwrap(), -1000000000);
558		assert!(de.is_empty());
559	}
560
561	#[test]
562	fn test_read_unsigned() {
563		let mut ser = KeySerializer::new();
564		ser.extend_u8(255u8).extend_u16(65535u16).extend_u32(4294967295u32).extend_u64(18446744073709551615u64);
565		let bytes = ser.finish();
566
567		let mut de = KeyDeserializer::from_bytes(&bytes);
568		assert_eq!(de.read_u8().unwrap(), 255);
569		assert_eq!(de.read_u16().unwrap(), 65535);
570		assert_eq!(de.read_u32().unwrap(), 4294967295);
571		assert_eq!(de.read_u64().unwrap(), 18446744073709551615);
572		assert!(de.is_empty());
573	}
574
575	#[test]
576	fn test_read_floats() {
577		let mut ser = KeySerializer::new();
578		ser.extend_f32(3.14).extend_f64(E);
579		let bytes = ser.finish();
580
581		let mut de = KeyDeserializer::from_bytes(&bytes);
582		assert!((de.read_f32().unwrap() - 3.14).abs() < 0.001);
583		assert!((de.read_f64().unwrap() - E).abs() < 0.000001);
584		assert!(de.is_empty());
585	}
586
587	#[test]
588	fn test_read_bytes() {
589		let mut ser = KeySerializer::new();
590		ser.extend_bytes(b"hello").extend_bytes(&[0x01, 0xff, 0x02]);
591		let bytes = ser.finish();
592
593		let mut de = KeyDeserializer::from_bytes(&bytes);
594		assert_eq!(de.read_bytes().unwrap(), b"hello");
595		assert_eq!(de.read_bytes().unwrap(), vec![0x01, 0xff, 0x02]);
596		assert!(de.is_empty());
597	}
598
599	#[test]
600	fn test_read_str() {
601		let mut ser = KeySerializer::new();
602		ser.extend_str("hello world").extend_str("👋");
603		let bytes = ser.finish();
604
605		let mut de = KeyDeserializer::from_bytes(&bytes);
606		assert_eq!(de.read_str().unwrap(), "hello world");
607		assert_eq!(de.read_str().unwrap(), "👋");
608		assert!(de.is_empty());
609	}
610
611	#[test]
612	fn test_read_date() {
613		let mut ser = KeySerializer::new();
614		let date = Date::from_ymd(2024, 1, 1).unwrap();
615		ser.extend_date(&date);
616		let bytes = ser.finish();
617
618		let mut de = KeyDeserializer::from_bytes(&bytes);
619		assert_eq!(de.read_date().unwrap(), date);
620		assert!(de.is_empty());
621	}
622
623	#[test]
624	fn test_read_datetime() {
625		let mut ser = KeySerializer::new();
626		let datetime = DateTime::from_ymd_hms(2024, 1, 1, 12, 30, 45).unwrap();
627		ser.extend_datetime(&datetime);
628		let bytes = ser.finish();
629
630		let mut de = KeyDeserializer::from_bytes(&bytes);
631		assert_eq!(de.read_datetime().unwrap(), datetime);
632		assert!(de.is_empty());
633	}
634
635	#[test]
636	fn test_read_time() {
637		let mut ser = KeySerializer::new();
638		let time = Time::from_hms(12, 30, 45).unwrap();
639		ser.extend_time(&time);
640		let bytes = ser.finish();
641
642		let mut de = KeyDeserializer::from_bytes(&bytes);
643		assert_eq!(de.read_time().unwrap(), time);
644		assert!(de.is_empty());
645	}
646
647	#[test]
648	fn test_read_duration() {
649		let mut ser = KeySerializer::new();
650		let duration = Duration::from_nanoseconds(1000000).unwrap();
651		ser.extend_duration(&duration);
652		let bytes = ser.finish();
653
654		let mut de = KeyDeserializer::from_bytes(&bytes);
655		assert_eq!(de.read_duration().unwrap(), duration);
656		assert!(de.is_empty());
657	}
658
659	#[test]
660	fn test_keycode_roundtrip_with_months_and_days() {
661		let mut ser = KeySerializer::new();
662		let duration = Duration::new(12, 5, 1_000_000_000).unwrap();
663		ser.extend_duration(&duration);
664		let bytes = ser.finish();
665
666		let mut de = KeyDeserializer::from_bytes(&bytes);
667		assert_eq!(de.read_duration().unwrap(), duration);
668		assert!(de.is_empty());
669	}
670
671	#[test]
672	fn test_keycode_different_durations_produce_different_keys() {
673		let d1 = Duration::new(12, 0, 0).unwrap();
674		let d2 = Duration::zero();
675
676		let mut s1 = KeySerializer::new();
677		s1.extend_duration(&d1);
678		let b1 = s1.finish();
679
680		let mut s2 = KeySerializer::new();
681		s2.extend_duration(&d2);
682		let b2 = s2.finish();
683
684		assert_ne!(b1, b2);
685	}
686
687	#[test]
688	fn test_keycode_duration_ordering_preserved() {
689		// Keycode encoding is descending: larger Duration → smaller bytes
690		let durations = vec![
691			Duration::new(0, 0, 0).unwrap(),
692			Duration::new(0, 0, 1_000_000_000).unwrap(),
693			Duration::new(0, 1, 0).unwrap(),
694			Duration::new(1, 0, 0).unwrap(),
695			Duration::new(12, 30, 0).unwrap(),
696		];
697
698		let keys: Vec<EncodedKey> = durations
699			.iter()
700			.map(|d| {
701				let mut ser = KeySerializer::new();
702				ser.extend_duration(d);
703				ser.finish()
704			})
705			.collect();
706
707		for i in 0..keys.len() - 1 {
708			assert!(
709				keys[i] > keys[i + 1],
710				"Key ordering broken: {:?} key should be > {:?} key (descending encoding)",
711				durations[i],
712				durations[i + 1]
713			);
714		}
715	}
716
717	#[test]
718	fn test_read_row_number() {
719		let mut ser = KeySerializer::new();
720		let row = RowNumber(42);
721		ser.extend_row_number(&row);
722		let bytes = ser.finish();
723
724		let mut de = KeyDeserializer::from_bytes(&bytes);
725		assert_eq!(de.read_row_number().unwrap(), row);
726		assert!(de.is_empty());
727	}
728
729	#[test]
730	fn test_read_shape_id() {
731		let mut ser = KeySerializer::new();
732		let primitive = ShapeId::table(42);
733		ser.extend_shape_id(primitive);
734		let bytes = ser.finish();
735
736		let mut de = KeyDeserializer::from_bytes(&bytes);
737		assert_eq!(de.read_shape_id().unwrap(), primitive);
738		assert!(de.is_empty());
739	}
740
741	#[test]
742	fn test_read_index_id() {
743		let mut ser = KeySerializer::new();
744		let index = IndexId::primary(999);
745		ser.extend_index_id(index);
746		let bytes = ser.finish();
747
748		let mut de = KeyDeserializer::from_bytes(&bytes);
749		assert_eq!(de.read_index_id().unwrap(), index);
750		assert!(de.is_empty());
751	}
752
753	#[test]
754	fn test_position_tracking() {
755		let mut ser = KeySerializer::new();
756		ser.extend_u8(1u8).extend_u16(2u16).extend_u32(3u32);
757		let bytes = ser.finish();
758
759		let mut de = KeyDeserializer::from_bytes(&bytes);
760		assert_eq!(de.position(), 0);
761		assert_eq!(de.remaining(), 4);
762
763		de.read_u8().unwrap();
764		assert_eq!(de.position(), 1);
765		assert_eq!(de.remaining(), 3);
766
767		de.read_u16().unwrap();
768		assert_eq!(de.position(), 3);
769		assert_eq!(de.remaining(), 1);
770
771		de.read_u32().unwrap();
772		assert_eq!(de.position(), 4);
773		assert_eq!(de.remaining(), 0);
774		assert!(de.is_empty());
775	}
776
777	#[test]
778	fn test_error_on_insufficient_bytes() {
779		let bytes = vec![0x00, 0x01];
780		let mut de = KeyDeserializer::from_bytes(&bytes);
781		assert!(de.read_u32().is_err());
782	}
783
784	#[test]
785	fn test_chaining() {
786		let mut ser = KeySerializer::new();
787		ser.extend_bool(true).extend_i32(42i32).extend_str("test").extend_u64(1000u64);
788		let bytes = ser.finish();
789
790		let mut de = KeyDeserializer::from_bytes(&bytes);
791		assert_eq!(de.read_bool().unwrap(), true);
792		assert_eq!(de.read_i32().unwrap(), 42);
793		assert_eq!(de.read_str().unwrap(), "test");
794		assert_eq!(de.read_u64().unwrap(), 1000);
795		assert!(de.is_empty());
796	}
797}