reifydb_core/value/encoded/
layout.rs

1// Copyright (c) reifydb.com 2025
2// This file is licensed under the AGPL-3.0-or-later, see license.md file
3
4use std::{ops::Deref, sync::Arc};
5
6use reifydb_type::Type;
7
8use crate::{CowVec, value::encoded::EncodedValues};
9
10#[derive(Debug, Clone)]
11pub struct EncodedValuesLayout(Arc<EncodedValuesLayoutInner>);
12
13impl Deref for EncodedValuesLayout {
14	type Target = EncodedValuesLayoutInner;
15
16	fn deref(&self) -> &Self::Target {
17		&self.0
18	}
19}
20
21impl EncodedValuesLayout {
22	pub fn new(types: &[Type]) -> Self {
23		Self(Arc::new(EncodedValuesLayoutInner::new(types)))
24	}
25}
26
27#[derive(Debug)]
28pub struct EncodedValuesLayoutInner {
29	pub fields: Vec<Field>,
30	/// size of data in bytes
31	pub static_section_size: usize,
32	/// size of bitvec part in bytes
33	pub bitvec_size: usize,
34	pub alignment: usize,
35}
36
37#[derive(Debug)]
38pub struct Field {
39	pub offset: usize,
40	pub size: usize,
41	pub align: usize,
42	pub r#type: Type,
43}
44
45impl EncodedValuesLayoutInner {
46	fn new(types: &[Type]) -> Self {
47		assert!(!types.is_empty());
48
49		let num_fields = types.len();
50		let bitvec_bytes = (num_fields + 7) / 8;
51
52		let mut offset = bitvec_bytes;
53		let mut fields = Vec::with_capacity(num_fields);
54		let mut max_align = 1;
55
56		for &value in types {
57			let size = value.size();
58			let align = value.alignment();
59
60			offset = align_up(offset, align);
61			fields.push(Field {
62				offset,
63				size,
64				align,
65				r#type: value,
66			});
67
68			offset += size;
69			max_align = max_align.max(align);
70		}
71
72		// Calculate the static section size
73		let static_section_size = align_up(offset, max_align);
74
75		EncodedValuesLayoutInner {
76			fields,
77			static_section_size,
78			alignment: max_align,
79			bitvec_size: bitvec_bytes,
80		}
81	}
82
83	pub fn allocate(&self) -> EncodedValues {
84		let total_size = self.total_static_size();
85		let layout = std::alloc::Layout::from_size_align(total_size, self.alignment).unwrap();
86		unsafe {
87			let ptr = std::alloc::alloc_zeroed(layout);
88			if ptr.is_null() {
89				std::alloc::handle_alloc_error(layout);
90			}
91			// Safe because alloc_zeroed + known size/capacity
92			let vec = Vec::from_raw_parts(ptr, total_size, total_size);
93			EncodedValues(CowVec::new(vec))
94		}
95	}
96
97	pub const fn data_offset(&self) -> usize {
98		self.bitvec_size
99	}
100
101	pub const fn static_section_size(&self) -> usize {
102		self.static_section_size
103	}
104
105	pub const fn total_static_size(&self) -> usize {
106		self.bitvec_size + self.static_section_size
107	}
108
109	pub fn dynamic_section_start(&self) -> usize {
110		self.total_static_size()
111	}
112
113	pub fn dynamic_section_size(&self, row: &EncodedValues) -> usize {
114		row.len().saturating_sub(self.total_static_size())
115	}
116
117	pub fn data_slice<'a>(&'a self, row: &'a EncodedValues) -> &'a [u8] {
118		&row.0[self.data_offset()..]
119	}
120
121	pub fn data_slice_mut<'a>(&'a mut self, row: &'a mut EncodedValues) -> &'a mut [u8] {
122		&mut row.0.make_mut()[self.data_offset()..]
123	}
124
125	pub fn all_defined(&self, row: &EncodedValues) -> bool {
126		let bits = self.fields.len();
127		if bits == 0 {
128			return false;
129		}
130
131		let bitvec_slice = &row[..self.bitvec_size];
132		for (i, &byte) in bitvec_slice.iter().enumerate() {
133			let bits_in_byte = if i == self.bitvec_size - 1 && bits % 8 != 0 {
134				bits % 8
135			} else {
136				8
137			};
138
139			let mask = if bits_in_byte == 8 {
140				0xFF
141			} else {
142				(1u8 << bits_in_byte) - 1
143			};
144			if (byte & mask) != mask {
145				return false;
146			}
147		}
148
149		true
150	}
151
152	pub fn value(&self, index: usize) -> Type {
153		self.fields[index].r#type
154	}
155}
156
157fn align_up(offset: usize, align: usize) -> usize {
158	(offset + align).saturating_sub(1) & !(align.saturating_sub(1))
159}
160
161#[cfg(test)]
162mod tests {
163	mod new {
164		use reifydb_type::Type;
165
166		use crate::value::encoded::EncodedValuesLayout;
167
168		#[test]
169		fn test_single_field_bool() {
170			let layout = EncodedValuesLayout::new(&[Type::Boolean]);
171			assert_eq!(layout.bitvec_size, 1);
172			assert_eq!(layout.fields.len(), 1);
173			assert_eq!(layout.fields[0].offset, 1);
174			assert_eq!(layout.alignment, 1);
175			assert_eq!(layout.static_section_size, layout.fields[0].offset + layout.fields[0].size);
176		}
177
178		#[test]
179		fn test_multiple_fields() {
180			let layout = EncodedValuesLayout::new(&[Type::Int1, Type::Int2, Type::Int4]);
181			assert_eq!(layout.bitvec_size, 1); // 3 fields = 1 byte
182			assert_eq!(layout.fields.len(), 3);
183
184			assert_eq!(layout.fields[0].r#type, Type::Int1);
185			assert_eq!(layout.fields[1].r#type, Type::Int2);
186			assert_eq!(layout.fields[2].r#type, Type::Int4);
187
188			assert_eq!(layout.fields[0].offset, 1);
189			assert_eq!(layout.fields[1].offset, 2);
190			assert_eq!(layout.fields[2].offset, 4);
191
192			assert_eq!(layout.alignment, 4);
193
194			assert_eq!(layout.static_section_size, 8); // 1 + 2 + 4 + 1(alignment)
195		}
196
197		#[test]
198		fn test_offset_and_alignment() {
199			let layout = EncodedValuesLayout::new(&[
200				Type::Uint1,
201				Type::Uint2,
202				Type::Uint4,
203				Type::Uint8,
204				Type::Uint16,
205			]);
206
207			assert_eq!(layout.bitvec_size, 1); // 5 fields = 1 byte
208			assert_eq!(layout.fields.len(), 5);
209
210			assert_eq!(layout.fields[0].offset, 1); // 1. byte is for bitvec
211			assert_eq!(layout.fields[1].offset, 2);
212			assert_eq!(layout.fields[2].offset, 4);
213			assert_eq!(layout.fields[3].offset, 8);
214			assert_eq!(layout.fields[4].offset, 16);
215
216			assert_eq!(layout.alignment, 16);
217
218			assert_eq!(layout.static_section_size, 32); // 1 + 2 + 4 + 8 + 16 + 1 (alignment)
219		}
220
221		#[test]
222		fn test_nine_fields_bitvec_size_two() {
223			let types = vec![
224				Type::Boolean,
225				Type::Int1,
226				Type::Int2,
227				Type::Int4,
228				Type::Int8,
229				Type::Uint1,
230				Type::Uint2,
231				Type::Uint4,
232				Type::Uint8,
233			];
234
235			let layout = EncodedValuesLayout::new(&types);
236
237			// 9 fields → ceil(9/8) = 2 bytes of bitvec bitmap
238			assert_eq!(layout.bitvec_size, 2);
239			assert_eq!(layout.fields.len(), 9);
240
241			assert_eq!(layout.fields[0].offset, 2); // first 2 bytes are for bitvec
242
243			// All field offsets must come after the 2 bitvec bytes
244			for field in &layout.fields {
245				assert!(field.offset >= 2);
246				assert_eq!(field.offset % field.align, 0);
247			}
248
249			assert_eq!(layout.static_section_size % layout.alignment, 0);
250		}
251	}
252
253	mod allocate_row {
254		use reifydb_type::Type;
255
256		use crate::value::encoded::EncodedValuesLayout;
257
258		#[test]
259		fn test_initial_state() {
260			let layout = EncodedValuesLayout::new(&[Type::Boolean, Type::Int1, Type::Uint2]);
261
262			let row = layout.allocate();
263
264			for byte in row.as_slice() {
265				assert_eq!(*byte, 0);
266			}
267
268			assert_eq!(row.len(), layout.total_static_size());
269		}
270
271		#[test]
272		fn test_clone_on_write_semantics() {
273			let layout = EncodedValuesLayout::new(&[Type::Boolean, Type::Boolean, Type::Boolean]);
274
275			let row1 = layout.allocate();
276			let mut row2 = row1.clone();
277
278			// Initially identical
279			assert_eq!(row1.as_slice(), row2.as_slice());
280
281			// Modify one encoded's bitvec bit
282			row2.set_valid(1, true);
283
284			// Internal buffers must now differ
285			assert_ne!(row1.as_ptr(), row2.as_ptr());
286
287			// row1 remains unchanged
288			assert!(!row1.is_defined(1));
289			// row2 has been mutated
290			assert!(row2.is_defined(1));
291		}
292	}
293
294	mod all_defined {
295		use reifydb_type::Type;
296
297		use crate::value::encoded::EncodedValuesLayout;
298
299		#[test]
300		fn test_one_field_none_valid() {
301			let layout = EncodedValuesLayout::new(&[Type::Boolean; 1]);
302			let mut row = layout.allocate();
303			layout.set_undefined(&mut row, 0);
304			assert!(!layout.all_defined(&row));
305		}
306
307		#[test]
308		fn test_one_field_valid() {
309			let layout = EncodedValuesLayout::new(&[Type::Boolean; 1]);
310			let mut row = layout.allocate();
311			layout.set_bool(&mut row, 0, true);
312			assert!(layout.all_defined(&row));
313		}
314
315		#[test]
316		fn test_seven_fields_none_valid() {
317			let types = vec![Type::Boolean; 7];
318			let layout = EncodedValuesLayout::new(&types);
319			let mut row = layout.allocate();
320
321			for idx in 0..7 {
322				layout.set_undefined(&mut row, idx);
323			}
324
325			assert!(!layout.all_defined(&row));
326		}
327
328		#[test]
329		fn test_seven_fields_allv() {
330			let types = vec![Type::Boolean; 7];
331			let layout = EncodedValuesLayout::new(&types);
332			let mut row = layout.allocate();
333
334			for idx in 0..7 {
335				layout.set_bool(&mut row, idx, idx % 2 == 0);
336			}
337
338			assert!(layout.all_defined(&row));
339		}
340
341		#[test]
342		fn test_seven_fields_partial_valid() {
343			let types = vec![Type::Boolean; 7];
344			let layout = EncodedValuesLayout::new(&types);
345			let mut row = layout.allocate();
346
347			for idx in 0..7 {
348				layout.set_bool(&mut row, idx, idx % 2 == 0);
349			}
350
351			for idx in [0, 3] {
352				layout.set_undefined(&mut row, idx);
353			}
354
355			assert!(!layout.all_defined(&row));
356		}
357
358		#[test]
359		fn test_eight_fields_none_valid() {
360			let types = vec![Type::Boolean; 8];
361			let layout = EncodedValuesLayout::new(&types);
362			let mut row = layout.allocate();
363
364			for idx in 0..8 {
365				layout.set_undefined(&mut row, idx);
366			}
367
368			assert!(!layout.all_defined(&row));
369		}
370
371		#[test]
372		fn test_eight_fields_allv() {
373			let types = vec![Type::Boolean; 8];
374			let layout = EncodedValuesLayout::new(&types);
375			let mut row = layout.allocate();
376
377			for idx in 0..8 {
378				layout.set_bool(&mut row, idx, idx % 2 == 0);
379			}
380
381			assert!(layout.all_defined(&row));
382		}
383
384		#[test]
385		fn test_eight_fields_partial_valid() {
386			let types = vec![Type::Boolean; 8];
387			let layout = EncodedValuesLayout::new(&types);
388			let mut row = layout.allocate();
389
390			for idx in 0..8 {
391				layout.set_bool(&mut row, idx, idx % 2 == 0);
392			}
393
394			for idx in [0, 3, 7] {
395				layout.set_undefined(&mut row, idx);
396			}
397
398			assert!(!layout.all_defined(&row));
399		}
400
401		#[test]
402		fn test_nine_fields_allv() {
403			let types = vec![Type::Boolean; 9];
404			let layout = EncodedValuesLayout::new(&types);
405			let mut row = layout.allocate();
406
407			for idx in 0..9 {
408				layout.set_bool(&mut row, idx, idx % 2 == 0);
409			}
410
411			assert!(layout.all_defined(&row));
412		}
413
414		#[test]
415		fn test_nine_fields_none_valid() {
416			let types = vec![Type::Boolean; 9];
417			let layout = EncodedValuesLayout::new(&types);
418			let mut row = layout.allocate();
419
420			for idx in 0..9 {
421				layout.set_undefined(&mut row, idx);
422			}
423
424			assert!(!layout.all_defined(&row));
425		}
426
427		#[test]
428		fn test_nine_fields_partial_valid() {
429			let types = vec![Type::Boolean; 9];
430			let layout = EncodedValuesLayout::new(&types);
431			let mut row = layout.allocate();
432
433			for idx in 0..9 {
434				layout.set_bool(&mut row, idx, idx % 2 == 0);
435			}
436
437			for idx in [0, 3, 7] {
438				layout.set_undefined(&mut row, idx);
439			}
440
441			assert!(!layout.all_defined(&row));
442		}
443
444		#[test]
445		fn test_sixteen_fields_allv() {
446			let types = vec![Type::Boolean; 16];
447			let layout = EncodedValuesLayout::new(&types);
448			let mut row = layout.allocate();
449
450			for idx in 0..16 {
451				layout.set_bool(&mut row, idx, idx % 2 == 0);
452			}
453
454			assert!(layout.all_defined(&row));
455		}
456
457		#[test]
458		fn test_sixteen_fields_none_valid() {
459			let types = vec![Type::Boolean; 16];
460			let layout = EncodedValuesLayout::new(&types);
461			let mut row = layout.allocate();
462
463			for idx in 0..16 {
464				layout.set_undefined(&mut row, idx);
465			}
466
467			assert!(!layout.all_defined(&row));
468		}
469
470		#[test]
471		fn test_sixteen_fields_partial_valid() {
472			let types = vec![Type::Boolean; 16];
473			let layout = EncodedValuesLayout::new(&types);
474			let mut row = layout.allocate();
475
476			for idx in 0..16 {
477				layout.set_bool(&mut row, idx, idx % 2 == 0);
478			}
479
480			for idx in [0, 3, 7] {
481				layout.set_undefined(&mut row, idx);
482			}
483
484			assert!(!layout.all_defined(&row));
485		}
486	}
487}