Skip to main content

reifydb_core/value/column/buffer/
mod.rs

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