reifydb_codec/row/shape/
fingerprint.rs1use std::ops::Deref;
5
6use reifydb_value::util::hash::{Hash64, xxh3_64};
7use serde::{Deserialize, Serialize};
8
9use crate::{
10 constraint::encode_type_constraint,
11 row::shape::{RowFamily, RowShapeField},
12};
13
14#[repr(transparent)]
15#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
16pub struct RowShapeFingerprint(pub Hash64);
17
18impl Deref for RowShapeFingerprint {
19 type Target = u64;
20
21 fn deref(&self) -> &Self::Target {
22 &self.0.0
23 }
24}
25
26impl RowShapeFingerprint {
27 #[inline]
28 pub const fn new(value: u64) -> Self {
29 Self(Hash64(value))
30 }
31
32 #[inline]
33 pub const fn zero() -> Self {
34 Self(Hash64(0))
35 }
36
37 #[inline]
38 pub const fn as_u64(&self) -> u64 {
39 self.0.0
40 }
41
42 #[inline]
43 pub const fn to_le_bytes(&self) -> [u8; 8] {
44 self.0.0.to_le_bytes()
45 }
46
47 #[inline]
48 pub const fn from_le_bytes(bytes: [u8; 8]) -> Self {
49 Self(Hash64(u64::from_le_bytes(bytes)))
50 }
51}
52
53impl From<Hash64> for RowShapeFingerprint {
54 fn from(hash: Hash64) -> Self {
55 Self(hash)
56 }
57}
58
59impl From<RowShapeFingerprint> for Hash64 {
60 fn from(fp: RowShapeFingerprint) -> Self {
61 fp.0
62 }
63}
64
65impl From<u64> for RowShapeFingerprint {
66 fn from(value: u64) -> Self {
67 Self(Hash64(value))
68 }
69}
70
71pub fn compute_fingerprint(family: RowFamily, fields: &[RowShapeField]) -> RowShapeFingerprint {
72 let estimated_size = 3 + fields.len() * 42;
73 let mut buffer = Vec::with_capacity(estimated_size);
74
75 buffer.push(family as u8);
76
77 let field_count = fields.len() as u16;
78 buffer.extend_from_slice(&field_count.to_le_bytes());
79
80 for field in fields {
81 let name_bytes = field.name.as_bytes();
82 let name_len = name_bytes.len() as u16;
83 buffer.extend_from_slice(&name_len.to_le_bytes());
84 buffer.extend_from_slice(name_bytes);
85
86 let extern_c = encode_type_constraint(&field.constraint)
87 .expect("row shape field constraint exceeds tag capacity");
88 buffer.push(extern_c.base_type);
89 buffer.push(extern_c.constraint_type);
90 buffer.extend_from_slice(&extern_c.constraint_param1.to_le_bytes());
91 buffer.extend_from_slice(&extern_c.constraint_param2.to_le_bytes());
92 }
93
94 RowShapeFingerprint(xxh3_64(&buffer))
95}