reifydb_core/key/
output_frontier.rs1use reifydb_codec::key::{
5 deserializer::KeyDeserializer,
6 encoded::{EncodedKey, EncodedKeyRange},
7 serializer::KeySerializer,
8};
9
10use super::{EncodableKey, KeyKind};
11use crate::{
12 interface::catalog::object::ObjectId,
13 key::catalog::{KeyDeserializerCatalogExt, KeySerializerCatalogExt},
14};
15
16#[derive(Debug, Clone, PartialEq)]
17pub struct OutputFrontierKey {
18 pub object: ObjectId,
19}
20
21impl EncodableKey for OutputFrontierKey {
22 const KIND: KeyKind = KeyKind::OutputFrontier;
23
24 fn encode(&self) -> EncodedKey {
25 let mut serializer = KeySerializer::with_capacity(10);
26 serializer.extend_u8(Self::KIND as u8).extend_object_id(self.object);
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 object = de.read_object_id().ok()?;
39
40 Some(Self {
41 object,
42 })
43 }
44}
45
46impl OutputFrontierKey {
47 pub fn encoded(object: impl Into<ObjectId>) -> EncodedKey {
48 Self {
49 object: object.into(),
50 }
51 .encode()
52 }
53
54 pub fn full_scan() -> EncodedKeyRange {
55 EncodedKeyRange::start_end(Some(Self::frontier_start()), Some(Self::frontier_end()))
56 }
57
58 fn frontier_start() -> EncodedKey {
59 let mut serializer = KeySerializer::with_capacity(1);
60 serializer.extend_u8(Self::KIND as u8);
61 serializer.to_encoded_key()
62 }
63
64 fn frontier_end() -> EncodedKey {
65 let mut serializer = KeySerializer::with_capacity(1);
66 serializer.extend_u8(Self::KIND as u8 - 1);
67 serializer.to_encoded_key()
68 }
69}
70
71#[cfg(test)]
72pub mod tests {
73 use reifydb_codec::key::encoded::EncodedKey;
74
75 use super::{EncodableKey, OutputFrontierKey};
76 use crate::{
77 interface::catalog::{id::ViewId, object::ObjectId},
78 key::KeyKind,
79 };
80
81 #[test]
82 fn test_encode_decode() {
83 let key = OutputFrontierKey {
84 object: ObjectId::View(ViewId(0xABCD)),
85 };
86 let encoded = key.encode();
87 let decoded = OutputFrontierKey::decode(&encoded).unwrap();
88
89 assert_eq!(decoded.object, ObjectId::View(ViewId(0xABCD)));
90 assert_eq!(key, decoded);
91 }
92
93 #[test]
94 fn the_tag_byte_is_the_inverted_kind() {
95 let encoded = OutputFrontierKey::encoded(ObjectId::View(ViewId(1)));
97
98 assert_eq!(encoded.as_slice()[0], !(KeyKind::OutputFrontier as u8));
99 }
100
101 #[test]
102 fn a_key_of_another_kind_never_decodes_as_a_frontier() {
103 let mut foreign = OutputFrontierKey::encoded(ObjectId::View(ViewId(1))).as_slice().to_vec();
105 foreign[0] = !(KeyKind::FlowEdgeByFlow as u8);
106
107 assert!(OutputFrontierKey::decode(&EncodedKey::new(foreign)).is_none());
108 }
109
110 #[test]
111 fn every_object_kind_round_trips_under_the_one_frontier_tag() {
112 for object in [
114 ObjectId::table(1),
115 ObjectId::View(ViewId(2)),
116 ObjectId::series(3),
117 ObjectId::ringbuffer(4),
118 ObjectId::queue(5),
119 ] {
120 let encoded = OutputFrontierKey::encoded(object);
121
122 assert_eq!(
123 encoded.as_slice()[0],
124 !(KeyKind::OutputFrontier as u8),
125 "{:?} encoded under a foreign tag",
126 object
127 );
128 assert_eq!(OutputFrontierKey::decode(&encoded).unwrap().object, object);
129 }
130 }
131}