1#[cfg(reifydb_assertions)]
5use reifydb_value::value::value_type::ValueType;
6use reifydb_value::{reifydb_assertions, value::Value};
7
8use crate::{
9 encoded::{row::EncodedRow, shape::RowShape},
10 value::{decode_value, encode_value},
11};
12
13impl RowShape {
14 pub fn set_any(&self, row: &mut EncodedRow, index: usize, value: &Value) {
15 reifydb_assertions! {
16 assert!(
17 row.len() >= self.total_static_size(),
18 "row/shape size mismatch: row.len()={} < total_static_size()={}",
19 row.len(),
20 self.total_static_size()
21 );
22 assert_eq!(*self.fields()[index].constraint.get_type().inner_type(), ValueType::Any);
23 }
24 let encoded = encode_value(value).expect("unsupported value in any row field");
25 self.replace_dynamic_data(row, index, &encoded);
26 }
27
28 pub fn get_any(&self, row: &EncodedRow, index: usize) -> Value {
29 let field = &self.fields()[index];
30 reifydb_assertions! {
31 assert!(
32 row.len() >= self.total_static_size(),
33 "row/shape size mismatch: row.len()={} < total_static_size()={}",
34 row.len(),
35 self.total_static_size()
36 );
37 assert_eq!(*field.constraint.get_type().inner_type(), ValueType::Any);
38 }
39
40 let ref_slice = &row.as_slice()[field.offset as usize..field.offset as usize + 8];
41 let offset = u32::from_le_bytes([ref_slice[0], ref_slice[1], ref_slice[2], ref_slice[3]]) as usize;
42 let length = u32::from_le_bytes([ref_slice[4], ref_slice[5], ref_slice[6], ref_slice[7]]) as usize;
43
44 let dynamic_start = self.dynamic_section_start();
45 let data_start = dynamic_start + offset;
46 let data_slice = &row.as_slice()[data_start..data_start + length];
47
48 decode_value(data_slice).expect("corrupt any row field bytes")
49 }
50}
51
52#[cfg(test)]
53pub mod tests {
54 use crate::value::{decode_value as decode_value_codec, encode_value as encode_value_codec};
55
56 pub fn encode_value(value: &Value) -> Vec<u8> {
57 encode_value_codec(value).unwrap()
58 }
59
60 pub fn decode_value(bytes: &[u8]) -> Value {
61 decode_value_codec(bytes).unwrap()
62 }
63
64 use std::f64::consts::E;
65
66 use reifydb_runtime::context::{
67 clock::{Clock, MockClock},
68 rng::Rng,
69 };
70 use reifydb_value::value::{
71 Value,
72 blob::Blob,
73 date::Date,
74 datetime::DateTime,
75 ordered_f32::OrderedF32,
76 ordered_f64::OrderedF64,
77 time::Time,
78 uuid::{Uuid4, Uuid7},
79 value_type::ValueType,
80 };
81
82 use crate::encoded::shape::RowShape;
83
84 fn test_clock_and_rng() -> (MockClock, Clock, Rng) {
85 let mock = MockClock::from_millis(1000);
86 let clock = Clock::Mock(mock.clone());
87 let rng = Rng::seeded(42);
88 (mock, clock, rng)
89 }
90
91 #[test]
92 fn test_any_boolean() {
93 let shape = RowShape::testing(&[ValueType::Any]);
94 let mut row = shape.allocate();
95 shape.set_any(&mut row, 0, &Value::Boolean(true));
96 assert_eq!(shape.get_any(&row, 0), Value::Boolean(true));
97 }
98
99 #[test]
100 fn test_any_integers() {
101 let shape = RowShape::testing(&[ValueType::Any]);
102
103 let cases: &[Value] = &[
104 Value::Int1(-42),
105 Value::Int2(-1000),
106 Value::Int4(-100000),
107 Value::Int8(i64::MIN),
108 Value::Int16(i128::MAX),
109 Value::Uint1(255),
110 Value::Uint2(65535),
111 Value::Uint4(u32::MAX),
112 Value::Uint8(u64::MAX),
113 Value::Uint16(u128::MAX),
114 ];
115
116 for case in cases {
117 let mut row = shape.allocate();
118 shape.set_any(&mut row, 0, case);
119 assert_eq!(&shape.get_any(&row, 0), case);
120 }
121 }
122
123 #[test]
124 fn test_any_floats() {
125 let shape = RowShape::testing(&[ValueType::Any]);
126
127 let f4 = Value::Float4(OrderedF32::try_from(3.14f32).unwrap());
128 let mut row = shape.allocate();
129 shape.set_any(&mut row, 0, &f4);
130 assert_eq!(shape.get_any(&row, 0), f4);
131
132 let f8 = Value::Float8(OrderedF64::try_from(E).unwrap());
133 let mut row2 = shape.allocate();
134 shape.set_any(&mut row2, 0, &f8);
135 assert_eq!(shape.get_any(&row2, 0), f8);
136 }
137
138 #[test]
139 fn test_any_temporal() {
140 let shape = RowShape::testing(&[ValueType::Any]);
141
142 let date = Value::Date(Date::new(2025, 7, 4).unwrap());
143 let mut row = shape.allocate();
144 shape.set_any(&mut row, 0, &date);
145 assert_eq!(shape.get_any(&row, 0), date);
146
147 let dt = Value::DateTime(DateTime::new(2025, 1, 1, 12, 0, 0, 0).unwrap());
148 let mut row2 = shape.allocate();
149 shape.set_any(&mut row2, 0, &dt);
150 assert_eq!(shape.get_any(&row2, 0), dt);
151
152 let t = Value::Time(Time::new(14, 30, 45, 123456789).unwrap());
153 let mut row3 = shape.allocate();
154 shape.set_any(&mut row3, 0, &t);
155 assert_eq!(shape.get_any(&row3, 0), t);
156
157 let dur = Value::duration_seconds(3600);
158 let mut row4 = shape.allocate();
159 shape.set_any(&mut row4, 0, &dur);
160 assert_eq!(shape.get_any(&row4, 0), dur);
161 }
162
163 #[test]
164 fn test_any_uuid() {
165 let (_, clock, rng) = test_clock_and_rng();
166 let shape = RowShape::testing(&[ValueType::Any]);
167
168 let u4 = Value::Uuid4(Uuid4::generate());
169 let mut row = shape.allocate();
170 shape.set_any(&mut row, 0, &u4);
171 assert_eq!(shape.get_any(&row, 0), u4);
172
173 let u7 = Value::Uuid7(Uuid7::generate(&clock, &rng));
174 let mut row2 = shape.allocate();
175 shape.set_any(&mut row2, 0, &u7);
176 assert_eq!(shape.get_any(&row2, 0), u7);
177 }
178
179 #[test]
180 fn test_any_utf8() {
181 let shape = RowShape::testing(&[ValueType::Any]);
182 let v = Value::Utf8("hello, world!".to_string());
183 let mut row = shape.allocate();
184 shape.set_any(&mut row, 0, &v);
185 assert_eq!(shape.get_any(&row, 0), v);
186 }
187
188 #[test]
189 fn test_any_blob() {
190 let shape = RowShape::testing(&[ValueType::Any]);
191 let v = Value::Blob(Blob::from_slice(&[0xDE, 0xAD, 0xBE, 0xEF]));
192 let mut row = shape.allocate();
193 shape.set_any(&mut row, 0, &v);
194 assert_eq!(shape.get_any(&row, 0), v);
195 }
196
197 #[test]
198 fn test_any_none_via_set_value() {
199 let shape = RowShape::testing(&[ValueType::Any]);
200 let mut row = shape.allocate();
201 shape.set_value(&mut row, 0, &Value::none());
202 assert!(!row.is_defined(0));
203 assert_eq!(shape.get_value(&row, 0), Value::none());
204 }
205
206 #[test]
207 fn test_any_roundtrip_via_set_get_value() {
208 let shape = RowShape::testing(&[ValueType::Any]);
209
210 let cases: &[Value] = &[
211 Value::Boolean(false),
212 Value::Int4(42),
213 Value::Utf8("test".to_string()),
214 Value::Uint8(1234567890),
215 ];
216
217 for inner in cases {
218 let wrapped = Value::any(inner.clone());
219 let mut row = shape.allocate();
220 shape.set_value(&mut row, 0, &wrapped);
221 let retrieved = shape.get_value(&row, 0);
222 assert_eq!(retrieved, wrapped, "roundtrip failed for {:?}", inner);
223 }
224 }
225
226 #[test]
227 fn test_any_multiple_fields() {
228 let shape = RowShape::testing(&[ValueType::Any, ValueType::Int4, ValueType::Any]);
229 let mut row = shape.allocate();
230
231 shape.set_any(&mut row, 0, &Value::Utf8("first".to_string()));
232 shape.set_i32(&mut row, 1, 99);
233 shape.set_any(&mut row, 2, &Value::Boolean(true));
234
235 assert_eq!(shape.get_any(&row, 0), Value::Utf8("first".to_string()));
236 assert_eq!(shape.get_i32(&row, 1), 99);
237 assert_eq!(shape.get_any(&row, 2), Value::Boolean(true));
238 }
239
240 #[test]
241 fn test_update_any() {
242 let shape = RowShape::testing(&[ValueType::Any]);
243 let mut row = shape.allocate();
244
245 shape.set_any(&mut row, 0, &Value::Int4(42));
246 assert_eq!(shape.get_any(&row, 0), Value::Int4(42));
247
248 shape.set_any(&mut row, 0, &Value::Utf8("hello".to_string()));
250 assert_eq!(shape.get_any(&row, 0), Value::Utf8("hello".to_string()));
251
252 shape.set_any(&mut row, 0, &Value::Boolean(true));
254 assert_eq!(shape.get_any(&row, 0), Value::Boolean(true));
255 }
256
257 #[test]
258 fn test_update_any_with_other_dynamic_fields() {
259 let shape = RowShape::testing(&[ValueType::Any, ValueType::Utf8, ValueType::Any]);
260 let mut row = shape.allocate();
261
262 shape.set_any(&mut row, 0, &Value::Int4(1));
263 shape.set_utf8(&mut row, 1, "middle");
264 shape.set_any(&mut row, 2, &Value::Boolean(false));
265
266 shape.set_any(&mut row, 0, &Value::Utf8("a long string value".to_string()));
268
269 assert_eq!(shape.get_any(&row, 0), Value::Utf8("a long string value".to_string()));
270 assert_eq!(shape.get_utf8(&row, 1), "middle");
271 assert_eq!(shape.get_any(&row, 2), Value::Boolean(false));
272 }
273
274 #[test]
280 fn test_encode_decode_none_various_inner_types() {
281 let cases: &[ValueType] = &[
285 ValueType::Boolean,
286 ValueType::Int4,
287 ValueType::Uint8,
288 ValueType::Utf8,
289 ValueType::Blob,
290 ValueType::Date,
291 ValueType::DateTime,
292 ValueType::Time,
293 ValueType::Duration,
294 ValueType::Uuid4,
295 ];
296
297 for ty in cases {
298 let encoded = encode_value(&Value::none_of(ty.clone()));
299 match decode_value(&encoded) {
300 Value::None {
301 inner,
302 } => assert_eq!(&inner, ty, "inner type lost for {ty}"),
303 other => panic!("expected Value::None for {ty}, got {other:?}"),
304 }
305 }
306 }
307
308 #[test]
309 fn test_encode_decode_none_nested_option_duration() {
310 let inner_ty = ValueType::Option(Box::new(ValueType::Duration));
313
314 let encoded = encode_value(&Value::none_of(inner_ty.clone()));
315 match decode_value(&encoded) {
316 Value::None {
317 inner,
318 } => assert_eq!(inner, inner_ty),
319 other => panic!("expected Value::None, got {other:?}"),
320 }
321 }
322
323 #[test]
324 fn test_encode_decode_none_triple_nested_option() {
325 let inner_ty = ValueType::Option(Box::new(ValueType::Option(Box::new(ValueType::Option(Box::new(
328 ValueType::Duration,
329 ))))));
330
331 let encoded = encode_value(&Value::none_of(inner_ty.clone()));
332 match decode_value(&encoded) {
333 Value::None {
334 inner,
335 } => assert_eq!(inner, inner_ty),
336 other => panic!("expected Value::None, got {other:?}"),
337 }
338 }
339
340 #[test]
341 fn test_any_set_get_none_duration() {
342 let shape = RowShape::testing(&[ValueType::Any]);
343 let mut row = shape.allocate();
344
345 shape.set_any(&mut row, 0, &Value::none_of(ValueType::Duration));
346
347 assert!(
348 row.is_defined(0),
349 "an Any field holding a None-of-Duration is a stored value, not an unset field"
350 );
351 match shape.get_any(&row, 0) {
352 Value::None {
353 inner,
354 } => assert_eq!(inner, ValueType::Duration),
355 other => panic!("expected Value::None, got {other:?}"),
356 }
357 }
358
359 #[test]
360 fn test_any_set_get_none_nested_option_duration() {
361 let shape = RowShape::testing(&[ValueType::Any]);
362 let mut row = shape.allocate();
363
364 let inner_ty = ValueType::Option(Box::new(ValueType::Duration));
365 shape.set_any(&mut row, 0, &Value::none_of(inner_ty.clone()));
366
367 match shape.get_any(&row, 0) {
368 Value::None {
369 inner,
370 } => assert_eq!(inner, inner_ty),
371 other => panic!("expected Value::None, got {other:?}"),
372 }
373 }
374}