Skip to main content

reifydb_core/value/column/buffer/
mod.rs

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