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