Skip to main content

reifydb_core/util/encoding/keycode/
mod.rs

1// SPDX-License-Identifier: AGPL-3.0-or-later
2// Copyright (c) 2025 ReifyDB
3
4// This file includes and modifies code from the toydb project (https://github.com/erikgrinaker/toydb),
5// originally licensed under the Apache License, Version 2.0.
6// Original copyright:
7//   Copyright (c) 2024 Erik Grinaker
8//
9// The original Apache License can be found at:
10//   http://www.apache.org/licenses/LICENSE-2.0
11
12use serde::{Deserialize, Serialize};
13
14pub mod catalog;
15pub mod deserialize;
16pub mod deserializer;
17pub mod serialize;
18pub mod serializer;
19
20use reifydb_type::{error, error::diagnostic::serde::serde_keycode_error};
21
22use crate::util::encoding::keycode::{deserialize::Deserializer, serialize::Serializer};
23
24/// Encode a bool value for keycode (true=0x00, false=0x01 for descending order)
25pub fn encode_bool(value: bool) -> u8 {
26	if value {
27		0x00
28	} else {
29		0x01
30	}
31}
32
33/// Encode an f32 value for keycode
34pub fn encode_f32(value: f32) -> [u8; 4] {
35	let mut bytes = value.to_be_bytes();
36	match value.is_sign_negative() {
37		false => bytes[0] ^= 1 << 7,                     // positive, flip sign bit
38		true => bytes.iter_mut().for_each(|b| *b = !*b), // negative, flip all bits
39	}
40	for b in bytes.iter_mut() {
41		*b = !*b;
42	}
43	bytes
44}
45
46/// Encode an f64 value for keycode
47pub fn encode_f64(value: f64) -> [u8; 8] {
48	let mut bytes = value.to_be_bytes();
49	match value.is_sign_negative() {
50		false => bytes[0] ^= 1 << 7,                     // positive, flip sign bit
51		true => bytes.iter_mut().for_each(|b| *b = !*b), // negative, flip all bits
52	}
53	for b in bytes.iter_mut() {
54		*b = !*b;
55	}
56	bytes
57}
58
59/// Encode an i8 value for keycode (flip sign bit, then NOT)
60pub fn encode_i8(value: i8) -> [u8; 1] {
61	let mut bytes = value.to_be_bytes();
62	bytes[0] ^= 1 << 7; // flip sign bit
63	for b in bytes.iter_mut() {
64		*b = !*b;
65	}
66	bytes
67}
68
69/// Encode an i16 value for keycode (flip sign bit, then NOT)
70pub fn encode_i16(value: i16) -> [u8; 2] {
71	let mut bytes = value.to_be_bytes();
72	bytes[0] ^= 1 << 7; // flip sign bit
73	for b in bytes.iter_mut() {
74		*b = !*b;
75	}
76	bytes
77}
78
79/// Encode an i32 value for keycode (flip sign bit, then NOT)
80pub fn encode_i32(value: i32) -> [u8; 4] {
81	let mut bytes = value.to_be_bytes();
82	bytes[0] ^= 1 << 7; // flip sign bit
83	for b in bytes.iter_mut() {
84		*b = !*b;
85	}
86	bytes
87}
88
89/// Encode an i64 value for keycode (flip sign bit, then NOT)
90pub fn encode_i64(value: i64) -> [u8; 8] {
91	let mut bytes = value.to_be_bytes();
92	bytes[0] ^= 1 << 7; // flip sign bit
93	for b in bytes.iter_mut() {
94		*b = !*b;
95	}
96	bytes
97}
98
99/// Encode an i128 value for keycode (flip sign bit, then NOT)
100pub fn encode_i128(value: i128) -> [u8; 16] {
101	let mut bytes = value.to_be_bytes();
102	bytes[0] ^= 1 << 7; // flip sign bit
103	for b in bytes.iter_mut() {
104		*b = !*b;
105	}
106	bytes
107}
108
109/// Encode a u8 value for keycode (bitwise NOT)
110pub fn encode_u8(value: u8) -> u8 {
111	!value
112}
113
114/// Encode a u16 value for keycode (bitwise NOT of big-endian)
115pub fn encode_u16(value: u16) -> [u8; 2] {
116	let mut bytes = value.to_be_bytes();
117	for b in bytes.iter_mut() {
118		*b = !*b;
119	}
120	bytes
121}
122
123/// Encode a u32 value for keycode (bitwise NOT of big-endian)
124pub fn encode_u32(value: u32) -> [u8; 4] {
125	let mut bytes = value.to_be_bytes();
126	for b in bytes.iter_mut() {
127		*b = !*b;
128	}
129	bytes
130}
131
132/// Encode a u64 value for keycode (bitwise NOT of big-endian)
133pub fn encode_u64(value: u64) -> [u8; 8] {
134	let mut bytes = value.to_be_bytes();
135	for b in bytes.iter_mut() {
136		*b = !*b;
137	}
138	bytes
139}
140
141/// Encode a u128 value for keycode (bitwise NOT of big-endian)
142pub fn encode_u128(value: u128) -> [u8; 16] {
143	let mut bytes = value.to_be_bytes();
144	for b in bytes.iter_mut() {
145		*b = !*b;
146	}
147	bytes
148}
149
150/// Encode bytes for keycode (escape 0xff, terminate with 0xffff)
151pub fn encode_bytes(bytes: &[u8], output: &mut Vec<u8>) {
152	for &byte in bytes {
153		if byte == 0xff {
154			output.push(0xff);
155			output.push(0x00);
156		} else {
157			output.push(byte);
158		}
159	}
160	output.push(0xff);
161	output.push(0xff);
162}
163
164#[macro_export]
165macro_rules! key_prefix {
166    ($($arg:tt)*) => {
167        &EncodedKey::new((&format!($($arg)*)).as_bytes().to_vec())
168    };
169}
170
171/// Serializes a key to a binary Keycode representation (Descending order)
172pub fn serialize<T: Serialize>(key: &T) -> Vec<u8> {
173	let mut serializer = Serializer {
174		output: Vec::new(),
175	};
176	// Panic on failure, as this is a problem with the data structure.
177	key.serialize(&mut serializer).expect("key must be serializable");
178	serializer.output
179}
180
181/// Deserializes a key from a binary Keycode representation (Descending order)
182pub fn deserialize<'a, T: Deserialize<'a>>(input: &'a [u8]) -> reifydb_type::Result<T> {
183	let mut deserializer = Deserializer::from_bytes(input);
184	let t = T::deserialize(&mut deserializer)?;
185	if !deserializer.input.is_empty() {
186		return Err(error!(serde_keycode_error(format!(
187			"unexpected trailing bytes {:x?} at end of key {input:x?}",
188			deserializer.input,
189		))));
190	}
191	Ok(t)
192}
193
194#[cfg(test)]
195pub mod tests {
196	use std::borrow::Cow;
197
198	const PI_F32: f32 = std::f32::consts::PI;
199	const PI_F64: f64 = std::f64::consts::PI;
200
201	use reifydb_type::value::{Value, ordered_f32::OrderedF32, ordered_f64::OrderedF64};
202	use serde_bytes::ByteBuf;
203
204	use super::*;
205	use crate::util::encoding::keycode::serializer::KeySerializer;
206
207	#[derive(Debug, Deserialize, Serialize, PartialEq)]
208	enum Key<'a> {
209		Unit,
210		NewType(String),
211		Tuple(bool, #[serde(with = "serde_bytes")] Vec<u8>, u64),
212		Cow(
213			#[serde(with = "serde_bytes")]
214			#[serde(borrow)]
215			Cow<'a, [u8]>,
216			bool,
217			#[serde(borrow)] Cow<'a, str>,
218		),
219	}
220
221	macro_rules! test_serde {
222        ( $( $name:ident: $input:expr => $expect:literal, )* ) => {
223        $(
224            #[test]
225            fn $name(){
226                let mut input = $input;
227                let expect = $expect;
228                let output = serialize(&input);
229                assert_eq!(reifydb_type::util::hex::encode(&output), expect, "encode failed");
230
231                let expect = input;
232                input = deserialize(&output).unwrap();
233                assert_eq!(input, expect, "decode failed");
234            }
235        )*
236        };
237    }
238
239	test_serde! {
240	bool_false: false => "01",
241	bool_true: true => "00",
242
243	f32_min: f32::MIN => "ff7fffff",
244	f32_neg_inf: f32::NEG_INFINITY => "ff800000",
245	f32_neg_pi: -PI_F32 => "c0490fdb",
246	f32_neg_zero: -0f32 => "80000000",
247	f32_zero: 0f32 => "7fffffff",
248	f32_pi: PI_F32 => "3fb6f024",
249	f32_max: f32::MAX => "00800000",
250	f32_inf: f32::INFINITY => "007fffff",
251
252	f64_min: f64::MIN => "ffefffffffffffff",
253	f64_neg_inf: f64::NEG_INFINITY => "fff0000000000000",
254	f64_neg_pi: -PI_F64 => "c00921fb54442d18",
255	f64_neg_zero: -0f64 => "8000000000000000",
256	f64_zero: 0f64 => "7fffffffffffffff",
257	f64_pi: PI_F64 => "3ff6de04abbbd2e7",
258	f64_max: f64::MAX => "0010000000000000",
259	f64_inf: f64::INFINITY => "000fffffffffffff",
260
261	i8_min: i8::MIN => "ff",
262	i8_neg_1: -1i8 => "80",
263	i8_0: 0i8 => "7f",
264	i8_1: 1i8 => "7e",
265	i8_max: i8::MAX => "00",
266
267	i16_min: i16::MIN => "ffff",
268	i16_neg_1: -1i16 => "8000",
269	i16_0: 0i16 => "7fff",
270	i16_1: 1i16 => "7ffe",
271	i16_max: i16::MAX => "0000",
272
273	i32_min: i32::MIN => "ffffffff",
274	i32_neg_1: -1i32 => "80000000",
275	i32_0: 0i32 => "7fffffff",
276	i32_1: 1i32 => "7ffffffe",
277	i32_max: i32::MAX => "00000000",
278
279	i64_min: i64::MIN => "ffffffffffffffff",
280	i64_neg_65535: -65535i64 => "800000000000fffe",
281	i64_neg_1: -1i64 => "8000000000000000",
282	i64_0: 0i64 => "7fffffffffffffff",
283	i64_1: 1i64 => "7ffffffffffffffe",
284	i64_65535: 65535i64 => "7fffffffffff0000",
285	i64_max: i64::MAX => "0000000000000000",
286
287	i128_min: i128::MIN => "ffffffffffffffffffffffffffffffff",
288	i128_neg_1: -1i128 => "80000000000000000000000000000000",
289	i128_0: 0i128 => "7fffffffffffffffffffffffffffffff",
290	i128_1: 1i128 => "7ffffffffffffffffffffffffffffffe",
291	i128_max: i128::MAX => "00000000000000000000000000000000",
292
293	u8_min: u8::MIN => "ff",
294	u8_1: 1_u8 => "fe",
295	u8_255: 255_u8 => "00",
296
297	u16_min: u16::MIN => "ffff",
298	u16_1: 1_u16 => "fffe",
299	u16_255: 255_u16 => "ff00",
300	u16_65535: u16::MAX => "0000",
301
302	u32_min: u32::MIN => "ffffffff",
303	u32_1: 1_u32 => "fffffffe",
304	u32_65535: 65535_u32 => "ffff0000",
305	u32_max: u32::MAX => "00000000",
306
307	u64_min: u64::MIN => "ffffffffffffffff",
308	u64_1: 1_u64 => "fffffffffffffffe",
309	u64_65535: 65535_u64 => "ffffffffffff0000",
310	u64_max: u64::MAX => "0000000000000000",
311
312	u128_min: u128::MIN => "ffffffffffffffffffffffffffffffff",
313	u128_1: 1_u128 => "fffffffffffffffffffffffffffffffe",
314	u128_65535: 65535_u128 => "ffffffffffffffffffffffffffff0000",
315	u128_max: u128::MAX => "00000000000000000000000000000000",
316
317	bytes: ByteBuf::from(vec![0x01, 0xff]) => "01ff00ffff",
318	bytes_empty: ByteBuf::new() => "ffff",
319	bytes_escape: ByteBuf::from(vec![0x00, 0x01, 0x02]) => "000102ffff",
320
321	string: "foo".to_string() => "666f6fffff",
322	string_empty: "".to_string() => "ffff",
323	string_escape: "foo\x00bar".to_string() => "666f6f00626172ffff",
324	string_utf8: "👋".to_string() => "f09f918bffff",
325
326	tuple: (true, u64::MAX, ByteBuf::from(vec![0x00, 0x01])) => "0000000000000000000001ffff",
327	array_bool: [false, true, false] => "010001",
328	vec_bool: vec![false, true, false] => "010001",
329	vec_u64: vec![u64::MIN, u64::MAX, 65535_u64] => "ffffffffffffffff0000000000000000ffffffffffff0000",
330
331	enum_unit: Key::Unit => "00",
332	enum_newtype: Key::NewType("foo".to_string()) => "01666f6fffff",
333	enum_tuple: Key::Tuple(false, vec![0x00, 0x01], u64::MAX) => "02010001ffff0000000000000000",
334	enum_cow: Key::Cow(vec![0x00, 0x01].into(), false, String::from("foo").into()) => "030001ffff01666f6fffff",
335	enum_cow_borrow: Key::Cow([0x00, 0x01].as_slice().into(), false, "foo".into()) => "030001ffff01666f6fffff",
336
337	value_none: Value::none() => "00",
338	value_bool: Value::Boolean(true) => "0100",
339	value_float4: Value::Float4(OrderedF32::try_from(PI_F32).unwrap()) => "023fb6f024",
340	value_float8: Value::Float8(OrderedF64::try_from(PI_F64).unwrap()) => "033ff6de04abbbd2e7",
341	value_int1: Value::Int1(-1) => "0480",
342	value_int4: Value::Int4(123456) => "067ffe1dbf",
343	value_int8: Value::Int8(31415926) => "077ffffffffe20a189",
344	value_int16: Value::Int16(-123456789012345678901234567890i128) => "08800000018ee90ff6c373e0ee4e3f0ad1",
345	value_string: Value::Utf8("foo".to_string()) => "09666f6fffff",
346	value_uint1: Value::Uint1(255) => "0a00",
347	value_uint2: Value::Uint2(65535) => "0b0000",
348	value_uint4: Value::Uint4(4294967295) => "0c00000000",
349	value_uint8: Value::Uint8(18446744073709551615) => "0d0000000000000000",
350	value_uint16: Value::Uint16(340282366920938463463374607431768211455u128) => "0e00000000000000000000000000000000",
351
352	// Option<bool>
353	option_none_bool: None::<bool> => "00",
354	option_some_true: Some(true) => "0100",
355	option_some_false: Some(false) => "0101",
356
357	// Option<f32>
358	option_none_f32: None::<f32> => "00",
359	option_some_f32: Some(PI_F32) => "013fb6f024",
360
361	// Option<f64>
362	option_none_f64: None::<f64> => "00",
363	option_some_f64: Some(PI_F64) => "013ff6de04abbbd2e7",
364
365	// Option<i8>
366	option_none_i8: None::<i8> => "00",
367	option_some_i8: Some(0i8) => "017f",
368
369	// Option<i16>
370	option_none_i16: None::<i16> => "00",
371	option_some_i16: Some(0i16) => "017fff",
372
373	// Option<i32>
374	option_none_i32: None::<i32> => "00",
375	option_some_i32: Some(0i32) => "017fffffff",
376
377	// Option<i64>
378	option_none_i64: None::<i64> => "00",
379	option_some_i64: Some(0i64) => "017fffffffffffffff",
380
381	// Option<i128>
382	option_none_i128: None::<i128> => "00",
383	option_some_i128: Some(0i128) => "017fffffffffffffffffffffffffffffff",
384
385	// Option<u8>
386	option_none_u8: None::<u8> => "00",
387	option_some_u8: Some(0u8) => "01ff",
388
389	// Option<u16>
390	option_none_u16: None::<u16> => "00",
391	option_some_u16: Some(0u16) => "01ffff",
392
393	// Option<u32>
394	option_none_u32: None::<u32> => "00",
395	option_some_u32: Some(0u32) => "01ffffffff",
396
397	// Option<u64>
398	option_none_u64: None::<u64> => "00",
399	option_some_u64: Some(0u64) => "01ffffffffffffffff",
400
401	// Option<u128>
402	option_none_u128: None::<u128> => "00",
403	option_some_u128: Some(0u128) => "01ffffffffffffffffffffffffffffffff",
404
405	// Option<String>
406	option_none_string: None::<String> => "00",
407	option_some_string: Some("foo".to_string()) => "01666f6fffff",
408	option_some_empty_string: Some("".to_string()) => "01ffff",
409
410	// Option<ByteBuf>
411	option_none_bytes: None::<ByteBuf> => "00",
412	option_some_bytes: Some(ByteBuf::from(vec![0x01, 0xff])) => "0101ff00ffff",
413
414	// Nested Option<Option<bool>>
415	option_nested_none: None::<Option<bool>> => "00",
416	option_nested_some_none: Some(None::<bool>) => "0100",
417	option_nested_some_some_true: Some(Some(true)) => "010100",
418	option_nested_some_some_false: Some(Some(false)) => "010101",
419
420	// Nested Option<Option<i32>>
421	option_nested_none_i32: None::<Option<i32>> => "00",
422	option_nested_some_none_i32: Some(None::<i32>) => "0100",
423	option_nested_some_some_i32: Some(Some(0i32)) => "01017fffffff",
424
425	// Nested Option<Option<String>>
426	option_nested_some_some_string: Some(Some("foo".to_string())) => "0101666f6fffff",
427
428	// Triple nested Option<Option<Option<bool>>>
429	option_triple_none: None::<Option<Option<bool>>> => "00",
430	option_triple_some_none: Some(None::<Option<bool>>) => "0100",
431	option_triple_some_some_none: Some(Some(None::<bool>)) => "010100",
432	option_triple_some_some_some: Some(Some(Some(true))) => "01010100",}
433
434	#[test]
435	fn test_option_ordering() {
436		// Descending: None > Some(MAX) > Some(0) > Some(MIN)
437		// Byte order: None < Some(MAX) < Some(0) < Some(MIN)
438		let none = serialize(&None::<i32>);
439		let some_max = serialize(&Some(i32::MAX));
440		let some_zero = serialize(&Some(0i32));
441		let some_min = serialize(&Some(i32::MIN));
442		assert!(none < some_max);
443		assert!(some_max < some_zero);
444		assert!(some_zero < some_min);
445	}
446
447	#[test]
448	fn test_nested_option_ordering() {
449		let none = serialize(&None::<Option<bool>>);
450		let some_none = serialize(&Some(None::<bool>));
451		let some_some_true = serialize(&Some(Some(true)));
452		let some_some_false = serialize(&Some(Some(false)));
453		assert!(none < some_none);
454		assert!(some_none < some_some_true);
455		assert!(some_some_true < some_some_false);
456	}
457
458	#[test]
459	fn test_key_serializer() {
460		// Test bool
461		let mut s = KeySerializer::new();
462		s.extend_bool(true);
463		assert_eq!(s.finish(), vec![0x00]);
464
465		let mut s = KeySerializer::new();
466		s.extend_bool(false);
467		assert_eq!(s.finish(), vec![0x01]);
468
469		// Test u64
470		let mut s = KeySerializer::new();
471		s.extend_u64(0u64);
472		assert_eq!(s.finish(), vec![0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]);
473
474		// Test i64
475		let mut s = KeySerializer::new();
476		s.extend_i64(0i64);
477		assert_eq!(s.finish(), vec![0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]);
478
479		// Test f32
480		let mut s = KeySerializer::new();
481		s.extend_f32(0.0f32);
482		assert_eq!(s.finish(), vec![0x7f, 0xff, 0xff, 0xff]);
483
484		// Test f64
485		let mut s = KeySerializer::new();
486		s.extend_f64(0.0f64);
487		assert_eq!(s.finish(), vec![0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]);
488
489		// Test bytes
490		let mut s = KeySerializer::new();
491		s.extend_bytes(b"foo");
492		assert_eq!(s.finish(), vec![0x66, 0x6f, 0x6f, 0xff, 0xff]);
493
494		// Test chaining
495		let mut s = KeySerializer::with_capacity(32);
496		s.extend_bool(true).extend_u32(1u32).extend_i16(-1i16).extend_bytes(b"test");
497		let result = s.finish();
498		assert!(!result.is_empty());
499		assert!(result.len() > 10); // Should have all the encoded values
500	}
501}