Skip to main content

reifydb_core/encoded/
row.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2025 ReifyDB
3
4use std::ops::Deref;
5
6use reifydb_type::util::cowvec::CowVec;
7use serde::{Deserialize, Serialize};
8
9use crate::encoded::shape::fingerprint::RowShapeFingerprint;
10
11/// Size of shape header (fingerprint) in bytes
12pub const SHAPE_HEADER_SIZE: usize = 8;
13pub const TIMESTAMP_TRAILER_SIZE: usize = 16;
14
15/// A boxed values iterator.
16pub type EncodedRowIter = Box<dyn EncodedRowIterator>;
17
18pub trait EncodedRowIterator: Iterator<Item = EncodedRow> {}
19
20impl<I: Iterator<Item = EncodedRow>> EncodedRowIterator for I {}
21
22#[derive(Debug, Clone, Serialize, Deserialize)]
23// [shape_finger_print]:[bitvec]:[static_values]:[dynamic_values]
24#[derive(PartialEq, Eq)]
25pub struct EncodedRow(pub CowVec<u8>);
26
27impl Deref for EncodedRow {
28	type Target = CowVec<u8>;
29
30	fn deref(&self) -> &Self::Target {
31		&self.0
32	}
33}
34
35impl EncodedRow {
36	pub fn make_mut(&mut self) -> &mut [u8] {
37		self.0.make_mut()
38	}
39
40	#[inline]
41	pub fn is_defined(&self, index: usize) -> bool {
42		let byte = SHAPE_HEADER_SIZE + index / 8;
43		let bit = index % 8;
44		(self.0[byte] & (1 << bit)) != 0
45	}
46
47	pub(crate) fn set_valid(&mut self, index: usize, valid: bool) {
48		let byte = SHAPE_HEADER_SIZE + index / 8;
49		let bit = index % 8;
50		if valid {
51			self.0.make_mut()[byte] |= 1 << bit;
52		} else {
53			self.0.make_mut()[byte] &= !(1 << bit);
54		}
55	}
56
57	/// Read the shape fingerprint from the header
58	#[inline]
59	pub fn fingerprint(&self) -> RowShapeFingerprint {
60		let bytes: [u8; 8] = self.0[0..8].try_into().unwrap();
61		RowShapeFingerprint::from_le_bytes(bytes)
62	}
63
64	/// Write the shape fingerprint to the header
65	pub fn set_fingerprint(&mut self, fingerprint: RowShapeFingerprint) {
66		self.0.make_mut()[0..8].copy_from_slice(&fingerprint.to_le_bytes());
67	}
68
69	#[inline]
70	pub fn created_at_nanos(&self) -> u64 {
71		let len = self.0.len();
72		if len < TIMESTAMP_TRAILER_SIZE {
73			return 0;
74		}
75		let offset = len - TIMESTAMP_TRAILER_SIZE;
76		let bytes: [u8; 8] = self.0[offset..offset + 8].try_into().unwrap();
77		u64::from_le_bytes(bytes)
78	}
79
80	#[inline]
81	pub fn updated_at_nanos(&self) -> u64 {
82		let len = self.0.len();
83		if len < TIMESTAMP_TRAILER_SIZE {
84			return 0;
85		}
86		let offset = len - TIMESTAMP_TRAILER_SIZE + 8;
87		let bytes: [u8; 8] = self.0[offset..offset + 8].try_into().unwrap();
88		u64::from_le_bytes(bytes)
89	}
90
91	pub fn set_timestamps(&mut self, created_at_nanos: u64, updated_at_nanos: u64) {
92		let buf = self.0.make_mut();
93		buf.extend_from_slice(&created_at_nanos.to_le_bytes());
94		buf.extend_from_slice(&updated_at_nanos.to_le_bytes());
95	}
96}