1use reifydb_type::{Blob, Type};
5
6use crate::value::encoded::{EncodedValues, EncodedValuesLayout};
7
8impl EncodedValuesLayout {
9 pub fn set_blob(&self, row: &mut EncodedValues, index: usize, value: &Blob) {
10 let field = &self.fields[index];
11 debug_assert_eq!(field.r#type, Type::Blob);
12 debug_assert!(!row.is_defined(index), "BLOB field {} already set", index);
13
14 let bytes = value.as_bytes();
15
16 let dynamic_offset = self.dynamic_section_size(row);
19
20 row.0.extend_from_slice(bytes);
22
23 let ref_slice = &mut row.0.make_mut()[field.offset..field.offset + 8];
26 ref_slice[0..4].copy_from_slice(&(dynamic_offset as u32).to_le_bytes());
27 ref_slice[4..8].copy_from_slice(&(bytes.len() as u32).to_le_bytes());
28
29 row.set_valid(index, true);
30 }
31
32 pub fn get_blob(&self, row: &EncodedValues, index: usize) -> Blob {
33 let field = &self.fields[index];
34 debug_assert_eq!(field.r#type, Type::Blob);
35
36 let ref_slice = &row.as_slice()[field.offset..field.offset + 8];
38 let offset = u32::from_le_bytes([ref_slice[0], ref_slice[1], ref_slice[2], ref_slice[3]]) as usize;
39 let length = u32::from_le_bytes([ref_slice[4], ref_slice[5], ref_slice[6], ref_slice[7]]) as usize;
40
41 let dynamic_start = self.dynamic_section_start();
43 let blob_start = dynamic_start + offset;
44 let blob_slice = &row.as_slice()[blob_start..blob_start + length];
45
46 Blob::from_slice(blob_slice)
47 }
48
49 pub fn try_get_blob(&self, row: &EncodedValues, index: usize) -> Option<Blob> {
50 if row.is_defined(index) && self.fields[index].r#type == Type::Blob {
51 Some(self.get_blob(row, index))
52 } else {
53 None
54 }
55 }
56}
57
58#[cfg(test)]
59mod tests {
60 use reifydb_type::{Blob, Type};
61
62 use crate::value::encoded::EncodedValuesLayout;
63
64 #[test]
65 fn test_set_get_blob() {
66 let layout = EncodedValuesLayout::new(&[Type::Blob]);
67 let mut row = layout.allocate();
68
69 let blob = Blob::from_slice(&[1, 2, 3, 4, 5]);
70 layout.set_blob(&mut row, 0, &blob);
71 assert_eq!(layout.get_blob(&row, 0), blob);
72 }
73
74 #[test]
75 fn test_try_get_blob() {
76 let layout = EncodedValuesLayout::new(&[Type::Blob]);
77 let mut row = layout.allocate();
78
79 assert_eq!(layout.try_get_blob(&row, 0), None);
80
81 let blob = Blob::from_slice(&[1, 2, 3, 4, 5]);
82 layout.set_blob(&mut row, 0, &blob);
83 assert_eq!(layout.try_get_blob(&row, 0), Some(blob));
84 }
85
86 #[test]
87 fn test_empty() {
88 let layout = EncodedValuesLayout::new(&[Type::Blob]);
89 let mut row = layout.allocate();
90
91 let empty_blob = Blob::from_slice(&[]);
92 layout.set_blob(&mut row, 0, &empty_blob);
93 assert_eq!(layout.get_blob(&row, 0), empty_blob);
94 assert_eq!(layout.try_get_blob(&row, 0), Some(empty_blob));
95 }
96
97 #[test]
98 fn test_binary_data() {
99 let layout = EncodedValuesLayout::new(&[Type::Blob]);
100 let mut row = layout.allocate();
101
102 let binary_data = vec![
104 0x00, 0xFF, 0xAA, 0x55, 0xCC, 0x33, 0x00, 0xFF, 0x10, 0x20, 0x30, 0x40, 0x50, 0x60, 0x70, 0x80,
105 ];
106 let blob = Blob::from_slice(&binary_data);
107 layout.set_blob(&mut row, 0, &blob);
108 assert_eq!(layout.get_blob(&row, 0), blob);
109 }
110
111 #[test]
112 fn test_large_data() {
113 let layout = EncodedValuesLayout::new(&[Type::Blob]);
114 let mut row = layout.allocate();
115
116 let large_data: Vec<u8> = (0..1024).map(|i| (i % 256) as u8).collect();
118 let large_blob = Blob::from_slice(&large_data);
119 layout.set_blob(&mut row, 0, &large_blob);
120 assert_eq!(layout.get_blob(&row, 0), large_blob);
121 }
122
123 #[test]
124 fn test_multiple_fields() {
125 let layout = EncodedValuesLayout::new(&[Type::Blob, Type::Blob, Type::Blob]);
126 let mut row = layout.allocate();
127
128 let blob1 = Blob::from_slice(&[1, 2, 3]);
129 let blob2 = Blob::from_slice(&[4, 5, 6, 7, 8]);
130 let blob3 = Blob::from_slice(&[9]);
131
132 layout.set_blob(&mut row, 0, &blob1);
133 layout.set_blob(&mut row, 1, &blob2);
134 layout.set_blob(&mut row, 2, &blob3);
135
136 assert_eq!(layout.get_blob(&row, 0), blob1);
137 assert_eq!(layout.get_blob(&row, 1), blob2);
138 assert_eq!(layout.get_blob(&row, 2), blob3);
139 }
140
141 #[test]
142 fn test_mixed_with_static_fields() {
143 let layout = EncodedValuesLayout::new(&[Type::Boolean, Type::Blob, Type::Int4, Type::Blob]);
144 let mut row = layout.allocate();
145
146 let blob1 = Blob::from_slice(&[0xFF, 0x00, 0xAA]);
147 let blob2 = Blob::from_slice(&[0x11, 0x22, 0x33, 0x44]);
148
149 layout.set_bool(&mut row, 0, true);
150 layout.set_blob(&mut row, 1, &blob1);
151 layout.set_i32(&mut row, 2, -12345);
152 layout.set_blob(&mut row, 3, &blob2);
153
154 assert_eq!(layout.get_bool(&row, 0), true);
155 assert_eq!(layout.get_blob(&row, 1), blob1);
156 assert_eq!(layout.get_i32(&row, 2), -12345);
157 assert_eq!(layout.get_blob(&row, 3), blob2);
158 }
159
160 #[test]
161 fn test_different_sizes() {
162 let layout = EncodedValuesLayout::new(&[Type::Blob, Type::Blob, Type::Blob]);
163 let mut row = layout.allocate();
164
165 let empty_blob = Blob::from_slice(&[]);
166 let medium_blob = Blob::from_slice(&[1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
167 let single_byte_blob = Blob::from_slice(&[42]);
168
169 layout.set_blob(&mut row, 0, &empty_blob);
170 layout.set_blob(&mut row, 1, &medium_blob);
171 layout.set_blob(&mut row, 2, &single_byte_blob);
172
173 assert_eq!(layout.get_blob(&row, 0), empty_blob);
174 assert_eq!(layout.get_blob(&row, 1), medium_blob);
175 assert_eq!(layout.get_blob(&row, 2), single_byte_blob);
176 }
177
178 #[test]
179 fn test_arbitrary_setting_order() {
180 let layout = EncodedValuesLayout::new(&[Type::Blob, Type::Blob, Type::Blob, Type::Blob]);
181 let mut row = layout.allocate();
182
183 let blob0 = Blob::from_slice(&[10, 20]);
184 let blob1 = Blob::from_slice(&[30, 40, 50]);
185 let blob2 = Blob::from_slice(&[60]);
186 let blob3 = Blob::from_slice(&[70, 80, 90, 100]);
187
188 layout.set_blob(&mut row, 3, &blob3);
190 layout.set_blob(&mut row, 1, &blob1);
191 layout.set_blob(&mut row, 0, &blob0);
192 layout.set_blob(&mut row, 2, &blob2);
193
194 assert_eq!(layout.get_blob(&row, 0), blob0);
195 assert_eq!(layout.get_blob(&row, 1), blob1);
196 assert_eq!(layout.get_blob(&row, 2), blob2);
197 assert_eq!(layout.get_blob(&row, 3), blob3);
198 }
199
200 #[test]
201 fn test_undefined_handling() {
202 let layout = EncodedValuesLayout::new(&[Type::Blob, Type::Blob, Type::Blob]);
203 let mut row = layout.allocate();
204
205 let blob = Blob::from_slice(&[1, 2, 3, 4]);
206
207 layout.set_blob(&mut row, 0, &blob);
209 layout.set_blob(&mut row, 2, &blob);
210
211 assert_eq!(layout.try_get_blob(&row, 0), Some(blob.clone()));
212 assert_eq!(layout.try_get_blob(&row, 1), None);
213 assert_eq!(layout.try_get_blob(&row, 2), Some(blob.clone()));
214
215 layout.set_undefined(&mut row, 0);
217 assert_eq!(layout.try_get_blob(&row, 0), None);
218 assert_eq!(layout.try_get_blob(&row, 2), Some(blob));
219 }
220
221 #[test]
222 fn test_all_byte_values() {
223 let layout = EncodedValuesLayout::new(&[Type::Blob]);
224 let mut row = layout.allocate();
225
226 let all_bytes: Vec<u8> = (0..=255).collect();
228 let full_range_blob = Blob::from_slice(&all_bytes);
229 layout.set_blob(&mut row, 0, &full_range_blob);
230 assert_eq!(layout.get_blob(&row, 0), full_range_blob);
231 }
232
233 #[test]
234 fn test_try_get_blob_wrong_type() {
235 let layout = EncodedValuesLayout::new(&[Type::Boolean]);
236 let mut row = layout.allocate();
237
238 layout.set_bool(&mut row, 0, true);
239
240 assert_eq!(layout.try_get_blob(&row, 0), None);
241 }
242}