Skip to main content

reifydb_core/value/column/push/
mod.rs

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