Skip to main content

reifydb_codec/key/
column.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2026 ReifyDB
3
4use reifydb_value::{
5	Result,
6	value::{
7		Value,
8		column_view::{ColumnView, ViewData},
9		constraint::{precision::Precision, scale::Scale},
10		container::{
11			decimal_array::decimal_at,
12			dictionary_array,
13			temporal_array::{dates, datetimes, durations, times},
14			uuid_array::{identity_ids, uuid4s, uuid7s},
15			wide_int_array::wide_at,
16		},
17	},
18};
19
20use crate::{
21	key::{
22		serializer::{KeySerializer, keycode_type_descending},
23		sort::SortOrder,
24	},
25	tag::{TypeTag, ValueKind},
26};
27
28enum Cell {
29	Written,
30	Value(Value),
31}
32
33pub fn extend_column_with_direction(view: &ColumnView, direction: SortOrder, rows: &mut [KeySerializer]) -> Result<()> {
34	let ascending = matches!(direction, SortOrder::Asc);
35	match &view.data {
36		ViewData::Bool(a) => typed(view, rows, ascending, |row, i, _| {
37			row.extend_kind(ValueKind::Boolean).extend_bool(a.value(i));
38			Ok(Cell::Written)
39		}),
40		ViewData::Float4(a) => typed(view, rows, ascending, |row, i, none| {
41			let value = a.value(i);
42			if value.is_nan() {
43				row.extend_raw(none);
44			} else {
45				row.extend_kind(ValueKind::Float4).extend_f32(if value == 0.0 {
46					0.0
47				} else {
48					value
49				});
50			}
51			Ok(Cell::Written)
52		}),
53		ViewData::Float8(a) => typed(view, rows, ascending, |row, i, none| {
54			let value = a.value(i);
55			if value.is_nan() {
56				row.extend_raw(none);
57			} else {
58				row.extend_kind(ValueKind::Float8).extend_f64(if value == 0.0 {
59					0.0
60				} else {
61					value
62				});
63			}
64			Ok(Cell::Written)
65		}),
66		ViewData::Int1(a) => typed(view, rows, ascending, |row, i, _| {
67			row.extend_kind(ValueKind::Int1).extend_i8(a.value(i));
68			Ok(Cell::Written)
69		}),
70		ViewData::Int2(a) => typed(view, rows, ascending, |row, i, _| {
71			row.extend_kind(ValueKind::Int2).extend_i16(a.value(i));
72			Ok(Cell::Written)
73		}),
74		ViewData::Int4(a) => typed(view, rows, ascending, |row, i, _| {
75			row.extend_kind(ValueKind::Int4).extend_i32(a.value(i));
76			Ok(Cell::Written)
77		}),
78		ViewData::Int8(a) => typed(view, rows, ascending, |row, i, _| {
79			row.extend_kind(ValueKind::Int8).extend_i64(a.value(i));
80			Ok(Cell::Written)
81		}),
82		ViewData::Int16(a) => typed(view, rows, ascending, |row, i, _| match wide_at::<i128>(a, i) {
83			Some(value) => {
84				row.extend_kind(ValueKind::Int16).extend_i128(value);
85				Ok(Cell::Written)
86			}
87			None => Ok(Cell::Value(view.get_value(i))),
88		}),
89		ViewData::Uint1(a) => typed(view, rows, ascending, |row, i, _| {
90			row.extend_kind(ValueKind::Uint1).extend_u8(a.value(i));
91			Ok(Cell::Written)
92		}),
93		ViewData::Uint2(a) => typed(view, rows, ascending, |row, i, _| {
94			row.extend_kind(ValueKind::Uint2).extend_u16(a.value(i));
95			Ok(Cell::Written)
96		}),
97		ViewData::Uint4(a) => typed(view, rows, ascending, |row, i, _| {
98			row.extend_kind(ValueKind::Uint4).extend_u32(a.value(i));
99			Ok(Cell::Written)
100		}),
101		ViewData::Uint8(a) => typed(view, rows, ascending, |row, i, _| {
102			row.extend_kind(ValueKind::Uint8).extend_u64(a.value(i));
103			Ok(Cell::Written)
104		}),
105		ViewData::Uint16(a) => typed(view, rows, ascending, |row, i, _| match wide_at::<u128>(a, i) {
106			Some(value) => {
107				row.extend_kind(ValueKind::Uint16).extend_u128(value);
108				Ok(Cell::Written)
109			}
110			None => Ok(Cell::Value(view.get_value(i))),
111		}),
112		ViewData::Utf8 {
113			container,
114			..
115		} => typed(view, rows, ascending, |row, i, _| {
116			row.extend_kind(ValueKind::Utf8).extend_str(container.value(i));
117			Ok(Cell::Written)
118		}),
119		ViewData::Blob {
120			container,
121			..
122		} => typed(view, rows, ascending, |row, i, _| {
123			row.extend_kind(ValueKind::Blob).extend_bytes(container.value(i));
124			Ok(Cell::Written)
125		}),
126		ViewData::Date(a) => {
127			let values = dates(a);
128			typed(view, rows, ascending, |row, i, _| {
129				row.extend_kind(ValueKind::Date).extend_date(&values[i]);
130				Ok(Cell::Written)
131			})
132		}
133		ViewData::DateTime(a) => {
134			let values = datetimes(a);
135			typed(view, rows, ascending, |row, i, _| {
136				row.extend_kind(ValueKind::DateTime).extend_datetime(&values[i]);
137				Ok(Cell::Written)
138			})
139		}
140		ViewData::Time(a) => {
141			let values = times(a);
142			typed(view, rows, ascending, |row, i, _| {
143				row.extend_kind(ValueKind::Time).extend_time(&values[i]);
144				Ok(Cell::Written)
145			})
146		}
147		ViewData::Duration(a) => {
148			let values = durations(a);
149			typed(view, rows, ascending, |row, i, _| {
150				row.extend_kind(ValueKind::Duration).extend_duration(&values[i]);
151				Ok(Cell::Written)
152			})
153		}
154		ViewData::IdentityId(a) => {
155			let values = identity_ids(a);
156			typed(view, rows, ascending, |row, i, _| {
157				row.extend_kind(ValueKind::IdentityId).extend_identity_id(&values[i]);
158				Ok(Cell::Written)
159			})
160		}
161		ViewData::Uuid4(a) => {
162			let values = uuid4s(a);
163			typed(view, rows, ascending, |row, i, _| {
164				row.extend_kind(ValueKind::Uuid4).extend_uuid4(&values[i]);
165				Ok(Cell::Written)
166			})
167		}
168		ViewData::Uuid7(a) => {
169			let values = uuid7s(a);
170			typed(view, rows, ascending, |row, i, _| {
171				row.extend_kind(ValueKind::Uuid7).extend_uuid7(&values[i]);
172				Ok(Cell::Written)
173			})
174		}
175		ViewData::Decimal(d) => typed(view, rows, ascending, |row, i, _| match decimal_at(d, i) {
176			Some(value) => {
177				row.extend_kind(ValueKind::Decimal).extend_decimal(
178					&value,
179					Precision::MAX,
180					Scale::new(value.scale()),
181				)?;
182				Ok(Cell::Written)
183			}
184			None => Ok(Cell::Value(view.get_value(i))),
185		}),
186		ViewData::DictionaryId {
187			container,
188			..
189		} => typed(view, rows, ascending, |row, i, _| match dictionary_array::get(container, i) {
190			Some(id) => {
191				row.try_extend_value(&Value::DictionaryId(id))?;
192				Ok(Cell::Written)
193			}
194			None => Ok(Cell::Value(view.get_value(i))),
195		}),
196		ViewData::Any {
197			..
198		}
199		| ViewData::Digest {
200			..
201		}
202		| ViewData::None {
203			..
204		} => {
205			for (i, row) in rows.iter_mut().enumerate() {
206				extend_cell(row, &view.get_value(i), ascending)?;
207			}
208			Ok(())
209		}
210	}
211}
212
213fn typed(
214	view: &ColumnView,
215	rows: &mut [KeySerializer],
216	ascending: bool,
217	mut write: impl FnMut(&mut KeySerializer, usize, &[u8]) -> Result<Cell>,
218) -> Result<()> {
219	let base = view.base_type();
220	let flip = ascending == keycode_type_descending(&base);
221	let none = [
222		ValueKind::None.byte(),
223		TypeTag::of_type(&base).expect("option nesting in a key none inner exceeds the supported depth").byte(),
224	];
225	for (i, row) in rows.iter_mut().enumerate() {
226		if view.none_at(i) {
227			let start = row.len();
228			row.extend_raw(&none);
229			if flip {
230				row.complement_from(start);
231			}
232			continue;
233		}
234		let start = row.len();
235		match write(row, i, &none)? {
236			Cell::Written => {
237				if flip {
238					row.complement_from(start);
239				}
240			}
241			Cell::Value(value) => extend_cell(row, &value, ascending)?,
242		}
243	}
244	Ok(())
245}
246
247fn extend_cell(row: &mut KeySerializer, value: &Value, ascending: bool) -> Result<()> {
248	let ty = match value {
249		Value::None {
250			inner,
251		} => inner.clone(),
252		present => present.get_type(),
253	};
254	let start = row.len();
255	row.try_extend_value(value)?;
256	if ascending == keycode_type_descending(&ty) {
257		row.complement_from(start);
258	}
259	Ok(())
260}