Skip to main content

reifydb_core/key/
ttl.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2025 ReifyDB
3
4use reifydb_type::value::dictionary::DictionaryId;
5use serde::{Deserialize, Serialize};
6
7use super::{EncodableKey, KeyKind};
8use crate::{
9	encoded::key::{EncodedKey, EncodedKeyRange},
10	interface::catalog::{
11		id::{RingBufferId, SeriesId, TableId, ViewId},
12		shape::ShapeId,
13		vtable::VTableId,
14	},
15	util::encoding::keycode::{deserializer::KeyDeserializer, serializer::KeySerializer},
16};
17
18const VERSION: u8 = 1;
19
20/// Key for storing TTL configuration for a data shape (table, ringbuffer, series)
21#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
22pub struct RowTtlKey {
23	pub shape: ShapeId,
24}
25
26impl RowTtlKey {
27	pub fn encoded(shape: impl Into<ShapeId>) -> EncodedKey {
28		Self {
29			shape: shape.into(),
30		}
31		.encode()
32	}
33}
34
35impl EncodableKey for RowTtlKey {
36	const KIND: KeyKind = KeyKind::RowTtl;
37
38	fn encode(&self) -> EncodedKey {
39		let mut serializer = KeySerializer::with_capacity(11);
40		serializer.extend_u8(VERSION).extend_u8(Self::KIND as u8);
41
42		match &self.shape {
43			ShapeId::Table(id) => {
44				serializer.extend_u8(0x01).extend_u64(id.0);
45			}
46			ShapeId::View(id) => {
47				serializer.extend_u8(0x02).extend_u64(id.0);
48			}
49			ShapeId::TableVirtual(id) => {
50				serializer.extend_u8(0x03).extend_u64(id.0);
51			}
52			ShapeId::RingBuffer(id) => {
53				serializer.extend_u8(0x04).extend_u64(id.0);
54			}
55			ShapeId::Dictionary(id) => {
56				serializer.extend_u8(0x06).extend_u64(id.0);
57			}
58			ShapeId::Series(id) => {
59				serializer.extend_u8(0x07).extend_u64(id.0);
60			}
61		}
62
63		serializer.to_encoded_key()
64	}
65
66	fn decode(key: &EncodedKey) -> Option<Self> {
67		let mut de = KeyDeserializer::from_bytes(key.as_slice());
68
69		let version = de.read_u8().ok()?;
70		if version != VERSION {
71			return None;
72		}
73
74		let kind: KeyKind = de.read_u8().ok()?.try_into().ok()?;
75		if kind != Self::KIND {
76			return None;
77		}
78
79		let discriminator = de.read_u8().ok()?;
80		let id = de.read_u64().ok()?;
81
82		let shape = match discriminator {
83			0x01 => ShapeId::Table(TableId(id)),
84			0x02 => ShapeId::View(ViewId(id)),
85			0x03 => ShapeId::TableVirtual(VTableId(id)),
86			0x04 => ShapeId::RingBuffer(RingBufferId(id)),
87			0x06 => ShapeId::Dictionary(DictionaryId(id)),
88			0x07 => ShapeId::Series(SeriesId(id)),
89			_ => return None,
90		};
91
92		Some(Self {
93			shape,
94		})
95	}
96}
97
98/// Range for scanning all shape TTL configurations
99pub struct RowTtlKeyRange;
100
101impl RowTtlKeyRange {
102	pub fn full_scan() -> EncodedKeyRange {
103		EncodedKeyRange::start_end(Some(Self::start()), Some(Self::end()))
104	}
105
106	fn start() -> EncodedKey {
107		let mut serializer = KeySerializer::with_capacity(2);
108		serializer.extend_u8(VERSION).extend_u8(RowTtlKey::KIND as u8);
109		serializer.to_encoded_key()
110	}
111
112	fn end() -> EncodedKey {
113		let mut serializer = KeySerializer::with_capacity(2);
114		serializer.extend_u8(VERSION).extend_u8(RowTtlKey::KIND as u8 - 1);
115		serializer.to_encoded_key()
116	}
117}
118
119#[cfg(test)]
120pub mod tests {
121	use super::*;
122
123	#[test]
124	fn test_row_ttl_key_encoding() {
125		let key = RowTtlKey {
126			shape: ShapeId::Table(TableId(42)),
127		};
128
129		let encoded = key.encode();
130		let decoded = RowTtlKey::decode(&encoded).unwrap();
131		assert_eq!(key, decoded);
132	}
133
134	#[test]
135	fn test_row_ttl_key_roundtrip_ringbuffer() {
136		let key = RowTtlKey {
137			shape: ShapeId::RingBuffer(RingBufferId(99)),
138		};
139
140		let encoded = key.encode();
141		let decoded = RowTtlKey::decode(&encoded).unwrap();
142		assert_eq!(key, decoded);
143	}
144
145	#[test]
146	fn test_row_ttl_key_roundtrip_series() {
147		let key = RowTtlKey {
148			shape: ShapeId::Series(SeriesId(7)),
149		};
150
151		let encoded = key.encode();
152		let decoded = RowTtlKey::decode(&encoded).unwrap();
153		assert_eq!(key, decoded);
154	}
155}