Skip to main content

reifydb_core/value/column/push/
mod.rs

1// SPDX-License-Identifier: AGPL-3.0-or-later
2// Copyright (c) 2025 ReifyDB
3
4use std::fmt::Debug;
5
6use reifydb_type::{
7	storage::DataBitVec,
8	value::{
9		blob::Blob, date::Date, datetime::DateTime, dictionary::DictionaryEntryId, duration::Duration,
10		number::safe::convert::SafeConvert, time::Time,
11	},
12};
13
14use crate::value::column::ColumnData;
15
16pub mod decimal;
17pub mod int;
18pub mod none;
19pub mod uint;
20pub mod uuid;
21pub mod value;
22
23pub trait Push<T> {
24	fn push(&mut self, value: T);
25}
26
27impl ColumnData {
28	pub fn push<T>(&mut self, value: T)
29	where
30		Self: Push<T>,
31		T: Debug,
32	{
33		<Self as Push<T>>::push(self, value)
34	}
35}
36
37macro_rules! impl_push {
38	($t:ty, $variant:ident, $factory:ident) => {
39		impl Push<$t> for ColumnData {
40			fn push(&mut self, value: $t) {
41				match self {
42					ColumnData::$variant(container) => {
43						container.push(value);
44					}
45					ColumnData::Option {
46						inner,
47						bitvec,
48					} => {
49						inner.push(value);
50						DataBitVec::push(bitvec, true);
51					}
52					other => panic!(
53						"called `push::<{}>()` on EngineColumnData::{:?}",
54						stringify!($t),
55						other.get_type()
56					),
57				}
58			}
59		}
60	};
61}
62
63macro_rules! impl_numeric_push {
64	($from:ty, $native_variant:ident, $factory:ident, $default:expr, [$(($variant:ident, $target:ty)),* $(,)?]) => {
65		impl Push<$from> for ColumnData {
66			fn push(&mut self, value: $from) {
67				match self {
68					$(
69						ColumnData::$variant(container) => match <$from as SafeConvert<$target>>::checked_convert(value) {
70							Some(v) => container.push(v),
71							None => container.push_default(),
72						},
73					)*
74					ColumnData::$native_variant(container) => {
75						container.push(value);
76					}
77					ColumnData::Option { inner, bitvec } => {
78						inner.push(value);
79						DataBitVec::push(bitvec, true);
80					}
81					other => {
82						panic!(
83							"called `push::<{}>()` on incompatible EngineColumnData::{:?}",
84							stringify!($from),
85							other.get_type()
86						);
87					}
88				}
89			}
90		}
91	};
92}
93
94impl Push<bool> for ColumnData {
95	fn push(&mut self, value: bool) {
96		match self {
97			ColumnData::Bool(container) => {
98				container.push(value);
99			}
100			ColumnData::Option {
101				inner,
102				bitvec,
103			} => {
104				inner.push(value);
105				DataBitVec::push(bitvec, true);
106			}
107			other => panic!("called `push::<bool>()` on EngineColumnData::{:?}", other.get_type()),
108		}
109	}
110}
111
112impl_push!(f32, Float4, float4);
113impl_push!(f64, Float8, float8);
114impl_push!(Date, Date, date);
115impl_push!(DateTime, DateTime, datetime);
116impl_push!(Time, Time, time);
117impl_push!(Duration, Duration, duration);
118
119// Signed integer push impls with cross-type SafeConvert
120impl_numeric_push!(
121	i8,
122	Int1,
123	int1,
124	0i8,
125	[
126		(Float4, f32),
127		(Float8, f64),
128		(Int2, i16),
129		(Int4, i32),
130		(Int8, i64),
131		(Int16, i128),
132		(Uint1, u8),
133		(Uint2, u16),
134		(Uint4, u32),
135		(Uint8, u64),
136		(Uint16, u128),
137	]
138);
139
140impl_numeric_push!(
141	i16,
142	Int2,
143	int2,
144	0i16,
145	[
146		(Float4, f32),
147		(Float8, f64),
148		(Int1, i8),
149		(Int4, i32),
150		(Int8, i64),
151		(Int16, i128),
152		(Uint1, u8),
153		(Uint2, u16),
154		(Uint4, u32),
155		(Uint8, u64),
156		(Uint16, u128),
157	]
158);
159
160impl_numeric_push!(
161	i32,
162	Int4,
163	int4,
164	0i32,
165	[
166		(Float4, f32),
167		(Float8, f64),
168		(Int1, i8),
169		(Int2, i16),
170		(Int8, i64),
171		(Int16, i128),
172		(Uint1, u8),
173		(Uint2, u16),
174		(Uint4, u32),
175		(Uint8, u64),
176		(Uint16, u128),
177	]
178);
179
180impl_numeric_push!(
181	i64,
182	Int8,
183	int8,
184	0i64,
185	[
186		(Float4, f32),
187		(Float8, f64),
188		(Int1, i8),
189		(Int2, i16),
190		(Int4, i32),
191		(Int16, i128),
192		(Uint1, u8),
193		(Uint2, u16),
194		(Uint4, u32),
195		(Uint8, u64),
196		(Uint16, u128),
197	]
198);
199
200impl_numeric_push!(
201	i128,
202	Int16,
203	int16,
204	0i128,
205	[
206		(Float4, f32),
207		(Float8, f64),
208		(Int1, i8),
209		(Int2, i16),
210		(Int4, i32),
211		(Int8, i64),
212		(Uint1, u8),
213		(Uint2, u16),
214		(Uint4, u32),
215		(Uint8, u64),
216		(Uint16, u128),
217	]
218);
219
220// Unsigned integer push impls with cross-type SafeConvert
221impl_numeric_push!(
222	u8,
223	Uint1,
224	uint1,
225	0u8,
226	[
227		(Float4, f32),
228		(Float8, f64),
229		(Uint2, u16),
230		(Uint4, u32),
231		(Uint8, u64),
232		(Uint16, u128),
233		(Int1, i8),
234		(Int2, i16),
235		(Int4, i32),
236		(Int8, i64),
237		(Int16, i128),
238	]
239);
240
241impl_numeric_push!(
242	u16,
243	Uint2,
244	uint2,
245	0u16,
246	[
247		(Float4, f32),
248		(Float8, f64),
249		(Uint1, u8),
250		(Uint4, u32),
251		(Uint8, u64),
252		(Uint16, u128),
253		(Int1, i8),
254		(Int2, i16),
255		(Int4, i32),
256		(Int8, i64),
257		(Int16, i128),
258	]
259);
260
261impl_numeric_push!(
262	u32,
263	Uint4,
264	uint4,
265	0u32,
266	[
267		(Float4, f32),
268		(Float8, f64),
269		(Uint1, u8),
270		(Uint2, u16),
271		(Uint8, u64),
272		(Uint16, u128),
273		(Int1, i8),
274		(Int2, i16),
275		(Int4, i32),
276		(Int8, i64),
277		(Int16, i128),
278	]
279);
280
281impl_numeric_push!(
282	u64,
283	Uint8,
284	uint8,
285	0u64,
286	[
287		(Float4, f32),
288		(Float8, f64),
289		(Uint1, u8),
290		(Uint2, u16),
291		(Uint4, u32),
292		(Uint16, u128),
293		(Int1, i8),
294		(Int2, i16),
295		(Int4, i32),
296		(Int8, i64),
297		(Int16, i128),
298	]
299);
300
301impl_numeric_push!(
302	u128,
303	Uint16,
304	uint16,
305	0u128,
306	[
307		(Float4, f32),
308		(Float8, f64),
309		(Uint1, u8),
310		(Uint2, u16),
311		(Uint4, u32),
312		(Uint8, u64),
313		(Int1, i8),
314		(Int2, i16),
315		(Int4, i32),
316		(Int8, i64),
317		(Int16, i128),
318	]
319);
320
321impl Push<Blob> for ColumnData {
322	fn push(&mut self, value: Blob) {
323		match self {
324			ColumnData::Blob {
325				container,
326				..
327			} => {
328				container.push(value);
329			}
330			ColumnData::Option {
331				inner,
332				bitvec,
333			} => {
334				inner.push(value);
335				DataBitVec::push(bitvec, true);
336			}
337			other => panic!("called `push::<Blob>()` on EngineColumnData::{:?}", other.get_type()),
338		}
339	}
340}
341
342impl Push<String> for ColumnData {
343	fn push(&mut self, value: String) {
344		match self {
345			ColumnData::Utf8 {
346				container,
347				..
348			} => {
349				container.push(value);
350			}
351			ColumnData::Option {
352				inner,
353				bitvec,
354			} => {
355				inner.push(value);
356				DataBitVec::push(bitvec, true);
357			}
358			other => {
359				panic!("called `push::<String>()` on EngineColumnData::{:?}", other.get_type())
360			}
361		}
362	}
363}
364
365impl Push<DictionaryEntryId> for ColumnData {
366	fn push(&mut self, value: DictionaryEntryId) {
367		match self {
368			ColumnData::DictionaryId(container) => {
369				container.push(value);
370			}
371			ColumnData::Option {
372				inner,
373				bitvec,
374			} => {
375				inner.push(value);
376				DataBitVec::push(bitvec, true);
377			}
378			other => panic!(
379				"called `push::<DictionaryEntryId>()` on EngineColumnData::{:?}",
380				other.get_type()
381			),
382		}
383	}
384}
385
386impl Push<&str> for ColumnData {
387	fn push(&mut self, value: &str) {
388		self.push(value.to_string());
389	}
390}