Skip to main content

reifydb_core/interface/catalog/
shape.rs

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