Skip to main content

reifydb_core/value/column/buffer/
mod.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2026 ReifyDB
3
4//! `ColumnBuffer` and its operation surface: the typed-per-primitive buffer that stores actual values.
5//!
6//! The buffer enum has one variant per primitive type the database understands (the integer family from `i8`/`u8`
7//! through `i128`/`u128`, the float pair, booleans, UTF-8, blobs, the temporal family, decimals, the UUID variants,
8//! dictionaries, identities, plus an `Option` wrapper for nullability). Submodules implement the operations the engine
9//! performs on a buffer: extend, factory construction, filter, conversions, value access, the buffer pool, reorder,
10//! scatter, slice, and take.
11
12pub mod extend;
13pub mod factory;
14pub mod filter;
15pub mod from;
16pub mod get;
17pub mod pool;
18pub mod reorder;
19pub mod scatter;
20pub mod slice;
21pub mod take;
22
23use std::fmt;
24
25use reifydb_value::{
26	util::bitvec::BitVec,
27	value::{
28		Value,
29		constraint::{bytes::MaxBytes, precision::Precision, scale::Scale},
30		container::{
31			any::AnyContainer, blob::BlobContainer, bool::BoolContainer, dictionary::DictionaryContainer,
32			identity_id::IdentityIdContainer, number::NumberContainer, temporal::TemporalContainer,
33			utf8::Utf8Container, uuid::UuidContainer,
34		},
35		date::Date,
36		datetime::DateTime,
37		decimal::Decimal,
38		duration::Duration,
39		int::Int,
40		time::Time,
41		uint::Uint,
42		uuid::{Uuid4, Uuid7},
43		value_type::ValueType,
44	},
45};
46use serde::{Deserialize, Deserializer, Serialize, Serializer};
47
48pub enum ColumnBuffer {
49	Bool(BoolContainer),
50	Float4(NumberContainer<f32>),
51	Float8(NumberContainer<f64>),
52	Int1(NumberContainer<i8>),
53	Int2(NumberContainer<i16>),
54	Int4(NumberContainer<i32>),
55	Int8(NumberContainer<i64>),
56	Int16(NumberContainer<i128>),
57	Uint1(NumberContainer<u8>),
58	Uint2(NumberContainer<u16>),
59	Uint4(NumberContainer<u32>),
60	Uint8(NumberContainer<u64>),
61	Uint16(NumberContainer<u128>),
62	Utf8 {
63		container: Utf8Container,
64		max_bytes: MaxBytes,
65	},
66	Date(TemporalContainer<Date>),
67	DateTime(TemporalContainer<DateTime>),
68	Time(TemporalContainer<Time>),
69	Duration(TemporalContainer<Duration>),
70	IdentityId(IdentityIdContainer),
71	Uuid4(UuidContainer<Uuid4>),
72	Uuid7(UuidContainer<Uuid7>),
73	Blob {
74		container: BlobContainer,
75		max_bytes: MaxBytes,
76	},
77	Int {
78		container: NumberContainer<Int>,
79		max_bytes: MaxBytes,
80	},
81	Uint {
82		container: NumberContainer<Uint>,
83		max_bytes: MaxBytes,
84	},
85	Decimal {
86		container: NumberContainer<Decimal>,
87		precision: Precision,
88		scale: Scale,
89	},
90
91	Any(AnyContainer),
92
93	DictionaryId(DictionaryContainer),
94
95	Option {
96		inner: Box<ColumnBuffer>,
97		bitvec: BitVec,
98	},
99}
100
101impl Clone for ColumnBuffer {
102	fn clone(&self) -> Self {
103		match self {
104			ColumnBuffer::Bool(c) => ColumnBuffer::Bool(c.clone()),
105			ColumnBuffer::Float4(c) => ColumnBuffer::Float4(c.clone()),
106			ColumnBuffer::Float8(c) => ColumnBuffer::Float8(c.clone()),
107			ColumnBuffer::Int1(c) => ColumnBuffer::Int1(c.clone()),
108			ColumnBuffer::Int2(c) => ColumnBuffer::Int2(c.clone()),
109			ColumnBuffer::Int4(c) => ColumnBuffer::Int4(c.clone()),
110			ColumnBuffer::Int8(c) => ColumnBuffer::Int8(c.clone()),
111			ColumnBuffer::Int16(c) => ColumnBuffer::Int16(c.clone()),
112			ColumnBuffer::Uint1(c) => ColumnBuffer::Uint1(c.clone()),
113			ColumnBuffer::Uint2(c) => ColumnBuffer::Uint2(c.clone()),
114			ColumnBuffer::Uint4(c) => ColumnBuffer::Uint4(c.clone()),
115			ColumnBuffer::Uint8(c) => ColumnBuffer::Uint8(c.clone()),
116			ColumnBuffer::Uint16(c) => ColumnBuffer::Uint16(c.clone()),
117			ColumnBuffer::Utf8 {
118				container,
119				max_bytes,
120			} => ColumnBuffer::Utf8 {
121				container: container.clone(),
122				max_bytes: *max_bytes,
123			},
124			ColumnBuffer::Date(c) => ColumnBuffer::Date(c.clone()),
125			ColumnBuffer::DateTime(c) => ColumnBuffer::DateTime(c.clone()),
126			ColumnBuffer::Time(c) => ColumnBuffer::Time(c.clone()),
127			ColumnBuffer::Duration(c) => ColumnBuffer::Duration(c.clone()),
128			ColumnBuffer::IdentityId(c) => ColumnBuffer::IdentityId(c.clone()),
129			ColumnBuffer::Uuid4(c) => ColumnBuffer::Uuid4(c.clone()),
130			ColumnBuffer::Uuid7(c) => ColumnBuffer::Uuid7(c.clone()),
131			ColumnBuffer::Blob {
132				container,
133				max_bytes,
134			} => ColumnBuffer::Blob {
135				container: container.clone(),
136				max_bytes: *max_bytes,
137			},
138			ColumnBuffer::Int {
139				container,
140				max_bytes,
141			} => ColumnBuffer::Int {
142				container: container.clone(),
143				max_bytes: *max_bytes,
144			},
145			ColumnBuffer::Uint {
146				container,
147				max_bytes,
148			} => ColumnBuffer::Uint {
149				container: container.clone(),
150				max_bytes: *max_bytes,
151			},
152			ColumnBuffer::Decimal {
153				container,
154				precision,
155				scale,
156			} => ColumnBuffer::Decimal {
157				container: container.clone(),
158				precision: *precision,
159				scale: *scale,
160			},
161			ColumnBuffer::Any(c) => ColumnBuffer::Any(c.clone()),
162			ColumnBuffer::DictionaryId(c) => ColumnBuffer::DictionaryId(c.clone()),
163			ColumnBuffer::Option {
164				inner,
165				bitvec,
166			} => ColumnBuffer::Option {
167				inner: inner.clone(),
168				bitvec: bitvec.clone(),
169			},
170		}
171	}
172}
173
174impl PartialEq for ColumnBuffer {
175	fn eq(&self, other: &Self) -> bool {
176		match (self, other) {
177			(ColumnBuffer::Bool(a), ColumnBuffer::Bool(b)) => a == b,
178			(ColumnBuffer::Float4(a), ColumnBuffer::Float4(b)) => a == b,
179			(ColumnBuffer::Float8(a), ColumnBuffer::Float8(b)) => a == b,
180			(ColumnBuffer::Int1(a), ColumnBuffer::Int1(b)) => a == b,
181			(ColumnBuffer::Int2(a), ColumnBuffer::Int2(b)) => a == b,
182			(ColumnBuffer::Int4(a), ColumnBuffer::Int4(b)) => a == b,
183			(ColumnBuffer::Int8(a), ColumnBuffer::Int8(b)) => a == b,
184			(ColumnBuffer::Int16(a), ColumnBuffer::Int16(b)) => a == b,
185			(ColumnBuffer::Uint1(a), ColumnBuffer::Uint1(b)) => a == b,
186			(ColumnBuffer::Uint2(a), ColumnBuffer::Uint2(b)) => a == b,
187			(ColumnBuffer::Uint4(a), ColumnBuffer::Uint4(b)) => a == b,
188			(ColumnBuffer::Uint8(a), ColumnBuffer::Uint8(b)) => a == b,
189			(ColumnBuffer::Uint16(a), ColumnBuffer::Uint16(b)) => a == b,
190			(
191				ColumnBuffer::Utf8 {
192					container: a,
193					max_bytes: am,
194				},
195				ColumnBuffer::Utf8 {
196					container: b,
197					max_bytes: bm,
198				},
199			) => a == b && am == bm,
200			(ColumnBuffer::Date(a), ColumnBuffer::Date(b)) => a == b,
201			(ColumnBuffer::DateTime(a), ColumnBuffer::DateTime(b)) => a == b,
202			(ColumnBuffer::Time(a), ColumnBuffer::Time(b)) => a == b,
203			(ColumnBuffer::Duration(a), ColumnBuffer::Duration(b)) => a == b,
204			(ColumnBuffer::IdentityId(a), ColumnBuffer::IdentityId(b)) => a == b,
205			(ColumnBuffer::Uuid4(a), ColumnBuffer::Uuid4(b)) => a == b,
206			(ColumnBuffer::Uuid7(a), ColumnBuffer::Uuid7(b)) => a == b,
207			(
208				ColumnBuffer::Blob {
209					container: a,
210					max_bytes: am,
211				},
212				ColumnBuffer::Blob {
213					container: b,
214					max_bytes: bm,
215				},
216			) => a == b && am == bm,
217			(
218				ColumnBuffer::Int {
219					container: a,
220					max_bytes: am,
221				},
222				ColumnBuffer::Int {
223					container: b,
224					max_bytes: bm,
225				},
226			) => a == b && am == bm,
227			(
228				ColumnBuffer::Uint {
229					container: a,
230					max_bytes: am,
231				},
232				ColumnBuffer::Uint {
233					container: b,
234					max_bytes: bm,
235				},
236			) => a == b && am == bm,
237			(
238				ColumnBuffer::Decimal {
239					container: a,
240					precision: ap,
241					scale: as_,
242				},
243				ColumnBuffer::Decimal {
244					container: b,
245					precision: bp,
246					scale: bs,
247				},
248			) => a == b && ap == bp && as_ == bs,
249			(ColumnBuffer::Any(a), ColumnBuffer::Any(b)) => a == b,
250			(ColumnBuffer::DictionaryId(a), ColumnBuffer::DictionaryId(b)) => a == b,
251			(
252				ColumnBuffer::Option {
253					inner: ai,
254					bitvec: ab,
255				},
256				ColumnBuffer::Option {
257					inner: bi,
258					bitvec: bb,
259				},
260			) => ai == bi && ab == bb,
261			_ => false,
262		}
263	}
264}
265
266impl fmt::Debug for ColumnBuffer {
267	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
268		match self {
269			ColumnBuffer::Bool(c) => f.debug_tuple("Bool").field(c).finish(),
270			ColumnBuffer::Float4(c) => f.debug_tuple("Float4").field(c).finish(),
271			ColumnBuffer::Float8(c) => f.debug_tuple("Float8").field(c).finish(),
272			ColumnBuffer::Int1(c) => f.debug_tuple("Int1").field(c).finish(),
273			ColumnBuffer::Int2(c) => f.debug_tuple("Int2").field(c).finish(),
274			ColumnBuffer::Int4(c) => f.debug_tuple("Int4").field(c).finish(),
275			ColumnBuffer::Int8(c) => f.debug_tuple("Int8").field(c).finish(),
276			ColumnBuffer::Int16(c) => f.debug_tuple("Int16").field(c).finish(),
277			ColumnBuffer::Uint1(c) => f.debug_tuple("Uint1").field(c).finish(),
278			ColumnBuffer::Uint2(c) => f.debug_tuple("Uint2").field(c).finish(),
279			ColumnBuffer::Uint4(c) => f.debug_tuple("Uint4").field(c).finish(),
280			ColumnBuffer::Uint8(c) => f.debug_tuple("Uint8").field(c).finish(),
281			ColumnBuffer::Uint16(c) => f.debug_tuple("Uint16").field(c).finish(),
282			ColumnBuffer::Utf8 {
283				container,
284				max_bytes,
285			} => f.debug_struct("Utf8").field("container", container).field("max_bytes", max_bytes).finish(),
286			ColumnBuffer::Date(c) => f.debug_tuple("Date").field(c).finish(),
287			ColumnBuffer::DateTime(c) => f.debug_tuple("DateTime").field(c).finish(),
288			ColumnBuffer::Time(c) => f.debug_tuple("Time").field(c).finish(),
289			ColumnBuffer::Duration(c) => f.debug_tuple("Duration").field(c).finish(),
290			ColumnBuffer::IdentityId(c) => f.debug_tuple("IdentityId").field(c).finish(),
291			ColumnBuffer::Uuid4(c) => f.debug_tuple("Uuid4").field(c).finish(),
292			ColumnBuffer::Uuid7(c) => f.debug_tuple("Uuid7").field(c).finish(),
293			ColumnBuffer::Blob {
294				container,
295				max_bytes,
296			} => f.debug_struct("Blob").field("container", container).field("max_bytes", max_bytes).finish(),
297			ColumnBuffer::Int {
298				container,
299				max_bytes,
300			} => f.debug_struct("Int").field("container", container).field("max_bytes", max_bytes).finish(),
301			ColumnBuffer::Uint {
302				container,
303				max_bytes,
304			} => f.debug_struct("Uint").field("container", container).field("max_bytes", max_bytes).finish(),
305			ColumnBuffer::Decimal {
306				container,
307				precision,
308				scale,
309			} => f.debug_struct("Decimal")
310				.field("container", container)
311				.field("precision", precision)
312				.field("scale", scale)
313				.finish(),
314			ColumnBuffer::Any(c) => f.debug_tuple("Any").field(c).finish(),
315			ColumnBuffer::DictionaryId(c) => f.debug_tuple("DictionaryId").field(c).finish(),
316			ColumnBuffer::Option {
317				inner,
318				bitvec,
319			} => f.debug_struct("Option").field("inner", inner).field("bitvec", bitvec).finish(),
320		}
321	}
322}
323
324impl Serialize for ColumnBuffer {
325	fn serialize<Ser: Serializer>(&self, serializer: Ser) -> Result<Ser::Ok, Ser::Error> {
326		#[derive(Serialize)]
327		enum Helper<'a> {
328			Bool(&'a BoolContainer),
329			Float4(&'a NumberContainer<f32>),
330			Float8(&'a NumberContainer<f64>),
331			Int1(&'a NumberContainer<i8>),
332			Int2(&'a NumberContainer<i16>),
333			Int4(&'a NumberContainer<i32>),
334			Int8(&'a NumberContainer<i64>),
335			Int16(&'a NumberContainer<i128>),
336			Uint1(&'a NumberContainer<u8>),
337			Uint2(&'a NumberContainer<u16>),
338			Uint4(&'a NumberContainer<u32>),
339			Uint8(&'a NumberContainer<u64>),
340			Uint16(&'a NumberContainer<u128>),
341			Utf8 {
342				container: &'a Utf8Container,
343				max_bytes: MaxBytes,
344			},
345			Date(&'a TemporalContainer<Date>),
346			DateTime(&'a TemporalContainer<DateTime>),
347			Time(&'a TemporalContainer<Time>),
348			Duration(&'a TemporalContainer<Duration>),
349			IdentityId(&'a IdentityIdContainer),
350			Uuid4(&'a UuidContainer<Uuid4>),
351			Uuid7(&'a UuidContainer<Uuid7>),
352			Blob {
353				container: &'a BlobContainer,
354				max_bytes: MaxBytes,
355			},
356			Int {
357				container: &'a NumberContainer<Int>,
358				max_bytes: MaxBytes,
359			},
360			Uint {
361				container: &'a NumberContainer<Uint>,
362				max_bytes: MaxBytes,
363			},
364			Decimal {
365				container: &'a NumberContainer<Decimal>,
366				precision: Precision,
367				scale: Scale,
368			},
369			Any(&'a AnyContainer),
370			DictionaryId(&'a DictionaryContainer),
371			Option {
372				inner: &'a ColumnBuffer,
373				bitvec: &'a BitVec,
374			},
375		}
376		let helper = match self {
377			ColumnBuffer::Bool(c) => Helper::Bool(c),
378			ColumnBuffer::Float4(c) => Helper::Float4(c),
379			ColumnBuffer::Float8(c) => Helper::Float8(c),
380			ColumnBuffer::Int1(c) => Helper::Int1(c),
381			ColumnBuffer::Int2(c) => Helper::Int2(c),
382			ColumnBuffer::Int4(c) => Helper::Int4(c),
383			ColumnBuffer::Int8(c) => Helper::Int8(c),
384			ColumnBuffer::Int16(c) => Helper::Int16(c),
385			ColumnBuffer::Uint1(c) => Helper::Uint1(c),
386			ColumnBuffer::Uint2(c) => Helper::Uint2(c),
387			ColumnBuffer::Uint4(c) => Helper::Uint4(c),
388			ColumnBuffer::Uint8(c) => Helper::Uint8(c),
389			ColumnBuffer::Uint16(c) => Helper::Uint16(c),
390			ColumnBuffer::Utf8 {
391				container,
392				max_bytes,
393			} => Helper::Utf8 {
394				container,
395				max_bytes: *max_bytes,
396			},
397			ColumnBuffer::Date(c) => Helper::Date(c),
398			ColumnBuffer::DateTime(c) => Helper::DateTime(c),
399			ColumnBuffer::Time(c) => Helper::Time(c),
400			ColumnBuffer::Duration(c) => Helper::Duration(c),
401			ColumnBuffer::IdentityId(c) => Helper::IdentityId(c),
402			ColumnBuffer::Uuid4(c) => Helper::Uuid4(c),
403			ColumnBuffer::Uuid7(c) => Helper::Uuid7(c),
404			ColumnBuffer::Blob {
405				container,
406				max_bytes,
407			} => Helper::Blob {
408				container,
409				max_bytes: *max_bytes,
410			},
411			ColumnBuffer::Int {
412				container,
413				max_bytes,
414			} => Helper::Int {
415				container,
416				max_bytes: *max_bytes,
417			},
418			ColumnBuffer::Uint {
419				container,
420				max_bytes,
421			} => Helper::Uint {
422				container,
423				max_bytes: *max_bytes,
424			},
425			ColumnBuffer::Decimal {
426				container,
427				precision,
428				scale,
429			} => Helper::Decimal {
430				container,
431				precision: *precision,
432				scale: *scale,
433			},
434			ColumnBuffer::Any(c) => Helper::Any(c),
435			ColumnBuffer::DictionaryId(c) => Helper::DictionaryId(c),
436			ColumnBuffer::Option {
437				inner,
438				bitvec,
439			} => Helper::Option {
440				inner: inner.as_ref(),
441				bitvec,
442			},
443		};
444		helper.serialize(serializer)
445	}
446}
447
448impl<'de> Deserialize<'de> for ColumnBuffer {
449	fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
450		#[derive(Deserialize)]
451		enum Helper {
452			Bool(BoolContainer),
453			Float4(NumberContainer<f32>),
454			Float8(NumberContainer<f64>),
455			Int1(NumberContainer<i8>),
456			Int2(NumberContainer<i16>),
457			Int4(NumberContainer<i32>),
458			Int8(NumberContainer<i64>),
459			Int16(NumberContainer<i128>),
460			Uint1(NumberContainer<u8>),
461			Uint2(NumberContainer<u16>),
462			Uint4(NumberContainer<u32>),
463			Uint8(NumberContainer<u64>),
464			Uint16(NumberContainer<u128>),
465			Utf8 {
466				container: Utf8Container,
467				max_bytes: MaxBytes,
468			},
469			Date(TemporalContainer<Date>),
470			DateTime(TemporalContainer<DateTime>),
471			Time(TemporalContainer<Time>),
472			Duration(TemporalContainer<Duration>),
473			IdentityId(IdentityIdContainer),
474			Uuid4(UuidContainer<Uuid4>),
475			Uuid7(UuidContainer<Uuid7>),
476			Blob {
477				container: BlobContainer,
478				max_bytes: MaxBytes,
479			},
480			Int {
481				container: NumberContainer<Int>,
482				max_bytes: MaxBytes,
483			},
484			Uint {
485				container: NumberContainer<Uint>,
486				max_bytes: MaxBytes,
487			},
488			Decimal {
489				container: NumberContainer<Decimal>,
490				precision: Precision,
491				scale: Scale,
492			},
493			Any(AnyContainer),
494			DictionaryId(DictionaryContainer),
495			Option {
496				inner: Box<ColumnBuffer>,
497				bitvec: BitVec,
498			},
499		}
500		let helper = Helper::deserialize(deserializer)?;
501		Ok(match helper {
502			Helper::Bool(c) => ColumnBuffer::Bool(c),
503			Helper::Float4(c) => ColumnBuffer::Float4(c),
504			Helper::Float8(c) => ColumnBuffer::Float8(c),
505			Helper::Int1(c) => ColumnBuffer::Int1(c),
506			Helper::Int2(c) => ColumnBuffer::Int2(c),
507			Helper::Int4(c) => ColumnBuffer::Int4(c),
508			Helper::Int8(c) => ColumnBuffer::Int8(c),
509			Helper::Int16(c) => ColumnBuffer::Int16(c),
510			Helper::Uint1(c) => ColumnBuffer::Uint1(c),
511			Helper::Uint2(c) => ColumnBuffer::Uint2(c),
512			Helper::Uint4(c) => ColumnBuffer::Uint4(c),
513			Helper::Uint8(c) => ColumnBuffer::Uint8(c),
514			Helper::Uint16(c) => ColumnBuffer::Uint16(c),
515			Helper::Utf8 {
516				container,
517				max_bytes,
518			} => ColumnBuffer::Utf8 {
519				container,
520				max_bytes,
521			},
522			Helper::Date(c) => ColumnBuffer::Date(c),
523			Helper::DateTime(c) => ColumnBuffer::DateTime(c),
524			Helper::Time(c) => ColumnBuffer::Time(c),
525			Helper::Duration(c) => ColumnBuffer::Duration(c),
526			Helper::IdentityId(c) => ColumnBuffer::IdentityId(c),
527			Helper::Uuid4(c) => ColumnBuffer::Uuid4(c),
528			Helper::Uuid7(c) => ColumnBuffer::Uuid7(c),
529			Helper::Blob {
530				container,
531				max_bytes,
532			} => ColumnBuffer::Blob {
533				container,
534				max_bytes,
535			},
536			Helper::Int {
537				container,
538				max_bytes,
539			} => ColumnBuffer::Int {
540				container,
541				max_bytes,
542			},
543			Helper::Uint {
544				container,
545				max_bytes,
546			} => ColumnBuffer::Uint {
547				container,
548				max_bytes,
549			},
550			Helper::Decimal {
551				container,
552				precision,
553				scale,
554			} => ColumnBuffer::Decimal {
555				container,
556				precision,
557				scale,
558			},
559			Helper::Any(c) => ColumnBuffer::Any(c),
560			Helper::DictionaryId(c) => ColumnBuffer::DictionaryId(c),
561			Helper::Option {
562				inner,
563				bitvec,
564			} => ColumnBuffer::Option {
565				inner,
566				bitvec,
567			},
568		})
569	}
570}
571
572macro_rules! with_container {
573	($self:expr, |$c:ident| $body:expr) => {
574		match $self {
575			ColumnBuffer::Bool($c) => $body,
576			ColumnBuffer::Float4($c) => $body,
577			ColumnBuffer::Float8($c) => $body,
578			ColumnBuffer::Int1($c) => $body,
579			ColumnBuffer::Int2($c) => $body,
580			ColumnBuffer::Int4($c) => $body,
581			ColumnBuffer::Int8($c) => $body,
582			ColumnBuffer::Int16($c) => $body,
583			ColumnBuffer::Uint1($c) => $body,
584			ColumnBuffer::Uint2($c) => $body,
585			ColumnBuffer::Uint4($c) => $body,
586			ColumnBuffer::Uint8($c) => $body,
587			ColumnBuffer::Uint16($c) => $body,
588			ColumnBuffer::Utf8 {
589				container: $c,
590				..
591			} => $body,
592			ColumnBuffer::Date($c) => $body,
593			ColumnBuffer::DateTime($c) => $body,
594			ColumnBuffer::Time($c) => $body,
595			ColumnBuffer::Duration($c) => $body,
596			ColumnBuffer::IdentityId($c) => $body,
597			ColumnBuffer::Uuid4($c) => $body,
598			ColumnBuffer::Uuid7($c) => $body,
599			ColumnBuffer::Blob {
600				container: $c,
601				..
602			} => $body,
603			ColumnBuffer::Int {
604				container: $c,
605				..
606			} => $body,
607			ColumnBuffer::Uint {
608				container: $c,
609				..
610			} => $body,
611			ColumnBuffer::Decimal {
612				container: $c,
613				..
614			} => $body,
615			ColumnBuffer::Any($c) => $body,
616			ColumnBuffer::DictionaryId($c) => $body,
617			ColumnBuffer::Option {
618				..
619			} => {
620				unreachable!(
621					"with_container! must not be called on Option variant directly; handle it explicitly"
622				)
623			}
624		}
625	};
626}
627
628pub(crate) use with_container;
629
630impl ColumnBuffer {
631	pub fn unwrap_option(&self) -> (&ColumnBuffer, Option<&BitVec>) {
632		match self {
633			ColumnBuffer::Option {
634				inner,
635				bitvec,
636			} => (inner.as_ref(), Some(bitvec)),
637			other => (other, None),
638		}
639	}
640
641	pub fn into_unwrap_option(self) -> (ColumnBuffer, Option<BitVec>) {
642		match self {
643			ColumnBuffer::Option {
644				inner,
645				bitvec,
646			} => (*inner, Some(bitvec)),
647			other => (other, None),
648		}
649	}
650
651	pub fn get_type(&self) -> ValueType {
652		match self {
653			ColumnBuffer::Bool(_) => ValueType::Boolean,
654			ColumnBuffer::Float4(_) => ValueType::Float4,
655			ColumnBuffer::Float8(_) => ValueType::Float8,
656			ColumnBuffer::Int1(_) => ValueType::Int1,
657			ColumnBuffer::Int2(_) => ValueType::Int2,
658			ColumnBuffer::Int4(_) => ValueType::Int4,
659			ColumnBuffer::Int8(_) => ValueType::Int8,
660			ColumnBuffer::Int16(_) => ValueType::Int16,
661			ColumnBuffer::Uint1(_) => ValueType::Uint1,
662			ColumnBuffer::Uint2(_) => ValueType::Uint2,
663			ColumnBuffer::Uint4(_) => ValueType::Uint4,
664			ColumnBuffer::Uint8(_) => ValueType::Uint8,
665			ColumnBuffer::Uint16(_) => ValueType::Uint16,
666			ColumnBuffer::Utf8 {
667				..
668			} => ValueType::Utf8,
669			ColumnBuffer::Date(_) => ValueType::Date,
670			ColumnBuffer::DateTime(_) => ValueType::DateTime,
671			ColumnBuffer::Time(_) => ValueType::Time,
672			ColumnBuffer::Duration(_) => ValueType::Duration,
673			ColumnBuffer::IdentityId(_) => ValueType::IdentityId,
674			ColumnBuffer::Uuid4(_) => ValueType::Uuid4,
675			ColumnBuffer::Uuid7(_) => ValueType::Uuid7,
676			ColumnBuffer::Blob {
677				..
678			} => ValueType::Blob,
679			ColumnBuffer::Int {
680				..
681			} => ValueType::Int,
682			ColumnBuffer::Uint {
683				..
684			} => ValueType::Uint,
685			ColumnBuffer::Decimal {
686				..
687			} => ValueType::Decimal,
688			ColumnBuffer::DictionaryId(_) => ValueType::DictionaryId,
689			ColumnBuffer::Any(_) => ValueType::Any,
690			ColumnBuffer::Option {
691				inner,
692				..
693			} => ValueType::Option(Box::new(inner.get_type())),
694		}
695	}
696
697	pub fn is_defined(&self, idx: usize) -> bool {
698		match self {
699			ColumnBuffer::Bool(c) => c.is_defined(idx),
700			ColumnBuffer::Float4(c) => c.is_defined(idx),
701			ColumnBuffer::Float8(c) => c.is_defined(idx),
702			ColumnBuffer::Int1(c) => c.is_defined(idx),
703			ColumnBuffer::Int2(c) => c.is_defined(idx),
704			ColumnBuffer::Int4(c) => c.is_defined(idx),
705			ColumnBuffer::Int8(c) => c.is_defined(idx),
706			ColumnBuffer::Int16(c) => c.is_defined(idx),
707			ColumnBuffer::Uint1(c) => c.is_defined(idx),
708			ColumnBuffer::Uint2(c) => c.is_defined(idx),
709			ColumnBuffer::Uint4(c) => c.is_defined(idx),
710			ColumnBuffer::Uint8(c) => c.is_defined(idx),
711			ColumnBuffer::Uint16(c) => c.is_defined(idx),
712			ColumnBuffer::Utf8 {
713				container: c,
714				..
715			} => c.is_defined(idx),
716			ColumnBuffer::Date(c) => c.is_defined(idx),
717			ColumnBuffer::DateTime(c) => c.is_defined(idx),
718			ColumnBuffer::Time(c) => c.is_defined(idx),
719			ColumnBuffer::Duration(c) => c.is_defined(idx),
720			ColumnBuffer::IdentityId(container) => container.get(idx).is_some(),
721			ColumnBuffer::Uuid4(c) => c.is_defined(idx),
722			ColumnBuffer::Uuid7(c) => c.is_defined(idx),
723			ColumnBuffer::Blob {
724				container: c,
725				..
726			} => c.is_defined(idx),
727			ColumnBuffer::Int {
728				container: c,
729				..
730			} => c.is_defined(idx),
731			ColumnBuffer::Uint {
732				container: c,
733				..
734			} => c.is_defined(idx),
735			ColumnBuffer::Decimal {
736				container: c,
737				..
738			} => c.is_defined(idx),
739			ColumnBuffer::DictionaryId(c) => c.is_defined(idx),
740			ColumnBuffer::Any(c) => c.is_defined(idx),
741			ColumnBuffer::Option {
742				bitvec,
743				..
744			} => idx < bitvec.len() && bitvec.get(idx),
745		}
746	}
747
748	pub fn is_bool(&self) -> bool {
749		self.get_type() == ValueType::Boolean
750	}
751
752	pub fn is_float(&self) -> bool {
753		self.get_type() == ValueType::Float4 || self.get_type() == ValueType::Float8
754	}
755
756	pub fn is_utf8(&self) -> bool {
757		self.get_type() == ValueType::Utf8
758	}
759
760	pub fn is_number(&self) -> bool {
761		matches!(
762			self.get_type(),
763			ValueType::Float4
764				| ValueType::Float8 | ValueType::Int1
765				| ValueType::Int2 | ValueType::Int4
766				| ValueType::Int8 | ValueType::Int16
767				| ValueType::Uint1 | ValueType::Uint2
768				| ValueType::Uint4 | ValueType::Uint8
769				| ValueType::Uint16 | ValueType::Int
770				| ValueType::Uint | ValueType::Decimal
771		)
772	}
773
774	pub fn is_text(&self) -> bool {
775		self.get_type() == ValueType::Utf8
776	}
777
778	pub fn is_temporal(&self) -> bool {
779		matches!(self.get_type(), ValueType::Date | ValueType::DateTime | ValueType::Time | ValueType::Duration)
780	}
781
782	pub fn is_uuid(&self) -> bool {
783		matches!(self.get_type(), ValueType::Uuid4 | ValueType::Uuid7)
784	}
785}
786
787impl ColumnBuffer {
788	pub fn none_count(&self) -> usize {
789		match self {
790			ColumnBuffer::Option {
791				bitvec,
792				..
793			} => bitvec.count_zeros(),
794			_ => 0,
795		}
796	}
797}
798
799impl ColumnBuffer {
800	pub fn len(&self) -> usize {
801		match self {
802			ColumnBuffer::Option {
803				inner,
804				..
805			} => inner.len(),
806			_ => with_container!(self, |c| c.len()),
807		}
808	}
809
810	pub fn is_empty(&self) -> bool {
811		self.len() == 0
812	}
813
814	pub fn capacity(&self) -> usize {
815		match self {
816			ColumnBuffer::Option {
817				inner,
818				..
819			} => inner.capacity(),
820			_ => with_container!(self, |c| c.capacity()),
821		}
822	}
823
824	pub fn heap_size(&self) -> usize {
825		match self {
826			ColumnBuffer::Option {
827				inner,
828				bitvec,
829			} => inner.heap_size() + bitvec.len().div_ceil(8),
830			_ => with_container!(self, |c| c.heap_size()),
831		}
832	}
833
834	pub fn clear(&mut self) {
835		match self {
836			ColumnBuffer::Option {
837				inner,
838				bitvec,
839			} => {
840				inner.clear();
841				bitvec.clear();
842			}
843			_ => with_container!(self, |c| c.clear()),
844		}
845	}
846
847	pub fn as_string(&self, index: usize) -> String {
848		match self {
849			ColumnBuffer::Option {
850				inner,
851				bitvec,
852			} => {
853				if index < bitvec.len() && bitvec.get(index) {
854					inner.as_string(index)
855				} else {
856					"none".to_string()
857				}
858			}
859			_ => with_container!(self, |c| c.as_string(index)),
860		}
861	}
862}
863
864impl ColumnBuffer {
865	pub fn with_capacity(target: ValueType, capacity: usize) -> Self {
866		match target {
867			ValueType::Boolean => Self::bool_with_capacity(capacity),
868			ValueType::Float4 => Self::float4_with_capacity(capacity),
869			ValueType::Float8 => Self::float8_with_capacity(capacity),
870			ValueType::Int1 => Self::int1_with_capacity(capacity),
871			ValueType::Int2 => Self::int2_with_capacity(capacity),
872			ValueType::Int4 => Self::int4_with_capacity(capacity),
873			ValueType::Int8 => Self::int8_with_capacity(capacity),
874			ValueType::Int16 => Self::int16_with_capacity(capacity),
875			ValueType::Uint1 => Self::uint1_with_capacity(capacity),
876			ValueType::Uint2 => Self::uint2_with_capacity(capacity),
877			ValueType::Uint4 => Self::uint4_with_capacity(capacity),
878			ValueType::Uint8 => Self::uint8_with_capacity(capacity),
879			ValueType::Uint16 => Self::uint16_with_capacity(capacity),
880			ValueType::Utf8 => Self::utf8_with_capacity(capacity),
881			ValueType::Date => Self::date_with_capacity(capacity),
882			ValueType::DateTime => Self::datetime_with_capacity(capacity),
883			ValueType::Time => Self::time_with_capacity(capacity),
884			ValueType::Duration => Self::duration_with_capacity(capacity),
885			ValueType::IdentityId => Self::identity_id_with_capacity(capacity),
886			ValueType::Uuid4 => Self::uuid4_with_capacity(capacity),
887			ValueType::Uuid7 => Self::uuid7_with_capacity(capacity),
888			ValueType::Blob => Self::blob_with_capacity(capacity),
889			ValueType::Int => Self::int_with_capacity(capacity),
890			ValueType::Uint => Self::uint_with_capacity(capacity),
891			ValueType::Decimal => Self::decimal_with_capacity(capacity),
892			ValueType::DictionaryId => Self::dictionary_id_with_capacity(capacity),
893			ValueType::Option(inner) => ColumnBuffer::Option {
894				inner: Box::new(ColumnBuffer::with_capacity(*inner, capacity)),
895				bitvec: BitVec::with_capacity(capacity),
896			},
897			ValueType::Any | ValueType::List(_) | ValueType::Record(_) | ValueType::Tuple(_) => {
898				Self::any_with_capacity(capacity)
899			}
900		}
901	}
902
903	pub fn empty_like(&self, capacity: usize) -> Self {
904		let mut buffer = Self::with_capacity(self.get_type(), capacity);
905		match (self, &mut buffer) {
906			(
907				ColumnBuffer::Utf8 {
908					max_bytes: src,
909					..
910				},
911				ColumnBuffer::Utf8 {
912					max_bytes: dst,
913					..
914				},
915			)
916			| (
917				ColumnBuffer::Blob {
918					max_bytes: src,
919					..
920				},
921				ColumnBuffer::Blob {
922					max_bytes: dst,
923					..
924				},
925			)
926			| (
927				ColumnBuffer::Int {
928					max_bytes: src,
929					..
930				},
931				ColumnBuffer::Int {
932					max_bytes: dst,
933					..
934				},
935			)
936			| (
937				ColumnBuffer::Uint {
938					max_bytes: src,
939					..
940				},
941				ColumnBuffer::Uint {
942					max_bytes: dst,
943					..
944				},
945			) => *dst = *src,
946			(
947				ColumnBuffer::Decimal {
948					precision: src_precision,
949					scale: src_scale,
950					..
951				},
952				ColumnBuffer::Decimal {
953					precision: dst_precision,
954					scale: dst_scale,
955					..
956				},
957			) => {
958				*dst_precision = *src_precision;
959				*dst_scale = *src_scale;
960			}
961			(ColumnBuffer::DictionaryId(src), ColumnBuffer::DictionaryId(dst)) => {
962				if let Some(dictionary_id) = src.dictionary_id() {
963					dst.set_dictionary_id(dictionary_id);
964				}
965			}
966			(
967				ColumnBuffer::Option {
968					inner: src_inner,
969					..
970				},
971				ColumnBuffer::Option {
972					inner: dst_inner,
973					..
974				},
975			) => {
976				**dst_inner = src_inner.empty_like(capacity);
977			}
978			_ => {}
979		}
980		buffer
981	}
982
983	pub fn iter<'a>(&'a self) -> Box<dyn Iterator<Item = Value> + 'a> {
984		Box::new((0..self.len()).map(move |i| self.get_value(i)))
985	}
986}