Skip to main content

reifydb_core/key/
variant_handler.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2025 ReifyDB
3
4use reifydb_type::value::sumtype::SumTypeId;
5
6use crate::{
7	encoded::key::{EncodedKey, EncodedKeyRange},
8	interface::catalog::id::{HandlerId, NamespaceId},
9	key::{EncodableKey, KeyKind},
10	util::encoding::keycode::{deserializer::KeyDeserializer, serializer::KeySerializer},
11};
12
13#[derive(Debug, Clone, PartialEq)]
14pub struct VariantHandlerKey {
15	pub namespace: NamespaceId,
16	pub sumtype: SumTypeId,
17	pub variant_tag: u8,
18	pub handler: HandlerId,
19}
20
21impl VariantHandlerKey {
22	pub fn new(namespace: NamespaceId, sumtype: SumTypeId, variant_tag: u8, handler: HandlerId) -> Self {
23		Self {
24			namespace,
25			sumtype,
26			variant_tag,
27			handler,
28		}
29	}
30
31	pub fn encoded(
32		namespace: impl Into<NamespaceId>,
33		sumtype: impl Into<SumTypeId>,
34		variant_tag: u8,
35		handler: impl Into<HandlerId>,
36	) -> EncodedKey {
37		Self::new(namespace.into(), sumtype.into(), variant_tag, handler.into()).encode()
38	}
39
40	pub fn variant_scan(namespace: NamespaceId, sumtype: SumTypeId, variant_tag: u8) -> EncodedKeyRange {
41		EncodedKeyRange::start_end(
42			Some(Self::variant_start(namespace, sumtype, variant_tag)),
43			Some(Self::variant_end(namespace, sumtype, variant_tag)),
44		)
45	}
46
47	fn variant_start(namespace: NamespaceId, sumtype: SumTypeId, variant_tag: u8) -> EncodedKey {
48		let mut serializer = KeySerializer::with_capacity(18);
49		serializer.extend_u8(Self::KIND as u8).extend_u64(namespace).extend_u64(sumtype).extend_u8(variant_tag);
50		serializer.to_encoded_key()
51	}
52
53	fn variant_end(namespace: NamespaceId, sumtype: SumTypeId, variant_tag: u8) -> EncodedKey {
54		let mut serializer = KeySerializer::with_capacity(18);
55		serializer
56			.extend_u8(Self::KIND as u8)
57			.extend_u64(namespace)
58			.extend_u64(sumtype)
59			.extend_u8(variant_tag.wrapping_sub(1));
60		serializer.to_encoded_key()
61	}
62}
63
64impl EncodableKey for VariantHandlerKey {
65	const KIND: KeyKind = KeyKind::VariantHandler;
66
67	fn encode(&self) -> EncodedKey {
68		let mut serializer = KeySerializer::with_capacity(26);
69		serializer
70			.extend_u8(Self::KIND as u8)
71			.extend_u64(self.namespace)
72			.extend_u64(self.sumtype)
73			.extend_u8(self.variant_tag)
74			.extend_u64(self.handler);
75		serializer.to_encoded_key()
76	}
77
78	fn decode(key: &EncodedKey) -> Option<Self> {
79		let mut de = KeyDeserializer::from_bytes(key.as_slice());
80
81		let kind: KeyKind = de.read_u8().ok()?.try_into().ok()?;
82		if kind != Self::KIND {
83			return None;
84		}
85
86		let namespace = de.read_u64().ok()?;
87		let sumtype = de.read_u64().ok()?;
88		let variant_tag = de.read_u8().ok()?;
89		let handler = de.read_u64().ok()?;
90
91		Some(Self {
92			namespace: NamespaceId(namespace),
93			sumtype: SumTypeId(sumtype),
94			variant_tag,
95			handler: HandlerId(handler),
96		})
97	}
98}
99
100#[cfg(test)]
101pub mod tests {
102	use std::ops::Bound;
103
104	use reifydb_type::value::sumtype::SumTypeId;
105
106	use super::{EncodableKey, VariantHandlerKey};
107	use crate::interface::catalog::id::{HandlerId, NamespaceId};
108
109	#[test]
110	fn test_encode_decode() {
111		let key = VariantHandlerKey {
112			namespace: NamespaceId(0xABCD),
113			sumtype: SumTypeId(0x1234),
114			variant_tag: 5,
115			handler: HandlerId(0x6789),
116		};
117		let encoded = key.encode();
118		let expected: Vec<u8> = vec![0xCF, 0x3F, 0x54, 0x32, 0x6D, 0xCB, 0xFA, 0x3F, 0x98, 0x76];
119		assert_eq!(encoded.as_slice(), expected);
120
121		let decoded = VariantHandlerKey::decode(&encoded).unwrap();
122		assert_eq!(decoded.namespace, NamespaceId(0xABCD));
123		assert_eq!(decoded.sumtype, SumTypeId(0x1234));
124		assert_eq!(decoded.variant_tag, 5);
125		assert_eq!(decoded.handler, HandlerId(0x6789));
126	}
127
128	#[test]
129	fn test_order_preserving() {
130		let key1 = VariantHandlerKey {
131			namespace: NamespaceId::SYSTEM,
132			sumtype: SumTypeId(5),
133			variant_tag: 3,
134			handler: HandlerId(100),
135		};
136		let key2 = VariantHandlerKey {
137			namespace: NamespaceId::SYSTEM,
138			sumtype: SumTypeId(5),
139			variant_tag: 3,
140			handler: HandlerId(200),
141		};
142		let key3 = VariantHandlerKey {
143			namespace: NamespaceId::SYSTEM,
144			sumtype: SumTypeId(5),
145			variant_tag: 4,
146			handler: HandlerId(1),
147		};
148		let key4 = VariantHandlerKey {
149			namespace: NamespaceId::DEFAULT,
150			sumtype: SumTypeId(1),
151			variant_tag: 0,
152			handler: HandlerId(1),
153		};
154
155		let encoded1 = key1.encode();
156		let encoded2 = key2.encode();
157		let encoded3 = key3.encode();
158		let encoded4 = key4.encode();
159
160		assert!(encoded4 < encoded3, "ordering not preserved");
161		assert!(encoded3 < encoded2, "ordering not preserved");
162		assert!(encoded2 < encoded1, "ordering not preserved");
163	}
164
165	#[test]
166	fn test_variant_scan() {
167		let ns = NamespaceId::SYSTEM;
168		let st = SumTypeId(10);
169		let tag = 5u8;
170
171		let range = VariantHandlerKey::variant_scan(ns, st, tag);
172		let start = match &range.start {
173			Bound::Included(k) | Bound::Excluded(k) => k,
174			Bound::Unbounded => panic!("expected bounded start"),
175		};
176		let end = match &range.end {
177			Bound::Included(k) | Bound::Excluded(k) => k,
178			Bound::Unbounded => panic!("expected bounded end"),
179		};
180
181		let key = VariantHandlerKey {
182			namespace: ns,
183			sumtype: st,
184			variant_tag: tag,
185			handler: HandlerId(42),
186		};
187		let encoded = key.encode();
188		assert!(encoded.as_slice() >= start.as_slice());
189		assert!(encoded.as_slice() <= end.as_slice());
190
191		let other = VariantHandlerKey {
192			namespace: ns,
193			sumtype: st,
194			variant_tag: tag + 1,
195			handler: HandlerId(42),
196		};
197		let other_encoded = other.encode();
198		assert!(other_encoded.as_slice() < start.as_slice());
199	}
200}