Skip to main content

reifydb_core/key/
row.rs

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