Skip to main content

reifydb_core/value/column/buffer/
get.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2026 ReifyDB
3
4use num_traits::NumCast;
5use reifydb_codec::{key::serializer::KeySerializer, tag::ValueKind};
6use reifydb_value::value::{
7	Value,
8	date::Date,
9	datetime::DateTime,
10	decimal::Decimal,
11	duration::Duration,
12	identity::IdentityId,
13	int::Int,
14	time::Time,
15	uint::Uint,
16	uuid::{Uuid4, Uuid7},
17	value_type::ValueType,
18};
19
20use crate::value::column::{ColumnBuffer, buffer::with_container};
21
22pub trait FromColumnBuffer: Sized {
23	fn from_column_buffer(data: &ColumnBuffer, index: usize) -> Option<Self>;
24}
25
26impl ColumnBuffer {
27	pub fn get_value(&self, index: usize) -> Value {
28		match self {
29			ColumnBuffer::Option {
30				inner,
31				bitvec,
32			} => {
33				if index < bitvec.len() && bitvec.get(index) {
34					inner.get_value(index)
35				} else {
36					Value::None {
37						inner: inner.get_type(),
38					}
39				}
40			}
41			_ => with_container!(self, |c| c.get_value(index)),
42		}
43	}
44
45	pub fn get_as<T: FromColumnBuffer>(&self, index: usize) -> Option<T> {
46		T::from_column_buffer(self, index)
47	}
48
49	pub fn extend_key(&self, index: usize, serializer: &mut KeySerializer) {
50		match self {
51			ColumnBuffer::Option {
52				inner,
53				bitvec,
54			} => {
55				if index < bitvec.len() && bitvec.get(index) {
56					inner.extend_key(index, serializer);
57				} else {
58					serializer.extend_value(&Value::None {
59						inner: inner.get_type(),
60					});
61				}
62			}
63			ColumnBuffer::Utf8 {
64				container,
65				..
66			} => match container.get(index) {
67				Some(text) => {
68					serializer.extend_kind(ValueKind::Utf8).extend_str(text);
69				}
70				None => {
71					serializer.extend_value(&Value::none_of(ValueType::Utf8));
72				}
73			},
74			ColumnBuffer::Blob {
75				container,
76				..
77			} => match container.get(index) {
78				Some(bytes) => {
79					serializer.extend_kind(ValueKind::Blob).extend_bytes(bytes);
80				}
81				None => {
82					serializer.extend_value(&Value::none_of(ValueType::Blob));
83				}
84			},
85			other => {
86				serializer.extend_value(&other.get_value(index));
87			}
88		}
89	}
90
91	pub fn get_str(&self, index: usize) -> Option<&str> {
92		match self {
93			ColumnBuffer::Utf8 {
94				container,
95				..
96			} => container.get(index),
97			ColumnBuffer::Option {
98				inner,
99				bitvec,
100			} => {
101				if index < bitvec.len() && bitvec.get(index) {
102					inner.get_str(index)
103				} else {
104					None
105				}
106			}
107			_ => None,
108		}
109	}
110
111	pub fn get_bytes(&self, index: usize) -> Option<&[u8]> {
112		match self {
113			ColumnBuffer::Blob {
114				container,
115				..
116			} => container.get(index),
117			ColumnBuffer::Option {
118				inner,
119				bitvec,
120			} => {
121				if index < bitvec.len() && bitvec.get(index) {
122					inner.get_bytes(index)
123				} else {
124					None
125				}
126			}
127			_ => None,
128		}
129	}
130}
131
132macro_rules! impl_from_column_data_numeric {
133	($($t:ty),*) => { $(
134		impl FromColumnBuffer for $t {
135			fn from_column_buffer(data: &ColumnBuffer, index: usize) -> Option<Self> {
136				match data {
137					ColumnBuffer::Int1(c) => c.get(index).and_then(|v| NumCast::from(*v)),
138					ColumnBuffer::Int2(c) => c.get(index).and_then(|v| NumCast::from(*v)),
139					ColumnBuffer::Int4(c) => c.get(index).and_then(|v| NumCast::from(*v)),
140					ColumnBuffer::Int8(c) => c.get(index).and_then(|v| NumCast::from(*v)),
141					ColumnBuffer::Int16(c) => c.get(index).and_then(|v| NumCast::from(*v)),
142					ColumnBuffer::Uint1(c) => c.get(index).and_then(|v| NumCast::from(*v)),
143					ColumnBuffer::Uint2(c) => c.get(index).and_then(|v| NumCast::from(*v)),
144					ColumnBuffer::Uint4(c) => c.get(index).and_then(|v| NumCast::from(*v)),
145					ColumnBuffer::Uint8(c) => c.get(index).and_then(|v| NumCast::from(*v)),
146					ColumnBuffer::Uint16(c) => c.get(index).and_then(|v| NumCast::from(*v)),
147					ColumnBuffer::Float4(c) => c.get(index).and_then(|v| NumCast::from(*v)),
148					ColumnBuffer::Float8(c) => c.get(index).and_then(|v| NumCast::from(*v)),
149					ColumnBuffer::Int { container, .. } => container.get(index).and_then(|v| NumCast::from(v.0.clone())),
150					ColumnBuffer::Uint { container, .. } => container.get(index).and_then(|v| NumCast::from(v.0.clone())),
151					_ => None,
152				}
153			}
154		}
155	)* };
156}
157
158impl_from_column_data_numeric!(u8, u16, u32, u64, u128, i8, i16, i32, i64, i128, f32, f64);
159
160impl FromColumnBuffer for bool {
161	fn from_column_buffer(data: &ColumnBuffer, index: usize) -> Option<Self> {
162		match data {
163			ColumnBuffer::Bool(c) => c.get(index),
164			_ => None,
165		}
166	}
167}
168
169impl FromColumnBuffer for String {
170	fn from_column_buffer(data: &ColumnBuffer, index: usize) -> Option<Self> {
171		match data {
172			ColumnBuffer::Utf8 {
173				container,
174				..
175			} => container.get(index).map(str::to_string),
176			_ => None,
177		}
178	}
179}
180
181impl FromColumnBuffer for Vec<u8> {
182	fn from_column_buffer(data: &ColumnBuffer, index: usize) -> Option<Self> {
183		match data {
184			ColumnBuffer::Blob {
185				container,
186				..
187			} => container.get(index).map(<[u8]>::to_vec),
188			_ => None,
189		}
190	}
191}
192
193impl FromColumnBuffer for Date {
194	fn from_column_buffer(data: &ColumnBuffer, index: usize) -> Option<Self> {
195		match data {
196			ColumnBuffer::Date(c) => c.get(index).copied(),
197			_ => None,
198		}
199	}
200}
201
202impl FromColumnBuffer for DateTime {
203	fn from_column_buffer(data: &ColumnBuffer, index: usize) -> Option<Self> {
204		match data {
205			ColumnBuffer::DateTime(c) => c.get(index).copied(),
206			_ => None,
207		}
208	}
209}
210
211impl FromColumnBuffer for Time {
212	fn from_column_buffer(data: &ColumnBuffer, index: usize) -> Option<Self> {
213		match data {
214			ColumnBuffer::Time(c) => c.get(index).copied(),
215			_ => None,
216		}
217	}
218}
219
220impl FromColumnBuffer for Duration {
221	fn from_column_buffer(data: &ColumnBuffer, index: usize) -> Option<Self> {
222		match data {
223			ColumnBuffer::Duration(c) => c.get(index).copied(),
224			_ => None,
225		}
226	}
227}
228
229impl FromColumnBuffer for Uuid4 {
230	fn from_column_buffer(data: &ColumnBuffer, index: usize) -> Option<Self> {
231		match data {
232			ColumnBuffer::Uuid4(c) => c.get(index).copied(),
233			_ => None,
234		}
235	}
236}
237
238impl FromColumnBuffer for Uuid7 {
239	fn from_column_buffer(data: &ColumnBuffer, index: usize) -> Option<Self> {
240		match data {
241			ColumnBuffer::Uuid7(c) => c.get(index).copied(),
242			_ => None,
243		}
244	}
245}
246
247impl FromColumnBuffer for Int {
248	fn from_column_buffer(data: &ColumnBuffer, index: usize) -> Option<Self> {
249		match data {
250			ColumnBuffer::Int {
251				container,
252				..
253			} => container.get(index).cloned(),
254			_ => None,
255		}
256	}
257}
258
259impl FromColumnBuffer for Uint {
260	fn from_column_buffer(data: &ColumnBuffer, index: usize) -> Option<Self> {
261		match data {
262			ColumnBuffer::Uint {
263				container,
264				..
265			} => container.get(index).cloned(),
266			_ => None,
267		}
268	}
269}
270
271impl FromColumnBuffer for Decimal {
272	fn from_column_buffer(data: &ColumnBuffer, index: usize) -> Option<Self> {
273		match data {
274			ColumnBuffer::Decimal {
275				container,
276				..
277			} => container.get(index).cloned(),
278			_ => None,
279		}
280	}
281}
282
283impl FromColumnBuffer for IdentityId {
284	fn from_column_buffer(data: &ColumnBuffer, index: usize) -> Option<Self> {
285		match data {
286			ColumnBuffer::IdentityId(c) => c.get(index),
287			_ => None,
288		}
289	}
290}