Skip to main content

reifydb_core/value/column/buffer/
get.rs

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