Skip to main content

reifydb_codec/primitive/
blob.rs

1// SPDX-License-Identifier: Apache-2.0
2// Copyright (c) 2026 ReifyDB
3
4use reifydb_value::{
5	reifydb_assertions,
6	value::{blob::Blob, value_type::ValueType},
7};
8
9use crate::row::{bytes::RowBuilder, shape::RowShape};
10
11impl RowShape {
12	pub fn set_blob(&self, row: &mut impl RowBuilder, index: usize, value: &Blob) {
13		self.set_blob_from_slice(row, index, value.as_bytes());
14	}
15
16	pub fn set_blob_from_slice(&self, row: &mut impl RowBuilder, index: usize, bytes: &[u8]) {
17		reifydb_assertions! {
18			assert!(
19				row.len() >= self.total_static_size(),
20				"row/shape size mismatch: row.len()={} < total_static_size()={}",
21				row.len(),
22				self.total_static_size()
23			);
24			assert_eq!(*self.fields()[index].constraint.get_type().inner_type(), ValueType::Blob);
25		}
26		self.replace_dynamic_data(row, index, bytes);
27	}
28
29	pub fn get_blob(&self, row: &[u8], index: usize) -> Blob {
30		Blob::from_slice(self.get_blob_slice(row, index))
31	}
32
33	pub fn get_blob_slice<'a>(&self, row: &'a [u8], index: usize) -> &'a [u8] {
34		let field = &self.fields()[index];
35		reifydb_assertions! {
36			assert!(
37				row.len() >= self.total_static_size(),
38				"row/shape size mismatch: row.len()={} < total_static_size()={}",
39				row.len(),
40				self.total_static_size()
41			);
42			assert_eq!(*field.constraint.get_type().inner_type(), ValueType::Blob);
43		}
44
45		let ref_slice = &row[field.offset as usize..field.offset as usize + 8];
46		let offset = u32::from_le_bytes([ref_slice[0], ref_slice[1], ref_slice[2], ref_slice[3]]) as usize;
47		let length = u32::from_le_bytes([ref_slice[4], ref_slice[5], ref_slice[6], ref_slice[7]]) as usize;
48
49		let dynamic_start = self.dynamic_section_start();
50		let blob_start = dynamic_start + offset;
51		&row[blob_start..blob_start + length]
52	}
53
54	pub fn get_blob_slice_builder<'a>(&self, row: &'a impl RowBuilder, index: usize) -> &'a [u8] {
55		let field = &self.fields()[index];
56		let buffer = row.as_slice();
57		let ref_slice = &buffer[field.offset as usize..field.offset as usize + 8];
58		let offset = u32::from_le_bytes([ref_slice[0], ref_slice[1], ref_slice[2], ref_slice[3]]) as usize;
59		let length = u32::from_le_bytes([ref_slice[4], ref_slice[5], ref_slice[6], ref_slice[7]]) as usize;
60		let blob_start = self.dynamic_section_start() + offset;
61		&buffer[blob_start..blob_start + length]
62	}
63
64	pub fn get_blob_slice_mut<'a>(&self, row: &'a mut [u8], index: usize) -> &'a mut [u8] {
65		let field = &self.fields()[index];
66		reifydb_assertions! {
67			assert!(
68				row.len() >= self.total_static_size(),
69				"row/shape size mismatch: row.len()={} < total_static_size()={}",
70				row.len(),
71				self.total_static_size()
72			);
73			assert_eq!(*field.constraint.get_type().inner_type(), ValueType::Blob);
74		}
75
76		let ref_slice = &row[field.offset as usize..field.offset as usize + 8];
77		let offset = u32::from_le_bytes([ref_slice[0], ref_slice[1], ref_slice[2], ref_slice[3]]) as usize;
78		let length = u32::from_le_bytes([ref_slice[4], ref_slice[5], ref_slice[6], ref_slice[7]]) as usize;
79
80		let blob_start = self.dynamic_section_start() + offset;
81		&mut row[blob_start..blob_start + length]
82	}
83
84	pub fn try_get_blob(&self, row: &[u8], index: usize) -> Option<Blob> {
85		if self.is_defined(row, index) && self.fields()[index].constraint.get_type() == ValueType::Blob {
86			Some(self.get_blob(row, index))
87		} else {
88			None
89		}
90	}
91}