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