reifydb_core/value/encoded/
layout.rs1use 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 pub static_section_size: usize,
32 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 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 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); 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); }
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); assert_eq!(layout.fields.len(), 5);
209
210 assert_eq!(layout.fields[0].offset, 1); 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); }
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 assert_eq!(layout.bitvec_size, 2);
239 assert_eq!(layout.fields.len(), 9);
240
241 assert_eq!(layout.fields[0].offset, 2); 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 assert_eq!(row1.as_slice(), row2.as_slice());
280
281 row2.set_valid(1, true);
283
284 assert_ne!(row1.as_ptr(), row2.as_ptr());
286
287 assert!(!row1.is_defined(1));
289 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}