Skip to main content

reifydb_core/key/
schema.rs

1// SPDX-License-Identifier: AGPL-3.0-or-later
2// Copyright (c) 2025 ReifyDB
3
4use super::{EncodableKey, KeyKind};
5use crate::{
6	encoded::{
7		key::{EncodedKey, EncodedKeyRange},
8		schema::fingerprint::SchemaFingerprint,
9	},
10	util::encoding::keycode::{deserializer::KeyDeserializer, serializer::KeySerializer},
11};
12
13/// Key for storing a schema definition by its fingerprint
14#[derive(Debug, Clone, PartialEq)]
15pub struct SchemaKey {
16	pub fingerprint: SchemaFingerprint,
17}
18
19const VERSION: u8 = 1;
20
21impl EncodableKey for SchemaKey {
22	const KIND: KeyKind = KeyKind::Schema;
23
24	fn encode(&self) -> EncodedKey {
25		let mut serializer = KeySerializer::with_capacity(10);
26		serializer.extend_u8(VERSION).extend_u8(Self::KIND as u8).extend_u64(self.fingerprint.as_u64());
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 version = de.read_u8().ok()?;
34		if version != VERSION {
35			return None;
36		}
37
38		let kind: KeyKind = de.read_u8().ok()?.try_into().ok()?;
39		if kind != Self::KIND {
40			return None;
41		}
42
43		let fingerprint = de.read_u64().ok()?;
44
45		Some(Self {
46			fingerprint: SchemaFingerprint::new(fingerprint),
47		})
48	}
49}
50
51impl SchemaKey {
52	pub fn encoded(fingerprint: SchemaFingerprint) -> EncodedKey {
53		Self {
54			fingerprint,
55		}
56		.encode()
57	}
58
59	pub fn full_scan() -> EncodedKeyRange {
60		EncodedKeyRange::start_end(Some(Self::scan_start()), Some(Self::scan_end()))
61	}
62
63	fn scan_start() -> EncodedKey {
64		let mut serializer = KeySerializer::with_capacity(2);
65		serializer.extend_u8(VERSION).extend_u8(Self::KIND as u8);
66		serializer.to_encoded_key()
67	}
68
69	fn scan_end() -> EncodedKey {
70		let mut serializer = KeySerializer::with_capacity(2);
71		serializer.extend_u8(VERSION).extend_u8(Self::KIND as u8 - 1);
72		serializer.to_encoded_key()
73	}
74}
75
76/// Key for storing individual schema fields
77/// Keyed by (schema_fingerprint, field_index) for ordered retrieval
78#[derive(Debug, Clone, PartialEq)]
79pub struct SchemaFieldKey {
80	pub schema_fingerprint: SchemaFingerprint,
81	pub field_index: u16,
82}
83
84impl EncodableKey for SchemaFieldKey {
85	const KIND: KeyKind = KeyKind::SchemaField;
86
87	fn encode(&self) -> EncodedKey {
88		let mut serializer = KeySerializer::with_capacity(11);
89		serializer
90			.extend_u8(VERSION)
91			.extend_u8(Self::KIND as u8)
92			.extend_u64(self.schema_fingerprint.as_u64())
93			.extend_u16(self.field_index);
94		serializer.to_encoded_key()
95	}
96
97	fn decode(key: &EncodedKey) -> Option<Self> {
98		let mut de = KeyDeserializer::from_bytes(key.as_slice());
99
100		let version = de.read_u8().ok()?;
101		if version != VERSION {
102			return None;
103		}
104
105		let kind: KeyKind = de.read_u8().ok()?.try_into().ok()?;
106		if kind != Self::KIND {
107			return None;
108		}
109
110		let schema_fingerprint = de.read_u64().ok()?;
111		let field_index = de.read_u16().ok()?;
112
113		Some(Self {
114			schema_fingerprint: SchemaFingerprint::new(schema_fingerprint),
115			field_index,
116		})
117	}
118}
119
120impl SchemaFieldKey {
121	pub fn encoded(schema_fingerprint: SchemaFingerprint, field_index: u16) -> EncodedKey {
122		Self {
123			schema_fingerprint,
124			field_index,
125		}
126		.encode()
127	}
128
129	/// Scan all fields for a given schema
130	pub fn scan_for_schema(fingerprint: SchemaFingerprint) -> EncodedKeyRange {
131		EncodedKeyRange::start_end(Some(Self::schema_start(fingerprint)), Some(Self::schema_end(fingerprint)))
132	}
133
134	fn schema_start(fingerprint: SchemaFingerprint) -> EncodedKey {
135		let mut serializer = KeySerializer::with_capacity(10);
136		serializer.extend_u8(VERSION).extend_u8(Self::KIND as u8).extend_u64(fingerprint.as_u64());
137		serializer.to_encoded_key()
138	}
139
140	fn schema_end(fingerprint: SchemaFingerprint) -> EncodedKey {
141		let mut serializer = KeySerializer::with_capacity(11);
142		serializer
143			.extend_u8(VERSION)
144			.extend_u8(Self::KIND as u8)
145			.extend_u64(fingerprint.as_u64())
146			.extend_u8(0xFF);
147		serializer.to_encoded_key()
148	}
149}
150
151#[cfg(test)]
152mod tests {
153	use super::*;
154
155	#[test]
156	fn test_schema_key_encode_decode() {
157		let key = SchemaKey {
158			fingerprint: SchemaFingerprint::new(0xDEADBEEFCAFEBABE),
159		};
160		let encoded = key.encode();
161		let decoded = SchemaKey::decode(&encoded).unwrap();
162		assert_eq!(decoded.fingerprint, SchemaFingerprint::new(0xDEADBEEFCAFEBABE));
163	}
164
165	#[test]
166	fn test_schema_field_key_encode_decode() {
167		let key = SchemaFieldKey {
168			schema_fingerprint: SchemaFingerprint::new(0x1234567890ABCDEF),
169			field_index: 42,
170		};
171		let encoded = key.encode();
172		let decoded = SchemaFieldKey::decode(&encoded).unwrap();
173		assert_eq!(decoded.schema_fingerprint, SchemaFingerprint::new(0x1234567890ABCDEF));
174		assert_eq!(decoded.field_index, 42);
175	}
176}