Skip to main content

reifydb_core/value/column/
row_ref.rs

1// SPDX-License-Identifier: AGPL-3.0-or-later
2// Copyright (c) 2026 ReifyDB
3
4use reifydb_value::value::{
5	Value, date::Date, datetime::DateTime, decimal::Decimal, duration::Duration, row_number::RowNumber, time::Time,
6};
7
8use crate::value::column::columns::Columns;
9
10#[derive(Clone, Copy)]
11pub struct RowRef<'a> {
12	columns: &'a Columns,
13	index: usize,
14}
15
16impl<'a> RowRef<'a> {
17	pub(crate) fn new(columns: &'a Columns, index: usize) -> Self {
18		Self {
19			columns,
20			index,
21		}
22	}
23
24	pub fn index(&self) -> usize {
25		self.index
26	}
27
28	pub fn row_number(&self) -> Option<RowNumber> {
29		self.columns.row_numbers.get(self.index).copied()
30	}
31
32	pub fn value(&self, name: &str) -> Option<Value> {
33		let col = self.columns.column(name)?;
34		Some(col.data().get_value(self.index))
35	}
36
37	pub fn is_defined(&self, name: &str) -> bool {
38		match self.value(name) {
39			Some(Value::None {
40				..
41			}) => false,
42			Some(_) => true,
43			None => false,
44		}
45	}
46
47	pub fn utf8(&self, name: &str) -> Option<String> {
48		match self.value(name)? {
49			Value::Utf8(s) => Some(s),
50			_ => None,
51		}
52	}
53
54	pub fn bool(&self, name: &str) -> Option<bool> {
55		match self.value(name)? {
56			Value::Boolean(b) => Some(b),
57			_ => None,
58		}
59	}
60
61	pub fn u64(&self, name: &str) -> Option<u64> {
62		match self.value(name)? {
63			Value::Uint8(v) => Some(v),
64			Value::Uint4(v) => Some(v as u64),
65			Value::Uint2(v) => Some(v as u64),
66			Value::Uint1(v) => Some(v as u64),
67			_ => None,
68		}
69	}
70
71	pub fn u32(&self, name: &str) -> Option<u32> {
72		match self.value(name)? {
73			Value::Uint4(v) => Some(v),
74			Value::Uint2(v) => Some(v as u32),
75			Value::Uint1(v) => Some(v as u32),
76			_ => None,
77		}
78	}
79
80	pub fn u16(&self, name: &str) -> Option<u16> {
81		match self.value(name)? {
82			Value::Uint2(v) => Some(v),
83			Value::Uint1(v) => Some(v as u16),
84			_ => None,
85		}
86	}
87
88	pub fn u8(&self, name: &str) -> Option<u8> {
89		match self.value(name)? {
90			Value::Uint1(v) => Some(v),
91			_ => None,
92		}
93	}
94
95	pub fn i64(&self, name: &str) -> Option<i64> {
96		match self.value(name)? {
97			Value::Int8(v) => Some(v),
98			Value::Int4(v) => Some(v as i64),
99			Value::Int2(v) => Some(v as i64),
100			Value::Int1(v) => Some(v as i64),
101			_ => None,
102		}
103	}
104
105	pub fn i32(&self, name: &str) -> Option<i32> {
106		match self.value(name)? {
107			Value::Int4(v) => Some(v),
108			Value::Int2(v) => Some(v as i32),
109			Value::Int1(v) => Some(v as i32),
110			_ => None,
111		}
112	}
113
114	pub fn i16(&self, name: &str) -> Option<i16> {
115		match self.value(name)? {
116			Value::Int2(v) => Some(v),
117			Value::Int1(v) => Some(v as i16),
118			_ => None,
119		}
120	}
121
122	pub fn i8(&self, name: &str) -> Option<i8> {
123		match self.value(name)? {
124			Value::Int1(v) => Some(v),
125			_ => None,
126		}
127	}
128
129	pub fn u128(&self, name: &str) -> Option<u128> {
130		match self.value(name)? {
131			Value::Uint16(v) => Some(v),
132			_ => None,
133		}
134	}
135
136	pub fn i128(&self, name: &str) -> Option<i128> {
137		match self.value(name)? {
138			Value::Int16(v) => Some(v),
139			_ => None,
140		}
141	}
142
143	pub fn f64(&self, name: &str) -> Option<f64> {
144		match self.value(name)? {
145			Value::Float8(v) => Some(v.into()),
146			Value::Float4(v) => Some(f32::from(v) as f64),
147			_ => None,
148		}
149	}
150
151	pub fn f32(&self, name: &str) -> Option<f32> {
152		match self.value(name)? {
153			Value::Float4(v) => Some(v.into()),
154			_ => None,
155		}
156	}
157
158	pub fn decimal(&self, name: &str) -> Option<Decimal> {
159		match self.value(name)? {
160			Value::Decimal(v) => Some(v),
161			Value::Float8(v) => Some(Decimal::from(f64::from(v))),
162			Value::Float4(v) => Some(Decimal::from(f32::from(v) as f64)),
163			_ => None,
164		}
165	}
166
167	pub fn blob(&self, name: &str) -> Option<Vec<u8>> {
168		match self.value(name)? {
169			Value::Blob(b) => Some(b.as_bytes().to_vec()),
170			_ => None,
171		}
172	}
173
174	pub fn date(&self, name: &str) -> Option<Date> {
175		match self.value(name)? {
176			Value::Date(v) => Some(v),
177			_ => None,
178		}
179	}
180
181	pub fn datetime(&self, name: &str) -> Option<DateTime> {
182		match self.value(name)? {
183			Value::DateTime(v) => Some(v),
184			_ => None,
185		}
186	}
187
188	pub fn time(&self, name: &str) -> Option<Time> {
189		match self.value(name)? {
190			Value::Time(v) => Some(v),
191			_ => None,
192		}
193	}
194
195	pub fn duration(&self, name: &str) -> Option<Duration> {
196		match self.value(name)? {
197			Value::Duration(v) => Some(v),
198			_ => None,
199		}
200	}
201}
202
203pub struct RowRefIter<'a> {
204	columns: &'a Columns,
205	index: usize,
206	end: usize,
207}
208
209impl<'a> Iterator for RowRefIter<'a> {
210	type Item = RowRef<'a>;
211
212	fn next(&mut self) -> Option<Self::Item> {
213		if self.index >= self.end {
214			return None;
215		}
216		let r = RowRef::new(self.columns, self.index);
217		self.index += 1;
218		Some(r)
219	}
220}
221
222impl Columns {
223	pub fn row_ref(&self, index: usize) -> Option<RowRef<'_>> {
224		if index >= self.row_count() {
225			return None;
226		}
227		Some(RowRef::new(self, index))
228	}
229
230	pub fn row_refs(&self) -> RowRefIter<'_> {
231		RowRefIter {
232			columns: self,
233			index: 0,
234			end: self.row_count(),
235		}
236	}
237}