Skip to main content

reifydb_codec/row/shape/
fingerprint.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2026 ReifyDB
3
4use 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}