Skip to main content

reifydb_core/key/
flow_node_internal_state.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2026 ReifyDB
3
4use std::ops::Bound;
5
6use super::{EncodableKey, EncodableKeyRange, KeyKind};
7use crate::{
8	encoded::key::{EncodedKey, EncodedKeyRange},
9	interface::catalog::flow::FlowNodeId,
10	util::encoding::keycode::{deserializer::KeyDeserializer, serializer::KeySerializer},
11};
12
13#[derive(Debug, Clone, PartialEq, Eq)]
14pub struct FlowNodeInternalStateKey {
15	pub node: FlowNodeId,
16	pub key: Vec<u8>,
17}
18
19impl EncodableKey for FlowNodeInternalStateKey {
20	const KIND: KeyKind = KeyKind::FlowNodeInternalState;
21
22	fn encode(&self) -> EncodedKey {
23		let mut serializer = KeySerializer::with_capacity(10 + self.key.len());
24		serializer.extend_u8(Self::KIND as u8).extend_u64(self.node.0).extend_raw(&self.key);
25		serializer.to_encoded_key()
26	}
27
28	fn decode(key: &EncodedKey) -> Option<Self> {
29		let mut de = KeyDeserializer::from_bytes(key.as_slice());
30
31		let kind: KeyKind = de.read_u8().ok()?.try_into().ok()?;
32		if kind != Self::KIND {
33			return None;
34		}
35
36		let node_id = de.read_u64().ok()?;
37		let key_bytes = de.read_raw(de.remaining()).ok()?.to_vec();
38
39		Some(Self {
40			node: FlowNodeId(node_id),
41			key: key_bytes,
42		})
43	}
44}
45
46impl FlowNodeInternalStateKey {
47	pub const ROW_NUMBER_COUNTER_TAG: u8 = b'C';
48
49	pub const ROW_NUMBER_MAPPING_TAG: u8 = b'M';
50
51	pub const WINDOW_META_TAG: u8 = b'W';
52
53	pub const WINDOW_EXPIRY_TAG: u8 = b'X';
54
55	pub const GATE_VISIBILITY_TAG: u8 = b'G';
56
57	pub fn is_row_number_counter(&self) -> bool {
58		self.key.as_slice() == [Self::ROW_NUMBER_COUNTER_TAG]
59	}
60
61	pub fn is_row_number_mapping(&self) -> bool {
62		self.key.first() == Some(&Self::ROW_NUMBER_MAPPING_TAG)
63	}
64
65	pub fn is_window_meta(&self) -> bool {
66		self.key.first() == Some(&Self::WINDOW_META_TAG)
67	}
68
69	pub fn is_window_expiry(&self) -> bool {
70		self.key.first() == Some(&Self::WINDOW_EXPIRY_TAG)
71	}
72
73	pub fn is_gate_visibility(&self) -> bool {
74		self.key.first() == Some(&Self::GATE_VISIBILITY_TAG)
75	}
76
77	pub fn new(node: FlowNodeId, key: Vec<u8>) -> Self {
78		Self {
79			node,
80			key,
81		}
82	}
83
84	pub fn new_empty(node: FlowNodeId) -> Self {
85		Self {
86			node,
87			key: Vec::new(),
88		}
89	}
90
91	pub fn encoded(node: impl Into<FlowNodeId>, key: impl Into<Vec<u8>>) -> EncodedKey {
92		Self::new(node.into(), key.into()).encode()
93	}
94
95	pub fn node_range(node: FlowNodeId) -> EncodedKeyRange {
96		let range = FlowNodeInternalStateKeyRange::new(node);
97		EncodedKeyRange::start_end(range.start(), range.end())
98	}
99}
100
101#[derive(Debug, Clone, PartialEq, Eq)]
102pub struct FlowNodeInternalStateKeyRange {
103	pub node: FlowNodeId,
104}
105
106impl FlowNodeInternalStateKeyRange {
107	pub fn new(node: FlowNodeId) -> Self {
108		Self {
109			node,
110		}
111	}
112
113	fn decode_key(key: &EncodedKey) -> Option<Self> {
114		let mut de = KeyDeserializer::from_bytes(key.as_slice());
115
116		let kind: KeyKind = de.read_u8().ok()?.try_into().ok()?;
117		if kind != FlowNodeInternalStateKey::KIND {
118			return None;
119		}
120
121		let node_id = de.read_u64().ok()?;
122
123		Some(Self {
124			node: FlowNodeId(node_id),
125		})
126	}
127}
128
129impl EncodableKeyRange for FlowNodeInternalStateKeyRange {
130	const KIND: KeyKind = KeyKind::FlowNodeInternalState;
131
132	fn start(&self) -> Option<EncodedKey> {
133		let mut serializer = KeySerializer::with_capacity(9);
134		serializer.extend_u8(Self::KIND as u8).extend_u64(self.node.0);
135		Some(serializer.to_encoded_key())
136	}
137
138	fn end(&self) -> Option<EncodedKey> {
139		let mut serializer = KeySerializer::with_capacity(9);
140		serializer.extend_u8(Self::KIND as u8).extend_u64(self.node.0.wrapping_sub(1));
141		Some(serializer.to_encoded_key())
142	}
143
144	fn decode(range: &EncodedKeyRange) -> (Option<Self>, Option<Self>)
145	where
146		Self: Sized,
147	{
148		let start_key = match &range.start {
149			Bound::Included(key) | Bound::Excluded(key) => Self::decode_key(key),
150			Bound::Unbounded => None,
151		};
152
153		let end_key = match &range.end {
154			Bound::Included(key) | Bound::Excluded(key) => Self::decode_key(key),
155			Bound::Unbounded => None,
156		};
157
158		(start_key, end_key)
159	}
160}
161
162#[cfg(test)]
163pub mod tests {
164	use super::{EncodableKey, EncodableKeyRange, FlowNodeInternalStateKey, FlowNodeInternalStateKeyRange};
165	use crate::{
166		encoded::key::{EncodedKey, EncodedKeyRange},
167		interface::catalog::flow::FlowNodeId,
168	};
169
170	#[test]
171	fn test_encode_decode() {
172		let key = FlowNodeInternalStateKey {
173			node: FlowNodeId(0xDEADBEEF),
174			key: vec![1, 2, 3, 4],
175		};
176		let encoded = key.encode();
177
178		assert_eq!(encoded[0], 0xE0);
179
180		let decoded = FlowNodeInternalStateKey::decode(&encoded).unwrap();
181		assert_eq!(decoded.node.0, 0xDEADBEEF);
182		assert_eq!(decoded.key, vec![1, 2, 3, 4]);
183	}
184
185	#[test]
186	fn test_encode_decode_empty_key() {
187		let key = FlowNodeInternalStateKey {
188			node: FlowNodeId(0xDEADBEEF),
189			key: vec![],
190		};
191		let encoded = key.encode();
192
193		let decoded = FlowNodeInternalStateKey::decode(&encoded).unwrap();
194		assert_eq!(decoded.node.0, 0xDEADBEEF);
195		assert_eq!(decoded.key, Vec::<u8>::new());
196	}
197
198	#[test]
199	fn test_new() {
200		let key = FlowNodeInternalStateKey::new(FlowNodeId(42), vec![5, 6, 7]);
201		assert_eq!(key.node.0, 42);
202		assert_eq!(key.key, vec![5, 6, 7]);
203	}
204
205	#[test]
206	fn test_new_empty() {
207		let key = FlowNodeInternalStateKey::new_empty(FlowNodeId(42));
208		assert_eq!(key.node.0, 42);
209		assert_eq!(key.key, Vec::<u8>::new());
210	}
211
212	#[test]
213	fn test_roundtrip() {
214		let original = FlowNodeInternalStateKey {
215			node: FlowNodeId(999_999_999),
216			key: vec![10, 20, 30, 40, 50],
217		};
218		let encoded = original.encode();
219		let decoded = FlowNodeInternalStateKey::decode(&encoded).unwrap();
220		assert_eq!(original, decoded);
221	}
222
223	#[test]
224	fn test_decode_invalid_version() {
225		let mut encoded = Vec::new();
226		encoded.push(0xFF);
227		encoded.push(0xE5);
228		encoded.extend(&999u64.to_be_bytes());
229		let key = EncodedKey::new(encoded);
230		assert!(FlowNodeInternalStateKey::decode(&key).is_none());
231	}
232
233	#[test]
234	fn test_decode_invalid_kind() {
235		let mut encoded = Vec::new();
236		encoded.push(0xFE);
237		encoded.push(0xFF);
238		encoded.extend(&999u64.to_be_bytes());
239		let key = EncodedKey::new(encoded);
240		assert!(FlowNodeInternalStateKey::decode(&key).is_none());
241	}
242
243	#[test]
244	fn test_decode_too_short() {
245		let mut encoded = Vec::new();
246		encoded.push(0xFE);
247		encoded.push(0xE5);
248		encoded.extend(&999u32.to_be_bytes());
249		let key = EncodedKey::new(encoded);
250		assert!(FlowNodeInternalStateKey::decode(&key).is_none());
251	}
252
253	#[test]
254	fn test_flow_node_internal_state_key_range() {
255		let node = FlowNodeId(42);
256		let range = FlowNodeInternalStateKeyRange::new(node);
257
258		let start = range.start().unwrap();
259		let decoded_start = FlowNodeInternalStateKey::decode(&start).unwrap();
260		assert_eq!(decoded_start.node, node);
261		assert_eq!(decoded_start.key, Vec::<u8>::new());
262
263		let end = range.end().unwrap();
264		let decoded_end = FlowNodeInternalStateKey::decode(&end).unwrap();
265		assert_eq!(decoded_end.node.0, 41);
266		assert_eq!(decoded_end.key, Vec::<u8>::new());
267	}
268
269	#[test]
270	fn test_flow_node_internal_state_key_range_decode() {
271		let node = FlowNodeId(100);
272		let range = FlowNodeInternalStateKeyRange::new(node);
273
274		let encoded_range = EncodedKeyRange::start_end(range.start(), range.end());
275
276		let (start_decoded, end_decoded) = FlowNodeInternalStateKeyRange::decode(&encoded_range);
277
278		assert!(start_decoded.is_some());
279		assert_eq!(start_decoded.unwrap().node, node);
280
281		assert!(end_decoded.is_some());
282		assert_eq!(end_decoded.unwrap().node.0, 99);
283	}
284}