1pub mod fingerprint;
9pub mod values;
10
11use std::{
12 fmt,
13 fmt::Debug,
14 iter,
15 ops::Deref,
16 ptr,
17 sync::{Arc, OnceLock},
18};
19
20use reifydb_value::{
21 reifydb_assertions,
22 value::{constraint::TypeConstraint, datetime::DateTime, value_type::ValueType},
23};
24use serde::{Deserialize, Serialize};
25
26use super::bytes::{
27 CATALOG_HEADER_SIZE, EncodedRowBuilder, QUEUE_HEADER_SIZE, RowBuilder, SHAPE_HEADER_SIZE, read_created_at,
28 read_defined_at, read_storage_time, read_updated_at, write_fingerprint,
29};
30use crate::row::{
31 catalog::EncodedCatalogRowBuilder,
32 operator::{
33 EncodedOperatorRowBuilder, OPERATOR_HEADER_SIZE, read_created_at as read_operator_created_at,
34 read_time as read_operator_time, read_updated_at as read_operator_updated_at,
35 write_time as write_operator_time,
36 },
37 pod::{EncodedPodRowBuilder, POD_HEADER_SIZE},
38 queue::EncodedQueueRowBuilder,
39 ringbuffer::EncodedRingBufferRowBuilder,
40 series::EncodedSeriesRowBuilder,
41 shape::fingerprint::{RowShapeFingerprint, compute_fingerprint},
42 table::EncodedTableRowBuilder,
43};
44
45const PACKED_MODE_DYNAMIC: u128 = 0x80000000000000000000000000000000;
46const PACKED_MODE_MASK: u128 = 0x80000000000000000000000000000000;
47const PACKED_OFFSET_MASK: u128 = 0x0000000000000000FFFFFFFFFFFFFFFF;
48const PACKED_LENGTH_MASK: u128 = 0x7FFFFFFFFFFFFFFF0000000000000000;
49
50#[repr(u8)]
51#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
52pub enum RowFamily {
53 Catalog = 0x01,
54 Operator = 0x02,
55 Pod = 0x03,
56 Table = 0x04,
57 Series = 0x05,
58 RingBuffer = 0x06,
59 Queue = 0x07,
60}
61
62impl RowFamily {
63 pub const fn header_size(self) -> usize {
64 match self {
65 Self::Catalog => CATALOG_HEADER_SIZE,
66 Self::Operator => OPERATOR_HEADER_SIZE,
67 Self::Pod => POD_HEADER_SIZE,
68 Self::Table => SHAPE_HEADER_SIZE,
69 Self::Series => SHAPE_HEADER_SIZE,
70 Self::RingBuffer => SHAPE_HEADER_SIZE,
71 Self::Queue => QUEUE_HEADER_SIZE,
72 }
73 }
74
75 #[inline]
76 pub fn updated_at(self, row: &[u8]) -> DateTime {
77 match self {
78 Self::Table | Self::Series | Self::RingBuffer | Self::Queue => read_updated_at(row),
79 _ => panic!("{self:?} rows carry no updated_at"),
80 }
81 }
82
83 pub const fn from_u8(value: u8) -> Option<Self> {
84 match value {
85 0x01 => Some(Self::Catalog),
86 0x02 => Some(Self::Operator),
87 0x03 => Some(Self::Pod),
88 0x04 => Some(Self::Table),
89 0x05 => Some(Self::Series),
90 0x06 => Some(Self::RingBuffer),
91 0x07 => Some(Self::Queue),
92 _ => None,
93 }
94 }
95}
96
97#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)]
98pub struct RowShapeField {
99 pub name: String,
100
101 pub constraint: TypeConstraint,
102
103 pub offset: u32,
104
105 pub size: u32,
106}
107
108impl RowShapeField {
109 pub fn new(name: impl Into<String>, constraint: TypeConstraint) -> Self {
110 let storage_type = constraint.storage_type();
111 Self {
112 name: name.into(),
113 constraint,
114 offset: 0,
115 size: storage_type.size() as u32,
116 }
117 }
118
119 pub fn unconstrained(name: impl Into<String>, field_type: ValueType) -> Self {
120 Self::new(name, TypeConstraint::unconstrained(field_type))
121 }
122}
123
124pub struct RowShape(Arc<Inner>);
125
126#[derive(Debug, Serialize, Deserialize)]
127pub struct Inner {
128 pub fingerprint: RowShapeFingerprint,
129
130 pub family: RowFamily,
131
132 pub fields: Vec<RowShapeField>,
133
134 #[serde(skip)]
135 cached_layout: OnceLock<usize>,
136}
137
138impl PartialEq for Inner {
139 fn eq(&self, other: &Self) -> bool {
140 self.fingerprint == other.fingerprint && self.family == other.family && self.fields == other.fields
141 }
142}
143
144impl Eq for Inner {}
145
146impl Deref for RowShape {
147 type Target = Inner;
148
149 fn deref(&self) -> &Self::Target {
150 &self.0
151 }
152}
153
154impl Clone for RowShape {
155 fn clone(&self) -> Self {
156 Self(self.0.clone())
157 }
158}
159
160impl Debug for RowShape {
161 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
162 self.0.fmt(f)
163 }
164}
165
166impl PartialEq for RowShape {
167 fn eq(&self, other: &Self) -> bool {
168 self.0.as_ref() == other.0.as_ref()
169 }
170}
171
172impl Eq for RowShape {}
173
174impl RowShape {
175 pub fn new(family: RowFamily, fields: Vec<RowShapeField>) -> Self {
176 let fields = Self::compute_layout(family, fields);
177 let fingerprint = compute_fingerprint(family, &fields);
178
179 Self(Arc::new(Inner {
180 fingerprint,
181 family,
182 fields,
183 cached_layout: OnceLock::new(),
184 }))
185 }
186
187 pub fn from_parts(family: RowFamily, fingerprint: RowShapeFingerprint, fields: Vec<RowShapeField>) -> Self {
188 Self(Arc::new(Inner {
189 fingerprint,
190 family,
191 fields,
192 cached_layout: OnceLock::new(),
193 }))
194 }
195
196 pub fn family(&self) -> RowFamily {
197 self.family
198 }
199
200 pub fn header_size(&self) -> usize {
201 self.family.header_size()
202 }
203
204 pub fn fingerprint(&self) -> RowShapeFingerprint {
205 self.fingerprint
206 }
207
208 pub fn fields(&self) -> &[RowShapeField] {
209 &self.fields
210 }
211
212 pub fn field_count(&self) -> usize {
213 self.fields.len()
214 }
215
216 pub fn find_field(&self, name: &str) -> Option<&RowShapeField> {
217 self.fields.iter().find(|f| f.name == name)
218 }
219
220 pub fn find_field_index(&self, name: &str) -> Option<usize> {
221 self.fields.iter().position(|f| f.name == name)
222 }
223
224 pub fn get_field(&self, index: usize) -> Option<&RowShapeField> {
225 self.fields.get(index)
226 }
227
228 pub fn get_field_name(&self, index: usize) -> Option<&str> {
229 self.fields.get(index).map(|f| f.name.as_str())
230 }
231
232 pub fn field_names(&self) -> impl Iterator<Item = &str> {
233 self.fields.iter().map(|f| f.name.as_str())
234 }
235
236 fn compute_layout(family: RowFamily, mut fields: Vec<RowShapeField>) -> Vec<RowShapeField> {
237 let bitvec_size = fields.len().div_ceil(8);
238 let mut offset: u32 = (family.header_size() + bitvec_size) as u32;
239
240 for field in fields.iter_mut() {
241 field.size = field.constraint.storage_type().size() as u32;
242 field.offset = offset;
243 offset += field.size;
244 }
245
246 fields
247 }
248
249 pub fn bitvec_size(&self) -> usize {
250 self.fields.len().div_ceil(8)
251 }
252
253 pub fn data_offset(&self) -> usize {
254 self.header_size() + self.bitvec_size()
255 }
256
257 #[inline]
258 pub fn is_defined(&self, row: &[u8], index: usize) -> bool {
259 read_defined_at(row, self.header_size(), index)
260 }
261
262 #[inline]
263 pub(crate) fn set_valid(&self, row: &mut impl RowBuilder, index: usize, valid: bool) {
264 row.set_valid_at(self.header_size(), index, valid);
265 }
266
267 #[inline]
268 pub fn time(&self, row: &[u8]) -> Option<DateTime> {
269 match self.family {
270 RowFamily::Pod => None,
271 RowFamily::Operator => read_operator_time(row),
272 _ => read_storage_time(row),
273 }
274 }
275
276 #[inline]
277 pub fn created_at(&self, row: &[u8]) -> DateTime {
278 match self.family {
279 RowFamily::Pod => panic!("pod rows carry no created_at"),
280 RowFamily::Operator => read_operator_created_at(row),
281 _ => read_created_at(row),
282 }
283 }
284
285 #[inline]
286 pub fn updated_at(&self, row: &[u8]) -> DateTime {
287 match self.family {
288 RowFamily::Pod => panic!("pod rows carry no updated_at"),
289 RowFamily::Operator => read_operator_updated_at(row),
290 _ => read_updated_at(row),
291 }
292 }
293
294 fn get_cached_layout(&self) -> usize {
295 *self.cached_layout.get_or_init(|| match self.fields.last() {
296 Some(last) => last.offset as usize + last.size as usize,
297 None => self.header_size() + self.bitvec_size(),
298 })
299 }
300
301 pub fn total_static_size(&self) -> usize {
302 self.get_cached_layout()
303 }
304
305 pub fn dynamic_section_start(&self) -> usize {
306 self.total_static_size()
307 }
308
309 pub fn dynamic_section_size(&self, row: &[u8]) -> usize {
310 row.len().saturating_sub(self.total_static_size())
311 }
312
313 pub(crate) fn read_dynamic_ref(&self, row: &[u8], index: usize) -> Option<(usize, usize)> {
314 if !self.is_defined(row, index) {
315 return None;
316 }
317 let field = &self.fields()[index];
318 match field.constraint.get_type().inner_type() {
319 ValueType::Utf8 | ValueType::Blob | ValueType::Any => {
320 let ref_slice = &row[field.offset as usize..field.offset as usize + 8];
321 let offset =
322 u32::from_le_bytes([ref_slice[0], ref_slice[1], ref_slice[2], ref_slice[3]])
323 as usize;
324 let length =
325 u32::from_le_bytes([ref_slice[4], ref_slice[5], ref_slice[6], ref_slice[7]])
326 as usize;
327 Some((offset, length))
328 }
329 ValueType::Int | ValueType::Uint | ValueType::Decimal => {
330 let packed = unsafe {
334 (row.as_ptr().add(field.offset as usize) as *const u128).read_unaligned()
335 };
336 let packed = u128::from_le(packed);
337 if packed & PACKED_MODE_MASK != 0 {
338 let offset = (packed & PACKED_OFFSET_MASK) as usize;
339 let length = ((packed & PACKED_LENGTH_MASK) >> 64) as usize;
340 Some((offset, length))
341 } else {
342 None
343 }
344 }
345 _ => None,
346 }
347 }
348
349 pub(crate) fn write_dynamic_ref(&self, row: &mut impl RowBuilder, index: usize, offset: usize, length: usize) {
350 let field = &self.fields()[index];
351 match field.constraint.get_type().inner_type() {
352 ValueType::Utf8 | ValueType::Blob | ValueType::Any => {
353 let ref_slice =
354 &mut row.as_mut_slice()[field.offset as usize..field.offset as usize + 8];
355 ref_slice[0..4].copy_from_slice(&(offset as u32).to_le_bytes());
356 ref_slice[4..8].copy_from_slice(&(length as u32).to_le_bytes());
357 }
358 ValueType::Int | ValueType::Uint | ValueType::Decimal => {
359 let offset_part = (offset as u128) & PACKED_OFFSET_MASK;
360 let length_part = ((length as u128) << 64) & PACKED_LENGTH_MASK;
361 let packed = PACKED_MODE_DYNAMIC | offset_part | length_part;
362 unsafe {
366 ptr::write_unaligned(
367 row.as_mut_slice().as_mut_ptr().add(field.offset as usize) as *mut u128,
368 packed.to_le(),
369 );
370 }
371 }
372 _ => {}
373 }
374 }
375
376 pub(crate) fn replace_dynamic_data(&self, row: &mut impl RowBuilder, index: usize, new_data: &[u8]) {
377 if let Some((old_offset, old_length)) = self.read_dynamic_ref(row.as_slice(), index) {
378 let delta = new_data.len() as isize - old_length as isize;
379
380 let refs_to_update: Vec<(usize, usize, usize)> = if delta != 0 {
381 self.fields()
382 .iter()
383 .enumerate()
384 .filter(|(i, _)| *i != index && self.is_defined(row.as_slice(), *i))
385 .filter_map(|(i, _)| {
386 self.read_dynamic_ref(row.as_slice(), i)
387 .filter(|(off, _)| *off > old_offset)
388 .map(|(off, len)| (i, off, len))
389 })
390 .collect()
391 } else {
392 vec![]
393 };
394
395 let dynamic_start = self.dynamic_section_start();
396 let abs_start = dynamic_start + old_offset;
397 let abs_end = abs_start + old_length;
398 row.splice(abs_start..abs_end, new_data.iter().copied());
399
400 self.write_dynamic_ref(row, index, old_offset, new_data.len());
401
402 for (i, off, len) in refs_to_update {
403 let new_off = (off as isize + delta) as usize;
404 self.write_dynamic_ref(row, i, new_off, len);
405 }
406 } else {
407 let dynamic_offset = self.dynamic_section_size(row.as_slice());
408 row.extend_from_slice(new_data);
409 self.write_dynamic_ref(row, index, dynamic_offset, new_data.len());
410 }
411 self.set_valid(row, index, true);
412 }
413
414 pub(crate) fn remove_dynamic_data(&self, row: &mut impl RowBuilder, index: usize) {
415 if let Some((old_offset, old_length)) = self.read_dynamic_ref(row.as_slice(), index) {
416 let refs_to_update: Vec<(usize, usize, usize)> = self
417 .fields()
418 .iter()
419 .enumerate()
420 .filter(|(i, _)| *i != index && self.is_defined(row.as_slice(), *i))
421 .filter_map(|(i, _)| {
422 self.read_dynamic_ref(row.as_slice(), i)
423 .filter(|(off, _)| *off > old_offset)
424 .map(|(off, len)| (i, off, len))
425 })
426 .collect();
427
428 let dynamic_start = self.dynamic_section_start();
429 let abs_start = dynamic_start + old_offset;
430 let abs_end = abs_start + old_length;
431 row.splice(abs_start..abs_end, iter::empty());
432
433 for (i, off, len) in refs_to_update {
434 let new_off = off - old_length;
435 self.write_dynamic_ref(row, i, new_off, len);
436 }
437 }
438 }
439
440 fn allocate(&self) -> EncodedRowBuilder {
441 let total_size = self.get_cached_layout();
442 let mut row = EncodedRowBuilder::zeroed(total_size);
443 match self.family {
444 RowFamily::Pod => {}
445 RowFamily::Operator => write_operator_time(row.as_mut_slice(), DateTime::MAX),
446 _ => write_fingerprint(row.as_mut_slice(), self.fingerprint),
447 }
448 reifydb_assertions! {
449 assert!(
450 row.len() == total_size,
451 "allocated row length does not match the shape total_static_size, so any field accessor using pre-computed offsets will read from garbage memory (row_len={} total_size={})",
452 row.len(),
453 total_size
454 );
455 }
456 row
457 }
458
459 pub fn allocate_catalog(&self) -> EncodedCatalogRowBuilder {
460 assert_eq!(self.family, RowFamily::Catalog, "allocate_catalog on a shape of another family");
461 EncodedCatalogRowBuilder::wrap(self.allocate())
462 }
463
464 pub fn allocate_operator(&self) -> EncodedOperatorRowBuilder {
465 assert_eq!(self.family, RowFamily::Operator, "allocate_operator on a shape of another family");
466 EncodedOperatorRowBuilder::wrap(self.allocate())
467 }
468
469 pub fn allocate_pod(&self) -> EncodedPodRowBuilder {
470 assert_eq!(self.family, RowFamily::Pod, "allocate_pod on a shape of another family");
471 EncodedPodRowBuilder::wrap(self.allocate())
472 }
473
474 pub fn allocate_table(&self) -> EncodedTableRowBuilder {
475 assert_eq!(self.family, RowFamily::Table, "allocate_table on a shape of another family");
476 EncodedTableRowBuilder::wrap(self.allocate())
477 }
478
479 pub fn allocate_series(&self) -> EncodedSeriesRowBuilder {
480 assert_eq!(self.family, RowFamily::Series, "allocate_series on a shape of another family");
481 EncodedSeriesRowBuilder::wrap(self.allocate())
482 }
483
484 pub fn allocate_ringbuffer(&self) -> EncodedRingBufferRowBuilder {
485 assert_eq!(self.family, RowFamily::RingBuffer, "allocate_ringbuffer on a shape of another family");
486 EncodedRingBufferRowBuilder::wrap(self.allocate())
487 }
488
489 pub fn allocate_queue(&self) -> EncodedQueueRowBuilder {
490 assert_eq!(self.family, RowFamily::Queue, "allocate_queue on a shape of another family");
491 EncodedQueueRowBuilder::wrap(self.allocate())
492 }
493
494 pub fn set_none(&self, row: &mut impl RowBuilder, index: usize) {
495 self.remove_dynamic_data(row, index);
496 self.set_valid(row, index, false);
497 }
498
499 pub fn testing(family: RowFamily, types: &[ValueType]) -> Self {
500 RowShape::new(
501 family,
502 types.iter()
503 .enumerate()
504 .map(|(i, t)| RowShapeField::unconstrained(format!("f{}", i), t.clone()))
505 .collect(),
506 )
507 }
508}