Skip to main content

reifydb_core/interface/catalog/
primitive.rs

1// SPDX-License-Identifier: AGPL-3.0-or-later
2// Copyright (c) 2025 ReifyDB
3
4use reifydb_type::value::dictionary::DictionaryId;
5use serde::{Deserialize, Serialize};
6
7use crate::{
8	interface::catalog::{
9		flow::{FlowDef, FlowId},
10		id::{RingBufferId, TableId, ViewId},
11		table::TableDef,
12		view::ViewDef,
13		vtable::{VTableDef, VTableId},
14	},
15	return_internal_error,
16};
17
18/// PrimitiveId represents identifiers for catalog primitives that use u64-based IDs.
19#[derive(Debug, Copy, Clone, PartialOrd, PartialEq, Ord, Eq, Hash, Serialize, Deserialize)]
20pub enum PrimitiveId {
21	Table(TableId),
22	View(ViewId),
23	Flow(FlowId),
24	TableVirtual(VTableId),
25	RingBuffer(RingBufferId),
26	Dictionary(DictionaryId),
27}
28
29impl std::fmt::Display for PrimitiveId {
30	fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
31		match self {
32			PrimitiveId::Table(id) => write!(f, "{}", id.0),
33			PrimitiveId::View(id) => write!(f, "{}", id.0),
34			PrimitiveId::Flow(id) => write!(f, "{}", id.0),
35			PrimitiveId::TableVirtual(id) => write!(f, "{}", id.0),
36			PrimitiveId::RingBuffer(id) => write!(f, "{}", id.0),
37			PrimitiveId::Dictionary(id) => write!(f, "{}", id.0),
38		}
39	}
40}
41
42impl PrimitiveId {
43	pub fn table(id: impl Into<TableId>) -> Self {
44		Self::Table(id.into())
45	}
46
47	pub fn view(id: impl Into<ViewId>) -> Self {
48		Self::View(id.into())
49	}
50
51	pub fn flow(id: impl Into<FlowId>) -> Self {
52		Self::Flow(id.into())
53	}
54
55	pub fn vtable(id: impl Into<VTableId>) -> Self {
56		Self::TableVirtual(id.into())
57	}
58
59	pub fn ringbuffer(id: impl Into<RingBufferId>) -> Self {
60		Self::RingBuffer(id.into())
61	}
62
63	pub fn dictionary(id: impl Into<DictionaryId>) -> Self {
64		Self::Dictionary(id.into())
65	}
66
67	/// Get the inner u64 value from the ID variant.
68	#[inline]
69	pub fn to_u64(self) -> u64 {
70		match self {
71			PrimitiveId::Table(id) => id.to_u64(),
72			PrimitiveId::View(id) => id.to_u64(),
73			PrimitiveId::Flow(id) => id.to_u64(),
74			PrimitiveId::TableVirtual(id) => id.to_u64(),
75			PrimitiveId::RingBuffer(id) => id.to_u64(),
76			PrimitiveId::Dictionary(id) => id.to_u64(),
77		}
78	}
79}
80
81impl From<TableId> for PrimitiveId {
82	fn from(id: TableId) -> Self {
83		PrimitiveId::Table(id)
84	}
85}
86
87impl From<ViewId> for PrimitiveId {
88	fn from(id: ViewId) -> Self {
89		PrimitiveId::View(id)
90	}
91}
92
93impl From<FlowId> for PrimitiveId {
94	fn from(id: FlowId) -> Self {
95		PrimitiveId::Flow(id)
96	}
97}
98
99impl From<VTableId> for PrimitiveId {
100	fn from(id: VTableId) -> Self {
101		PrimitiveId::TableVirtual(id)
102	}
103}
104
105impl From<RingBufferId> for PrimitiveId {
106	fn from(id: RingBufferId) -> Self {
107		PrimitiveId::RingBuffer(id)
108	}
109}
110
111impl From<DictionaryId> for PrimitiveId {
112	fn from(id: DictionaryId) -> Self {
113		PrimitiveId::Dictionary(id)
114	}
115}
116
117impl PartialEq<u64> for PrimitiveId {
118	fn eq(&self, other: &u64) -> bool {
119		match self {
120			PrimitiveId::Table(id) => id.0.eq(other),
121			PrimitiveId::View(id) => id.0.eq(other),
122			PrimitiveId::Flow(id) => id.0.eq(other),
123			PrimitiveId::TableVirtual(id) => id.0.eq(other),
124			PrimitiveId::RingBuffer(id) => id.0.eq(other),
125			PrimitiveId::Dictionary(id) => id.0.eq(other),
126		}
127	}
128}
129
130impl PartialEq<TableId> for PrimitiveId {
131	fn eq(&self, other: &TableId) -> bool {
132		match self {
133			PrimitiveId::Table(id) => id.0 == other.0,
134			_ => false,
135		}
136	}
137}
138
139impl PartialEq<ViewId> for PrimitiveId {
140	fn eq(&self, other: &ViewId) -> bool {
141		match self {
142			PrimitiveId::View(id) => id.0 == other.0,
143			_ => false,
144		}
145	}
146}
147
148impl PartialEq<FlowId> for PrimitiveId {
149	fn eq(&self, other: &FlowId) -> bool {
150		match self {
151			PrimitiveId::Flow(id) => id.0 == other.0,
152			_ => false,
153		}
154	}
155}
156
157impl PartialEq<VTableId> for PrimitiveId {
158	fn eq(&self, other: &VTableId) -> bool {
159		match self {
160			PrimitiveId::TableVirtual(id) => id.0 == other.0,
161			_ => false,
162		}
163	}
164}
165
166impl PartialEq<RingBufferId> for PrimitiveId {
167	fn eq(&self, other: &RingBufferId) -> bool {
168		match self {
169			PrimitiveId::RingBuffer(id) => id.0 == other.0,
170			_ => false,
171		}
172	}
173}
174
175impl PartialEq<DictionaryId> for PrimitiveId {
176	fn eq(&self, other: &DictionaryId) -> bool {
177		match self {
178			PrimitiveId::Dictionary(id) => id.0 == other.0,
179			_ => false,
180		}
181	}
182}
183
184impl From<PrimitiveId> for u64 {
185	fn from(primitive: PrimitiveId) -> u64 {
186		primitive.as_u64()
187	}
188}
189
190impl PrimitiveId {
191	/// Returns the type discriminant as a u8 value
192	pub fn to_type_u8(&self) -> u8 {
193		match self {
194			PrimitiveId::Table(_) => 1,
195			PrimitiveId::View(_) => 2,
196			PrimitiveId::Flow(_) => 3,
197			PrimitiveId::TableVirtual(_) => 4,
198			PrimitiveId::RingBuffer(_) => 5,
199			PrimitiveId::Dictionary(_) => 6,
200		}
201	}
202
203	/// Returns the raw u64 value regardless of the primitive type
204	pub fn as_u64(&self) -> u64 {
205		match self {
206			PrimitiveId::Table(id) => id.0,
207			PrimitiveId::View(id) => id.0,
208			PrimitiveId::Flow(id) => id.0,
209			PrimitiveId::TableVirtual(id) => id.0,
210			PrimitiveId::RingBuffer(id) => id.0,
211			PrimitiveId::Dictionary(id) => id.0,
212		}
213	}
214
215	/// Creates a next primitive id for range operations (numerically next)
216	pub fn next(&self) -> PrimitiveId {
217		match self {
218			PrimitiveId::Table(table) => PrimitiveId::table(table.0 + 1),
219			PrimitiveId::View(view) => PrimitiveId::view(view.0 + 1),
220			PrimitiveId::Flow(flow) => PrimitiveId::flow(flow.0 + 1),
221			PrimitiveId::TableVirtual(vtable) => PrimitiveId::vtable(vtable.0 + 1),
222			PrimitiveId::RingBuffer(ringbuffer) => PrimitiveId::ringbuffer(ringbuffer.0 + 1),
223			PrimitiveId::Dictionary(dictionary) => PrimitiveId::dictionary(dictionary.0 + 1),
224		}
225	}
226
227	/// Creates a previous primitive id for range operations (numerically
228	/// previous) In descending order encoding, this gives us the next
229	/// value in sort order Uses wrapping_sub to handle ID 0 correctly
230	/// (wraps to u64::MAX)
231	pub fn prev(&self) -> PrimitiveId {
232		match self {
233			PrimitiveId::Table(table) => PrimitiveId::table(table.0.wrapping_sub(1)),
234			PrimitiveId::View(view) => PrimitiveId::view(view.0.wrapping_sub(1)),
235			PrimitiveId::Flow(flow) => PrimitiveId::flow(flow.0.wrapping_sub(1)),
236			PrimitiveId::TableVirtual(vtable) => PrimitiveId::vtable(vtable.0.wrapping_sub(1)),
237			PrimitiveId::RingBuffer(ringbuffer) => PrimitiveId::ringbuffer(ringbuffer.0.wrapping_sub(1)),
238			PrimitiveId::Dictionary(dictionary) => PrimitiveId::dictionary(dictionary.0.wrapping_sub(1)),
239		}
240	}
241
242	pub fn to_table_id(self) -> reifydb_type::Result<TableId> {
243		if let PrimitiveId::Table(table) = self {
244			Ok(table)
245		} else {
246			return_internal_error!(
247				"Data inconsistency: Expected PrimitiveId::Table but found {:?}. \
248				This indicates a critical catalog inconsistency where a non-table primitive ID \
249				was used in a context that requires a table ID.",
250				self
251			)
252		}
253	}
254
255	pub fn to_view_id(self) -> reifydb_type::Result<ViewId> {
256		if let PrimitiveId::View(view) = self {
257			Ok(view)
258		} else {
259			return_internal_error!(
260				"Data inconsistency: Expected PrimitiveId::View but found {:?}. \
261				This indicates a critical catalog inconsistency where a non-view primitive ID \
262				was used in a context that requires a view ID.",
263				self
264			)
265		}
266	}
267
268	pub fn to_flow_id(self) -> reifydb_type::Result<FlowId> {
269		if let PrimitiveId::Flow(flow) = self {
270			Ok(flow)
271		} else {
272			return_internal_error!(
273				"Data inconsistency: Expected PrimitiveId::Flow but found {:?}. \
274				This indicates a critical catalog inconsistency where a non-flow primitive ID \
275				was used in a context that requires a flow ID.",
276				self
277			)
278		}
279	}
280
281	pub fn to_vtable_id(self) -> reifydb_type::Result<VTableId> {
282		if let PrimitiveId::TableVirtual(vtable) = self {
283			Ok(vtable)
284		} else {
285			return_internal_error!(
286				"Data inconsistency: Expected PrimitiveId::TableVirtual but found {:?}. \
287				This indicates a critical catalog inconsistency where a non-virtual-table primitive ID \
288				was used in a context that requires a virtual table ID.",
289				self
290			)
291		}
292	}
293
294	pub fn to_ringbuffer_id(self) -> reifydb_type::Result<RingBufferId> {
295		if let PrimitiveId::RingBuffer(ringbuffer) = self {
296			Ok(ringbuffer)
297		} else {
298			return_internal_error!(
299				"Data inconsistency: Expected PrimitiveId::RingBuffer but found {:?}. \
300				This indicates a critical catalog inconsistency where a non-ring-buffer primitive ID \
301				was used in a context that requires a ring buffer ID.",
302				self
303			)
304		}
305	}
306
307	pub fn to_dictionary_id(self) -> reifydb_type::Result<DictionaryId> {
308		if let PrimitiveId::Dictionary(dictionary) = self {
309			Ok(dictionary)
310		} else {
311			return_internal_error!(
312				"Data inconsistency: Expected PrimitiveId::Dictionary but found {:?}. \
313				This indicates a critical catalog inconsistency where a non-dictionary primitive ID \
314				was used in a context that requires a dictionary ID.",
315				self
316			)
317		}
318	}
319}
320
321#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
322pub enum PrimitiveDef {
323	Table(TableDef),
324	View(ViewDef),
325	Flow(FlowDef),
326	TableVirtual(VTableDef),
327}
328
329impl PrimitiveDef {
330	pub fn id(&self) -> PrimitiveId {
331		match self {
332			PrimitiveDef::Table(table) => table.id.into(),
333			PrimitiveDef::View(view) => view.id.into(),
334			PrimitiveDef::Flow(flow) => flow.id.into(),
335			PrimitiveDef::TableVirtual(vtable) => vtable.id.into(),
336		}
337	}
338
339	pub fn primitive_type(&self) -> PrimitiveId {
340		match self {
341			PrimitiveDef::Table(table) => PrimitiveId::Table(table.id),
342			PrimitiveDef::View(view) => PrimitiveId::View(view.id),
343			PrimitiveDef::Flow(flow) => PrimitiveId::Flow(flow.id),
344			PrimitiveDef::TableVirtual(vtable) => PrimitiveId::TableVirtual(vtable.id),
345		}
346	}
347}