Skip to main content

reifydb_core/key/
column.rs

1// SPDX-License-Identifier: AGPL-3.0-or-later
2// Copyright (c) 2025 ReifyDB
3
4use crate::{
5	encoded::key::{EncodedKey, EncodedKeyRange},
6	interface::catalog::{id::ColumnId, primitive::PrimitiveId},
7	key::{EncodableKey, KeyKind},
8	util::encoding::keycode::{deserializer::KeyDeserializer, serializer::KeySerializer},
9};
10
11#[derive(Debug, Clone, PartialEq)]
12pub struct ColumnKey {
13	pub primitive: PrimitiveId,
14	pub column: ColumnId,
15}
16
17const VERSION: u8 = 1;
18
19impl EncodableKey for ColumnKey {
20	const KIND: KeyKind = KeyKind::Column;
21
22	fn encode(&self) -> EncodedKey {
23		let mut serializer = KeySerializer::with_capacity(19); // 1 + 1 + 9 + 8
24		serializer
25			.extend_u8(VERSION)
26			.extend_u8(Self::KIND as u8)
27			.extend_primitive_id(self.primitive)
28			.extend_u64(self.column);
29		serializer.to_encoded_key()
30	}
31
32	fn decode(key: &EncodedKey) -> Option<Self> {
33		let mut de = KeyDeserializer::from_bytes(key.as_slice());
34
35		let version = de.read_u8().ok()?;
36		if version != VERSION {
37			return None;
38		}
39
40		let kind: KeyKind = de.read_u8().ok()?.try_into().ok()?;
41		if kind != Self::KIND {
42			return None;
43		}
44
45		let primitive = de.read_primitive_id().ok()?;
46		let column = de.read_u64().ok()?;
47
48		Some(Self {
49			primitive,
50			column: ColumnId(column),
51		})
52	}
53}
54
55impl ColumnKey {
56	pub fn encoded(primitive: impl Into<PrimitiveId>, column: impl Into<ColumnId>) -> EncodedKey {
57		Self {
58			primitive: primitive.into(),
59			column: column.into(),
60		}
61		.encode()
62	}
63
64	pub fn full_scan(primitive: impl Into<PrimitiveId>) -> EncodedKeyRange {
65		let primitive = primitive.into();
66		EncodedKeyRange::start_end(Some(Self::start(primitive)), Some(Self::end(primitive)))
67	}
68
69	fn start(primitive: PrimitiveId) -> EncodedKey {
70		let mut serializer = KeySerializer::with_capacity(11);
71		serializer.extend_u8(VERSION).extend_u8(Self::KIND as u8).extend_primitive_id(primitive);
72		serializer.to_encoded_key()
73	}
74
75	fn end(primitive: PrimitiveId) -> EncodedKey {
76		let mut serializer = KeySerializer::with_capacity(11);
77		serializer.extend_u8(VERSION).extend_u8(Self::KIND as u8).extend_primitive_id(primitive.prev());
78		serializer.to_encoded_key()
79	}
80}
81
82#[cfg(test)]
83pub mod tests {
84	use super::EncodableKey;
85	use crate::{
86		interface::catalog::{id::ColumnId, primitive::PrimitiveId},
87		key::ColumnKey,
88	};
89
90	#[test]
91	fn test_encode_decode() {
92		let key = ColumnKey {
93			primitive: PrimitiveId::table(0xABCD),
94			column: ColumnId(0x123456789ABCDEF0),
95		};
96		let encoded = key.encode();
97
98		let expected: Vec<u8> = vec![
99			0xFE, // version
100			0xF8, // kind
101			0x01, // PrimitiveId type discriminator (Table)
102			0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x54, 0x32, // primitive id bytes
103			0xED, 0xCB, 0xA9, 0x87, 0x65, 0x43, 0x21, 0x0F, // column id bytes
104		];
105
106		assert_eq!(encoded.as_slice(), expected);
107
108		let key = ColumnKey::decode(&encoded).unwrap();
109		assert_eq!(key.primitive, 0xABCD);
110		assert_eq!(key.column, 0x123456789ABCDEF0);
111	}
112
113	#[test]
114	fn test_order_preserving() {
115		let key1 = ColumnKey {
116			primitive: PrimitiveId::table(1),
117			column: ColumnId(100),
118		};
119		let key2 = ColumnKey {
120			primitive: PrimitiveId::table(1),
121			column: ColumnId(200),
122		};
123		let key3 = ColumnKey {
124			primitive: PrimitiveId::table(2),
125			column: ColumnId(0),
126		};
127
128		let encoded1 = key1.encode();
129		let encoded2 = key2.encode();
130		let encoded3 = key3.encode();
131
132		assert!(encoded3 < encoded2, "ordering not preserved");
133		assert!(encoded2 < encoded1, "ordering not preserved");
134	}
135}