Skip to main content

reifydb_codec/primitive/
digest.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2026 ReifyDB
3
4use reifydb_value::{
5	reifydb_assertions,
6	value::{digest::Digest, value_type::ValueType},
7};
8
9use crate::row::{bytes::RowBuilder, shape::RowShape};
10
11impl RowShape {
12	pub fn set_digest(&self, row: &mut impl RowBuilder, index: usize, value: &Digest) {
13		reifydb_assertions! {
14			assert!(
15				row.len() >= self.total_static_size(),
16				"row/shape size mismatch: row.len()={} < total_static_size()={}",
17				row.len(),
18				self.total_static_size()
19			);
20		}
21		self.check_digest_type(index, value);
22		self.replace_dynamic_data(row, index, &value.encode());
23	}
24
25	pub fn get_digest(&self, row: &[u8], index: usize) -> Digest {
26		let field = &self.fields()[index];
27		reifydb_assertions! {
28			assert!(
29				row.len() >= self.total_static_size(),
30				"row/shape size mismatch: row.len()={} < total_static_size()={}",
31				row.len(),
32				self.total_static_size()
33			);
34		}
35
36		let ref_slice = &row[field.offset as usize..field.offset as usize + 8];
37		let offset = u32::from_le_bytes([ref_slice[0], ref_slice[1], ref_slice[2], ref_slice[3]]) as usize;
38		let length = u32::from_le_bytes([ref_slice[4], ref_slice[5], ref_slice[6], ref_slice[7]]) as usize;
39
40		let data_start = self.dynamic_section_start() + offset;
41		let bytes = row.get(data_start..data_start + length).unwrap_or_else(|| {
42			panic!(
43				"corrupt digest in column {:?}: bytes {data_start}..{} lie outside the {}-byte row",
44				field.name,
45				data_start + length,
46				row.len()
47			)
48		});
49		let digest = Digest::decode(bytes)
50			.unwrap_or_else(|error| panic!("corrupt digest in column {:?}: {error}", field.name));
51		self.check_digest_type(index, &digest);
52		digest
53	}
54
55	fn check_digest_type(&self, index: usize, digest: &Digest) {
56		let field = &self.fields()[index];
57		match field.constraint.get_type().inner_type() {
58			ValueType::Digest {
59				inner,
60				accuracy,
61			} if **inner == *digest.inner() && *accuracy == digest.accuracy() => {}
62			declared => panic!(
63				"column {:?} of type {declared} cannot hold a {}",
64				field.name,
65				ValueType::Digest {
66					inner: Box::new(digest.inner().clone()),
67					accuracy: digest.accuracy(),
68				}
69			),
70		}
71	}
72}