Skip to main content

reifydb_core/value/column/data/
canonical.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2025 ReifyDB
3
4use std::{any::Any, sync::Arc};
5
6use reifydb_type::{
7	Result,
8	value::{Value, r#type::Type},
9};
10
11use crate::value::column::{
12	buffer::ColumnBuffer,
13	data::{Column, ColumnData},
14	encoding::EncodingId,
15	nones::NoneBitmap,
16	stats::StatsSet,
17};
18
19#[derive(Clone, Debug)]
20pub struct Canonical {
21	pub ty: Type,
22	pub nullable: bool,
23	pub nones: Option<NoneBitmap>,
24	pub buffer: ColumnBuffer,
25	stats: StatsSet,
26}
27
28impl Canonical {
29	pub fn new(ty: Type, nullable: bool, nones: Option<NoneBitmap>, buffer: ColumnBuffer) -> Self {
30		debug_assert!(
31			!matches!(buffer, ColumnBuffer::Option { .. }),
32			"Canonical.buffer must not be a ColumnBuffer::Option; nullability is lifted"
33		);
34		Self {
35			ty,
36			nullable,
37			nones,
38			buffer,
39			stats: StatsSet::new(),
40		}
41	}
42
43	pub fn from_buffer(b: ColumnBuffer) -> Self {
44		match b {
45			ColumnBuffer::Option {
46				inner,
47				bitvec,
48			} => {
49				let mut inner_c = Self::from_buffer(*inner);
50				inner_c.nullable = true;
51				inner_c.nones = Some(NoneBitmap::from_defined_bitvec(&bitvec));
52				inner_c
53			}
54			other => {
55				let ty = other.get_type();
56				Self {
57					ty,
58					nullable: false,
59					nones: None,
60					buffer: other,
61					stats: StatsSet::new(),
62				}
63			}
64		}
65	}
66
67	pub fn from_column_buffer(cd: &ColumnBuffer) -> Result<Self> {
68		Ok(Self::from_buffer(cd.clone()))
69	}
70
71	pub fn into_buffer(self) -> ColumnBuffer {
72		match self.nones {
73			None => self.buffer,
74			Some(nones) => ColumnBuffer::Option {
75				inner: Box::new(self.buffer),
76				bitvec: nones.to_defined_bitvec(),
77			},
78		}
79	}
80
81	pub fn to_buffer(&self) -> ColumnBuffer {
82		match &self.nones {
83			None => self.buffer.clone(),
84			Some(nones) => ColumnBuffer::Option {
85				inner: Box::new(self.buffer.clone()),
86				bitvec: nones.to_defined_bitvec(),
87			},
88		}
89	}
90
91	pub fn to_column_buffer(&self) -> Result<ColumnBuffer> {
92		Ok(self.to_buffer())
93	}
94
95	pub fn len(&self) -> usize {
96		self.buffer.len()
97	}
98
99	pub fn is_empty(&self) -> bool {
100		self.len() == 0
101	}
102
103	pub fn stats(&self) -> &StatsSet {
104		&self.stats
105	}
106}
107
108fn encoding_for_type(ty: &Type) -> EncodingId {
109	match ty {
110		Type::Boolean => EncodingId::CANONICAL_BOOL,
111		Type::Utf8 | Type::Blob => EncodingId::CANONICAL_VARLEN,
112		Type::Int | Type::Uint | Type::Decimal => EncodingId::CANONICAL_BIGNUM,
113		_ => EncodingId::CANONICAL_FIXED,
114	}
115}
116
117static UNIT_METADATA: () = ();
118static EMPTY_CHILDREN: Vec<Column> = Vec::new();
119
120impl ColumnData for Canonical {
121	fn ty(&self) -> Type {
122		self.ty.clone()
123	}
124
125	fn is_nullable(&self) -> bool {
126		self.nullable
127	}
128
129	fn len(&self) -> usize {
130		self.buffer.len()
131	}
132
133	fn encoding(&self) -> EncodingId {
134		encoding_for_type(&self.ty)
135	}
136
137	fn stats(&self) -> &StatsSet {
138		&self.stats
139	}
140
141	fn nones(&self) -> Option<&NoneBitmap> {
142		self.nones.as_ref()
143	}
144
145	fn get_value(&self, idx: usize) -> Value {
146		if self.nones.as_ref().map(|n| n.is_none(idx)).unwrap_or(false) {
147			Value::none_of(self.ty.clone())
148		} else {
149			self.buffer.get_value(idx)
150		}
151	}
152
153	fn as_string(&self, idx: usize) -> String {
154		self.buffer.as_string(idx)
155	}
156
157	fn as_any(&self) -> &dyn Any {
158		self
159	}
160
161	fn as_any_mut(&mut self) -> &mut dyn Any {
162		self
163	}
164
165	fn children(&self) -> &[Column] {
166		&EMPTY_CHILDREN
167	}
168
169	fn metadata(&self) -> &dyn Any {
170		&UNIT_METADATA
171	}
172
173	fn to_canonical(&self) -> Result<Arc<Canonical>> {
174		Ok(Arc::new(self.clone()))
175	}
176}