reifydb_core/util/encoding/keycode/
mod.rs

1// Copyright (c) reifydb.com 2025
2// This file is licensed under the AGPL-3.0-or-later, see license.md file
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
14mod catalog;
15mod deserialize;
16mod deserializer;
17mod serialize;
18mod serializer;
19
20pub use catalog::{deserialize_index_id, deserialize_source_id, serialize_index_id, serialize_source_id};
21pub use deserializer::KeyDeserializer;
22use reifydb_type::diagnostic::serde::serde_keycode_error;
23pub use serializer::KeySerializer;
24
25use crate::util::encoding::keycode::{deserialize::Deserializer, serialize::Serializer};
26
27/// Encode a bool value for keycode (true=0x00, false=0x01 for descending order)
28pub fn encode_bool(value: bool) -> u8 {
29	if value {
30		0x00
31	} else {
32		0x01
33	}
34}
35
36/// Encode an f32 value for keycode
37pub fn encode_f32(value: f32) -> [u8; 4] {
38	let mut bytes = value.to_be_bytes();
39	match value.is_sign_negative() {
40		false => bytes[0] ^= 1 << 7,                     // positive, flip sign bit
41		true => bytes.iter_mut().for_each(|b| *b = !*b), // negative, flip all bits
42	}
43	for b in bytes.iter_mut() {
44		*b = !*b;
45	}
46	bytes
47}
48
49/// Encode an f64 value for keycode
50pub fn encode_f64(value: f64) -> [u8; 8] {
51	let mut bytes = value.to_be_bytes();
52	match value.is_sign_negative() {
53		false => bytes[0] ^= 1 << 7,                     // positive, flip sign bit
54		true => bytes.iter_mut().for_each(|b| *b = !*b), // negative, flip all bits
55	}
56	for b in bytes.iter_mut() {
57		*b = !*b;
58	}
59	bytes
60}
61
62/// Encode an i8 value for keycode (flip sign bit, then NOT)
63pub fn encode_i8(value: i8) -> [u8; 1] {
64	let mut bytes = value.to_be_bytes();
65	bytes[0] ^= 1 << 7; // flip sign bit
66	for b in bytes.iter_mut() {
67		*b = !*b;
68	}
69	bytes
70}
71
72/// Encode an i16 value for keycode (flip sign bit, then NOT)
73pub fn encode_i16(value: i16) -> [u8; 2] {
74	let mut bytes = value.to_be_bytes();
75	bytes[0] ^= 1 << 7; // flip sign bit
76	for b in bytes.iter_mut() {
77		*b = !*b;
78	}
79	bytes
80}
81
82/// Encode an i32 value for keycode (flip sign bit, then NOT)
83pub fn encode_i32(value: i32) -> [u8; 4] {
84	let mut bytes = value.to_be_bytes();
85	bytes[0] ^= 1 << 7; // flip sign bit
86	for b in bytes.iter_mut() {
87		*b = !*b;
88	}
89	bytes
90}
91
92/// Encode an i64 value for keycode (flip sign bit, then NOT)
93pub fn encode_i64(value: i64) -> [u8; 8] {
94	let mut bytes = value.to_be_bytes();
95	bytes[0] ^= 1 << 7; // flip sign bit
96	for b in bytes.iter_mut() {
97		*b = !*b;
98	}
99	bytes
100}
101
102/// Encode an i128 value for keycode (flip sign bit, then NOT)
103pub fn encode_i128(value: i128) -> [u8; 16] {
104	let mut bytes = value.to_be_bytes();
105	bytes[0] ^= 1 << 7; // flip sign bit
106	for b in bytes.iter_mut() {
107		*b = !*b;
108	}
109	bytes
110}
111
112/// Encode a u8 value for keycode (bitwise NOT)
113pub fn encode_u8(value: u8) -> u8 {
114	!value
115}
116
117/// Encode a u16 value for keycode (bitwise NOT of big-endian)
118pub fn encode_u16(value: u16) -> [u8; 2] {
119	let mut bytes = value.to_be_bytes();
120	for b in bytes.iter_mut() {
121		*b = !*b;
122	}
123	bytes
124}
125
126/// Encode a u32 value for keycode (bitwise NOT of big-endian)
127pub fn encode_u32(value: u32) -> [u8; 4] {
128	let mut bytes = value.to_be_bytes();
129	for b in bytes.iter_mut() {
130		*b = !*b;
131	}
132	bytes
133}
134
135/// Encode a u64 value for keycode (bitwise NOT of big-endian)
136pub fn encode_u64(value: u64) -> [u8; 8] {
137	let mut bytes = value.to_be_bytes();
138	for b in bytes.iter_mut() {
139		*b = !*b;
140	}
141	bytes
142}
143
144/// Encode a u128 value for keycode (bitwise NOT of big-endian)
145pub fn encode_u128(value: u128) -> [u8; 16] {
146	let mut bytes = value.to_be_bytes();
147	for b in bytes.iter_mut() {
148		*b = !*b;
149	}
150	bytes
151}
152
153/// Encode bytes for keycode (escape 0xff, terminate with 0xffff)
154pub fn encode_bytes(bytes: &[u8], output: &mut Vec<u8>) {
155	for &byte in bytes {
156		if byte == 0xff {
157			output.push(0xff);
158			output.push(0x00);
159		} else {
160			output.push(byte);
161		}
162	}
163	output.push(0xff);
164	output.push(0xff);
165}
166
167#[macro_export]
168macro_rules! key_prefix {
169    ($($arg:tt)*) => {
170        &EncodedKey::new((&format!($($arg)*)).as_bytes().to_vec())
171    };
172}
173
174/// Serializes a key to a binary Keycode representation (Descending order)
175pub fn serialize<T: Serialize>(key: &T) -> Vec<u8> {
176	let mut serializer = Serializer {
177		output: Vec::new(),
178	};
179	// Panic on failure, as this is a problem with the data structure.
180	key.serialize(&mut serializer).expect("key must be serializable");
181	serializer.output
182}
183
184/// Deserializes a key from a binary Keycode representation (Descending order)
185pub fn deserialize<'a, T: Deserialize<'a>>(input: &'a [u8]) -> crate::Result<T> {
186	let mut deserializer = Deserializer::from_bytes(input);
187	let t = T::deserialize(&mut deserializer)?;
188	if !deserializer.input.is_empty() {
189		return Err(crate::error!(serde_keycode_error(format!(
190			"unexpected trailing bytes {:x?} at end of key {input:x?}",
191			deserializer.input,
192		))));
193	}
194	Ok(t)
195}
196
197#[cfg(test)]
198mod tests {
199	use std::borrow::Cow;
200
201	use reifydb_type::{OrderedF32, OrderedF64, Value};
202
203	const PI_F32: f32 = std::f32::consts::PI;
204	const PI_F64: f64 = std::f64::consts::PI;
205
206	use serde_bytes::ByteBuf;
207
208	use super::*;
209
210	#[derive(Debug, Deserialize, Serialize, PartialEq)]
211	enum Key<'a> {
212		Unit,
213		NewType(String),
214		Tuple(bool, #[serde(with = "serde_bytes")] Vec<u8>, u64),
215		Cow(
216			#[serde(with = "serde_bytes")]
217			#[serde(borrow)]
218			Cow<'a, [u8]>,
219			bool,
220			#[serde(borrow)] Cow<'a, str>,
221		),
222	}
223
224	macro_rules! test_serde {
225        ( $( $name:ident: $input:expr => $expect:literal, )* ) => {
226        $(
227            #[test]
228            fn $name(){
229                let mut input = $input;
230                let expect = $expect;
231                let output = serialize(&input);
232                assert_eq!(reifydb_type::util::hex::encode(&output), expect, "encode failed");
233
234                let expect = input;
235                input = deserialize(&output).unwrap();
236                assert_eq!(input, expect, "decode failed");
237            }
238        )*
239        };
240    }
241
242	test_serde! {
243	bool_false: false => "01",
244	bool_true: true => "00",
245
246	f32_min: f32::MIN => "ff7fffff",
247	f32_neg_inf: f32::NEG_INFINITY => "ff800000",
248	f32_neg_pi: -PI_F32 => "c0490fdb",
249	f32_neg_zero: -0f32 => "80000000",
250	f32_zero: 0f32 => "7fffffff",
251	f32_pi: PI_F32 => "3fb6f024",
252	f32_max: f32::MAX => "00800000",
253	f32_inf: f32::INFINITY => "007fffff",
254
255	f64_min: f64::MIN => "ffefffffffffffff",
256	f64_neg_inf: f64::NEG_INFINITY => "fff0000000000000",
257	f64_neg_pi: -PI_F64 => "c00921fb54442d18",
258	f64_neg_zero: -0f64 => "8000000000000000",
259	f64_zero: 0f64 => "7fffffffffffffff",
260	f64_pi: PI_F64 => "3ff6de04abbbd2e7",
261	f64_max: f64::MAX => "0010000000000000",
262	f64_inf: f64::INFINITY => "000fffffffffffff",
263
264	i8_min: i8::MIN => "ff",
265	i8_neg_1: -1i8 => "80",
266	i8_0: 0i8 => "7f",
267	i8_1: 1i8 => "7e",
268	i8_max: i8::MAX => "00",
269
270	i16_min: i16::MIN => "ffff",
271	i16_neg_1: -1i16 => "8000",
272	i16_0: 0i16 => "7fff",
273	i16_1: 1i16 => "7ffe",
274	i16_max: i16::MAX => "0000",
275
276	i32_min: i32::MIN => "ffffffff",
277	i32_neg_1: -1i32 => "80000000",
278	i32_0: 0i32 => "7fffffff",
279	i32_1: 1i32 => "7ffffffe",
280	i32_max: i32::MAX => "00000000",
281
282	i64_min: i64::MIN => "ffffffffffffffff",
283	i64_neg_65535: -65535i64 => "800000000000fffe",
284	i64_neg_1: -1i64 => "8000000000000000",
285	i64_0: 0i64 => "7fffffffffffffff",
286	i64_1: 1i64 => "7ffffffffffffffe",
287	i64_65535: 65535i64 => "7fffffffffff0000",
288	i64_max: i64::MAX => "0000000000000000",
289
290	i128_min: i128::MIN => "ffffffffffffffffffffffffffffffff",
291	i128_neg_1: -1i128 => "80000000000000000000000000000000",
292	i128_0: 0i128 => "7fffffffffffffffffffffffffffffff",
293	i128_1: 1i128 => "7ffffffffffffffffffffffffffffffe",
294	i128_max: i128::MAX => "00000000000000000000000000000000",
295
296	u8_min: u8::MIN => "ff",
297	u8_1: 1_u8 => "fe",
298	u8_255: 255_u8 => "00",
299
300	u16_min: u16::MIN => "ffff",
301	u16_1: 1_u16 => "fffe",
302	u16_255: 255_u16 => "ff00",
303	u16_65535: u16::MAX => "0000",
304
305	u32_min: u32::MIN => "ffffffff",
306	u32_1: 1_u32 => "fffffffe",
307	u32_65535: 65535_u32 => "ffff0000",
308	u32_max: u32::MAX => "00000000",
309
310	u64_min: u64::MIN => "ffffffffffffffff",
311	u64_1: 1_u64 => "fffffffffffffffe",
312	u64_65535: 65535_u64 => "ffffffffffff0000",
313	u64_max: u64::MAX => "0000000000000000",
314
315	u128_min: u128::MIN => "ffffffffffffffffffffffffffffffff",
316	u128_1: 1_u128 => "fffffffffffffffffffffffffffffffe",
317	u128_65535: 65535_u128 => "ffffffffffffffffffffffffffff0000",
318	u128_max: u128::MAX => "00000000000000000000000000000000",
319
320	bytes: ByteBuf::from(vec![0x01, 0xff]) => "01ff00ffff",
321	bytes_empty: ByteBuf::new() => "ffff",
322	bytes_escape: ByteBuf::from(vec![0x00, 0x01, 0x02]) => "000102ffff",
323
324	string: "foo".to_string() => "666f6fffff",
325	string_empty: "".to_string() => "ffff",
326	string_escape: "foo\x00bar".to_string() => "666f6f00626172ffff",
327	string_utf8: "👋".to_string() => "f09f918bffff",
328
329	tuple: (true, u64::MAX, ByteBuf::from(vec![0x00, 0x01])) => "0000000000000000000001ffff",
330	array_bool: [false, true, false] => "010001",
331	vec_bool: vec![false, true, false] => "010001",
332	vec_u64: vec![u64::MIN, u64::MAX, 65535_u64] => "ffffffffffffffff0000000000000000ffffffffffff0000",
333
334	enum_unit: Key::Unit => "00",
335	enum_newtype: Key::NewType("foo".to_string()) => "01666f6fffff",
336	enum_tuple: Key::Tuple(false, vec![0x00, 0x01], u64::MAX) => "02010001ffff0000000000000000",
337	enum_cow: Key::Cow(vec![0x00, 0x01].into(), false, String::from("foo").into()) => "030001ffff01666f6fffff",
338	enum_cow_borrow: Key::Cow([0x00, 0x01].as_slice().into(), false, "foo".into()) => "030001ffff01666f6fffff",
339
340	value_undefined: Value::Undefined => "00",
341	value_bool: Value::Boolean(true) => "0100",
342	value_float4: Value::Float4(OrderedF32::try_from(PI_F32).unwrap()) => "023fb6f024",
343	value_float8: Value::Float8(OrderedF64::try_from(PI_F64).unwrap()) => "033ff6de04abbbd2e7",
344	value_int1: Value::Int1(-1) => "0480",
345	value_int4: Value::Int4(123456) => "067ffe1dbf",
346	value_int8: Value::Int8(31415926) => "077ffffffffe20a189",
347	value_int16: Value::Int16(-123456789012345678901234567890i128) => "08800000018ee90ff6c373e0ee4e3f0ad1",
348	value_string: Value::Utf8("foo".to_string()) => "09666f6fffff",
349	value_uint1: Value::Uint1(255) => "0a00",
350	value_uint2: Value::Uint2(65535) => "0b0000",
351	value_uint4: Value::Uint4(4294967295) => "0c00000000",
352	value_uint8: Value::Uint8(18446744073709551615) => "0d0000000000000000",
353	value_uint16: Value::Uint16(340282366920938463463374607431768211455u128) => "0e00000000000000000000000000000000",}
354
355	#[test]
356	fn test_key_serializer() {
357		// Test bool
358		let mut s = KeySerializer::new();
359		s.extend_bool(true);
360		assert_eq!(s.finish(), vec![0x00]);
361
362		let mut s = KeySerializer::new();
363		s.extend_bool(false);
364		assert_eq!(s.finish(), vec![0x01]);
365
366		// Test u64
367		let mut s = KeySerializer::new();
368		s.extend_u64(0u64);
369		assert_eq!(s.finish(), vec![0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]);
370
371		// Test i64
372		let mut s = KeySerializer::new();
373		s.extend_i64(0i64);
374		assert_eq!(s.finish(), vec![0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]);
375
376		// Test f32
377		let mut s = KeySerializer::new();
378		s.extend_f32(0.0f32);
379		assert_eq!(s.finish(), vec![0x7f, 0xff, 0xff, 0xff]);
380
381		// Test f64
382		let mut s = KeySerializer::new();
383		s.extend_f64(0.0f64);
384		assert_eq!(s.finish(), vec![0x7f, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff]);
385
386		// Test bytes
387		let mut s = KeySerializer::new();
388		s.extend_bytes(b"foo");
389		assert_eq!(s.finish(), vec![0x66, 0x6f, 0x6f, 0xff, 0xff]);
390
391		// Test chaining
392		let mut s = KeySerializer::with_capacity(32);
393		s.extend_bool(true).extend_u32(1u32).extend_i16(-1i16).extend_bytes(b"test");
394		let result = s.finish();
395		assert!(!result.is_empty());
396		assert!(result.len() > 10); // Should have all the encoded values
397	}
398}