Skip to main content

reifydb_core/key/
row.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2026 ReifyDB
3
4use std::collections::Bound;
5
6use reifydb_codec::key::{
7	deserializer::KeyDeserializer,
8	encoded::{EncodedKey, EncodedKeyRange},
9	serializer::KeySerializer,
10};
11use reifydb_value::value::row_number::RowNumber;
12
13use super::{EncodableKey, EncodableKeyRange, KeyKind};
14use crate::{
15	interface::catalog::shape::ShapeId,
16	key::catalog::{KeyDeserializerCatalogExt, KeySerializerCatalogExt},
17};
18
19#[derive(Debug, Clone, PartialEq)]
20pub struct RowKey {
21	pub shape: ShapeId,
22	pub row: RowNumber,
23}
24
25impl EncodableKey for RowKey {
26	const KIND: KeyKind = KeyKind::Row;
27
28	fn encode(&self) -> EncodedKey {
29		let mut serializer = KeySerializer::with_capacity(18);
30		serializer.extend_u8(Self::KIND as u8).extend_shape_id(self.shape).extend_u64(self.row.0);
31		serializer.to_encoded_key()
32	}
33
34	fn decode(key: &EncodedKey) -> Option<Self> {
35		let mut de = KeyDeserializer::from_bytes(key.as_slice());
36
37		let kind: KeyKind = de.read_u8().ok()?.try_into().ok()?;
38		if kind != Self::KIND {
39			return None;
40		}
41
42		let shape = de.read_shape_id().ok()?;
43		let row = de.read_row_number().ok()?;
44
45		Some(Self {
46			shape,
47			row,
48		})
49	}
50}
51
52#[derive(Debug, Clone, PartialEq)]
53pub struct RowKeyRange {
54	pub shape: ShapeId,
55}
56
57impl RowKeyRange {
58	fn decode_key(key: &EncodedKey) -> Option<Self> {
59		let mut de = KeyDeserializer::from_bytes(key.as_slice());
60
61		let kind: KeyKind = de.read_u8().ok()?.try_into().ok()?;
62		if kind != Self::KIND {
63			return None;
64		}
65
66		let shape = de.read_shape_id().ok()?;
67
68		Some(RowKeyRange {
69			shape,
70		})
71	}
72
73	pub fn scan_range(shape: ShapeId, last_key: Option<&EncodedKey>) -> EncodedKeyRange {
74		let range = RowKeyRange {
75			shape,
76		};
77
78		if let Some(last_key) = last_key {
79			EncodedKeyRange::new(Bound::Excluded(last_key.clone()), Bound::Included(range.end().unwrap()))
80		} else {
81			EncodedKeyRange::new(
82				Bound::Included(range.start().unwrap()),
83				Bound::Included(range.end().unwrap()),
84			)
85		}
86	}
87}
88
89impl EncodableKeyRange for RowKeyRange {
90	const KIND: KeyKind = KeyKind::Row;
91
92	fn start(&self) -> Option<EncodedKey> {
93		let mut serializer = KeySerializer::with_capacity(10);
94		serializer.extend_u8(Self::KIND as u8).extend_shape_id(self.shape);
95		Some(serializer.to_encoded_key())
96	}
97
98	fn end(&self) -> Option<EncodedKey> {
99		let mut serializer = KeySerializer::with_capacity(10);
100		serializer.extend_u8(Self::KIND as u8).extend_shape_id(self.shape.prev());
101		Some(serializer.to_encoded_key())
102	}
103
104	fn decode(range: &EncodedKeyRange) -> (Option<Self>, Option<Self>)
105	where
106		Self: Sized,
107	{
108		let start_key = match &range.start {
109			Bound::Included(key) | Bound::Excluded(key) => Self::decode_key(key),
110			Bound::Unbounded => None,
111		};
112
113		let end_key = match &range.end {
114			Bound::Included(key) | Bound::Excluded(key) => Self::decode_key(key),
115			Bound::Unbounded => None,
116		};
117
118		(start_key, end_key)
119	}
120}
121
122impl RowKey {
123	pub fn encoded(shape: impl Into<ShapeId>, row: impl Into<RowNumber>) -> EncodedKey {
124		Self {
125			shape: shape.into(),
126			row: row.into(),
127		}
128		.encode()
129	}
130
131	pub fn full_scan(shape: impl Into<ShapeId>) -> EncodedKeyRange {
132		let shape = shape.into();
133		EncodedKeyRange::start_end(Some(Self::shape_start(shape)), Some(Self::shape_end(shape)))
134	}
135
136	pub fn shape_start(shape: impl Into<ShapeId>) -> EncodedKey {
137		let shape = shape.into();
138		let mut serializer = KeySerializer::with_capacity(10);
139		serializer.extend_u8(Self::KIND as u8).extend_shape_id(shape);
140		serializer.to_encoded_key()
141	}
142
143	pub fn shape_end(shape: impl Into<ShapeId>) -> EncodedKey {
144		let shape = shape.into();
145		let mut serializer = KeySerializer::with_capacity(10);
146		serializer.extend_u8(Self::KIND as u8).extend_shape_id(shape.prev());
147		serializer.to_encoded_key()
148	}
149}
150
151#[cfg(test)]
152pub mod tests {
153	use reifydb_value::value::row_number::RowNumber;
154
155	use super::{EncodableKey, RowKey};
156	use crate::interface::catalog::shape::ShapeId;
157
158	#[test]
159	fn test_encode_decode() {
160		let key = RowKey {
161			shape: ShapeId::table(0xABCD),
162			row: RowNumber(0x123456789ABCDEF0),
163		};
164		let encoded = key.encode();
165
166		let expected: Vec<u8> =
167			vec![0xFC, 0x01, 0x3F, 0x54, 0x32, 0x00, 0xED, 0xCB, 0xA9, 0x87, 0x65, 0x43, 0x21, 0x0F];
168
169		assert_eq!(encoded.as_slice(), expected);
170
171		let key = RowKey::decode(&encoded).unwrap();
172		assert_eq!(key.shape, ShapeId::table(0xABCD));
173		assert_eq!(key.row, 0x123456789ABCDEF0);
174	}
175
176	#[test]
177	fn test_order_preserving() {
178		let key1 = RowKey {
179			shape: ShapeId::table(1),
180			row: RowNumber(100),
181		};
182		let key2 = RowKey {
183			shape: ShapeId::table(1),
184			row: RowNumber(200),
185		};
186		let key3 = RowKey {
187			shape: ShapeId::table(2),
188			row: RowNumber(1),
189		};
190
191		let encoded1 = key1.encode();
192		let encoded2 = key2.encode();
193		let encoded3 = key3.encode();
194
195		assert!(encoded3 < encoded2, "ordering not preserved");
196		assert!(encoded2 < encoded1, "ordering not preserved");
197	}
198}