1use std::str;
5
6use reifydb_type::value::{
7 Value,
8 blob::Blob,
9 date::Date,
10 datetime::DateTime,
11 duration::Duration,
12 identity::IdentityId,
13 ordered_f32::OrderedF32,
14 ordered_f64::OrderedF64,
15 time::Time,
16 r#type::Type,
17 uuid::{Uuid4, Uuid7},
18};
19use uuid::Uuid;
20
21use crate::encoded::{row::EncodedRow, shape::RowShape};
22
23pub fn encode_value(value: &Value) -> Vec<u8> {
27 match value {
28 Value::Boolean(v) => vec![Type::Boolean.to_u8(), *v as u8],
29
30 Value::Uint1(v) => vec![Type::Uint1.to_u8(), *v],
31 Value::Uint2(v) => {
32 let mut b = vec![Type::Uint2.to_u8()];
33 b.extend_from_slice(&v.to_le_bytes());
34 b
35 }
36 Value::Uint4(v) => {
37 let mut b = vec![Type::Uint4.to_u8()];
38 b.extend_from_slice(&v.to_le_bytes());
39 b
40 }
41 Value::Uint8(v) => {
42 let mut b = vec![Type::Uint8.to_u8()];
43 b.extend_from_slice(&v.to_le_bytes());
44 b
45 }
46 Value::Uint16(v) => {
47 let mut b = vec![Type::Uint16.to_u8()];
48 b.extend_from_slice(&v.to_le_bytes());
49 b
50 }
51
52 Value::Int1(v) => vec![Type::Int1.to_u8(), *v as u8],
53 Value::Int2(v) => {
54 let mut b = vec![Type::Int2.to_u8()];
55 b.extend_from_slice(&v.to_le_bytes());
56 b
57 }
58 Value::Int4(v) => {
59 let mut b = vec![Type::Int4.to_u8()];
60 b.extend_from_slice(&v.to_le_bytes());
61 b
62 }
63 Value::Int8(v) => {
64 let mut b = vec![Type::Int8.to_u8()];
65 b.extend_from_slice(&v.to_le_bytes());
66 b
67 }
68 Value::Int16(v) => {
69 let mut b = vec![Type::Int16.to_u8()];
70 b.extend_from_slice(&v.to_le_bytes());
71 b
72 }
73
74 Value::Float4(v) => {
75 let mut b = vec![Type::Float4.to_u8()];
76 b.extend_from_slice(&v.value().to_bits().to_le_bytes());
77 b
78 }
79 Value::Float8(v) => {
80 let mut b = vec![Type::Float8.to_u8()];
81 b.extend_from_slice(&v.value().to_bits().to_le_bytes());
82 b
83 }
84
85 Value::Date(v) => {
86 let mut b = vec![Type::Date.to_u8()];
87 b.extend_from_slice(&v.to_days_since_epoch().to_le_bytes());
88 b
89 }
90 Value::DateTime(v) => {
91 let mut b = vec![Type::DateTime.to_u8()];
92 b.extend_from_slice(&v.to_nanos().to_le_bytes());
93 b
94 }
95 Value::Time(v) => {
96 let mut b = vec![Type::Time.to_u8()];
97 b.extend_from_slice(&v.to_nanos_since_midnight().to_le_bytes());
98 b
99 }
100 Value::Duration(v) => {
101 let mut b = vec![Type::Duration.to_u8()];
102 b.extend_from_slice(&v.get_months().to_le_bytes());
103 b.extend_from_slice(&v.get_days().to_le_bytes());
104 b.extend_from_slice(&v.get_nanos().to_le_bytes());
105 b
106 }
107
108 Value::Uuid4(v) => {
109 let mut b = vec![Type::Uuid4.to_u8()];
110 b.extend_from_slice(v.as_bytes());
111 b
112 }
113 Value::Uuid7(v) => {
114 let mut b = vec![Type::Uuid7.to_u8()];
115 b.extend_from_slice(v.as_bytes());
116 b
117 }
118 Value::IdentityId(v) => {
119 let mut b = vec![Type::IdentityId.to_u8()];
120 b.extend_from_slice(v.as_bytes());
121 b
122 }
123
124 Value::Utf8(v) => {
125 let s = v.as_bytes();
126 let mut b = vec![Type::Utf8.to_u8()];
127 b.extend_from_slice(&(s.len() as u32).to_le_bytes());
128 b.extend_from_slice(s);
129 b
130 }
131 Value::Blob(v) => {
132 let s = v.as_bytes();
133 let mut b = vec![Type::Blob.to_u8()];
134 b.extend_from_slice(&(s.len() as u32).to_le_bytes());
135 b.extend_from_slice(s);
136 b
137 }
138
139 Value::Int(_)
140 | Value::Uint(_)
141 | Value::Decimal(_)
142 | Value::DictionaryId(_)
143 | Value::Any(_)
144 | Value::None {
145 ..
146 }
147 | Value::Type(_)
148 | Value::List(_)
149 | Value::Record(_)
150 | Value::Tuple(_) => unreachable!("unsupported value type in Any encoding: {:?}", value),
151 }
152}
153
154pub fn decode_value(bytes: &[u8]) -> Value {
156 let type_byte = bytes[0];
157 let p = &bytes[1..];
158 let ty = Type::from_u8(type_byte);
159
160 match ty {
161 Type::Boolean => Value::Boolean(p[0] != 0),
162
163 Type::Uint1 => Value::Uint1(p[0]),
164 Type::Uint2 => Value::Uint2(u16::from_le_bytes([p[0], p[1]])),
165 Type::Uint4 => Value::Uint4(u32::from_le_bytes([p[0], p[1], p[2], p[3]])),
166 Type::Uint8 => Value::Uint8(u64::from_le_bytes(p[..8].try_into().unwrap())),
167 Type::Uint16 => Value::Uint16(u128::from_le_bytes(p[..16].try_into().unwrap())),
168
169 Type::Int1 => Value::Int1(p[0] as i8),
170 Type::Int2 => Value::Int2(i16::from_le_bytes([p[0], p[1]])),
171 Type::Int4 => Value::Int4(i32::from_le_bytes([p[0], p[1], p[2], p[3]])),
172 Type::Int8 => Value::Int8(i64::from_le_bytes(p[..8].try_into().unwrap())),
173 Type::Int16 => Value::Int16(i128::from_le_bytes(p[..16].try_into().unwrap())),
174
175 Type::Float4 => {
176 let bits = u32::from_le_bytes([p[0], p[1], p[2], p[3]]);
177 Value::Float4(OrderedF32::try_from(f32::from_bits(bits)).unwrap())
178 }
179 Type::Float8 => {
180 let bits = u64::from_le_bytes(p[..8].try_into().unwrap());
181 Value::Float8(OrderedF64::try_from(f64::from_bits(bits)).unwrap())
182 }
183
184 Type::Date => {
185 let days = i32::from_le_bytes([p[0], p[1], p[2], p[3]]);
186 Value::Date(Date::from_days_since_epoch(days).unwrap())
187 }
188 Type::DateTime => {
189 let nanos = u64::from_le_bytes(p[..8].try_into().unwrap());
190 Value::DateTime(DateTime::from_nanos(nanos))
191 }
192 Type::Time => {
193 let nanos = u64::from_le_bytes(p[..8].try_into().unwrap());
194 Value::Time(Time::from_nanos_since_midnight(nanos).unwrap())
195 }
196 Type::Duration => {
197 let months = i32::from_le_bytes([p[0], p[1], p[2], p[3]]);
198 let days = i32::from_le_bytes([p[4], p[5], p[6], p[7]]);
199 let nanos = i64::from_le_bytes(p[8..16].try_into().unwrap());
200 Value::Duration(Duration::new(months, days, nanos).unwrap())
201 }
202
203 Type::Uuid4 => {
204 let b: [u8; 16] = p[..16].try_into().unwrap();
205 Value::Uuid4(Uuid4::from(Uuid::from_bytes(b)))
206 }
207 Type::Uuid7 => {
208 let b: [u8; 16] = p[..16].try_into().unwrap();
209 Value::Uuid7(Uuid7::from(Uuid::from_bytes(b)))
210 }
211 Type::IdentityId => {
212 let b: [u8; 16] = p[..16].try_into().unwrap();
213 Value::IdentityId(IdentityId::from(Uuid7::from(Uuid::from_bytes(b))))
214 }
215
216 Type::Utf8 => {
217 let len = u32::from_le_bytes([p[0], p[1], p[2], p[3]]) as usize;
218 let s = str::from_utf8(&p[4..4 + len]).unwrap();
219 Value::Utf8(s.to_string())
220 }
221 Type::Blob => {
222 let len = u32::from_le_bytes([p[0], p[1], p[2], p[3]]) as usize;
223 Value::Blob(Blob::from_slice(&p[4..4 + len]))
224 }
225
226 _ => unreachable!("unsupported type byte {} in Any decoding", type_byte),
227 }
228}
229
230impl RowShape {
231 pub fn set_any(&self, row: &mut EncodedRow, index: usize, value: &Value) {
232 debug_assert_eq!(*self.fields()[index].constraint.get_type().inner_type(), Type::Any);
233 let encoded = encode_value(value);
234 self.replace_dynamic_data(row, index, &encoded);
235 }
236
237 pub fn get_any(&self, row: &EncodedRow, index: usize) -> Value {
238 let field = &self.fields()[index];
239 debug_assert_eq!(*field.constraint.get_type().inner_type(), Type::Any);
240
241 let ref_slice = &row.as_slice()[field.offset as usize..field.offset as usize + 8];
242 let offset = u32::from_le_bytes([ref_slice[0], ref_slice[1], ref_slice[2], ref_slice[3]]) as usize;
243 let length = u32::from_le_bytes([ref_slice[4], ref_slice[5], ref_slice[6], ref_slice[7]]) as usize;
244
245 let dynamic_start = self.dynamic_section_start();
246 let data_start = dynamic_start + offset;
247 let data_slice = &row.as_slice()[data_start..data_start + length];
248
249 decode_value(data_slice)
250 }
251}
252
253#[cfg(test)]
254pub mod tests {
255 use std::f64::consts::E;
256
257 use reifydb_runtime::context::{
258 clock::{Clock, MockClock},
259 rng::Rng,
260 };
261 use reifydb_type::value::{
262 Value,
263 blob::Blob,
264 date::Date,
265 datetime::DateTime,
266 duration::Duration,
267 ordered_f32::OrderedF32,
268 ordered_f64::OrderedF64,
269 time::Time,
270 r#type::Type,
271 uuid::{Uuid4, Uuid7},
272 };
273
274 use crate::encoded::shape::RowShape;
275
276 fn test_clock_and_rng() -> (MockClock, Clock, Rng) {
277 let mock = MockClock::from_millis(1000);
278 let clock = Clock::Mock(mock.clone());
279 let rng = Rng::seeded(42);
280 (mock, clock, rng)
281 }
282
283 #[test]
284 fn test_any_boolean() {
285 let shape = RowShape::testing(&[Type::Any]);
286 let mut row = shape.allocate();
287 shape.set_any(&mut row, 0, &Value::Boolean(true));
288 assert_eq!(shape.get_any(&row, 0), Value::Boolean(true));
289 }
290
291 #[test]
292 fn test_any_integers() {
293 let shape = RowShape::testing(&[Type::Any]);
294
295 let cases: &[Value] = &[
296 Value::Int1(-42),
297 Value::Int2(-1000),
298 Value::Int4(-100000),
299 Value::Int8(i64::MIN),
300 Value::Int16(i128::MAX),
301 Value::Uint1(255),
302 Value::Uint2(65535),
303 Value::Uint4(u32::MAX),
304 Value::Uint8(u64::MAX),
305 Value::Uint16(u128::MAX),
306 ];
307
308 for case in cases {
309 let mut row = shape.allocate();
310 shape.set_any(&mut row, 0, case);
311 assert_eq!(&shape.get_any(&row, 0), case);
312 }
313 }
314
315 #[test]
316 fn test_any_floats() {
317 let shape = RowShape::testing(&[Type::Any]);
318
319 let f4 = Value::Float4(OrderedF32::try_from(3.14f32).unwrap());
320 let mut row = shape.allocate();
321 shape.set_any(&mut row, 0, &f4);
322 assert_eq!(shape.get_any(&row, 0), f4);
323
324 let f8 = Value::Float8(OrderedF64::try_from(E).unwrap());
325 let mut row2 = shape.allocate();
326 shape.set_any(&mut row2, 0, &f8);
327 assert_eq!(shape.get_any(&row2, 0), f8);
328 }
329
330 #[test]
331 fn test_any_temporal() {
332 let shape = RowShape::testing(&[Type::Any]);
333
334 let date = Value::Date(Date::new(2025, 7, 4).unwrap());
335 let mut row = shape.allocate();
336 shape.set_any(&mut row, 0, &date);
337 assert_eq!(shape.get_any(&row, 0), date);
338
339 let dt = Value::DateTime(DateTime::new(2025, 1, 1, 12, 0, 0, 0).unwrap());
340 let mut row2 = shape.allocate();
341 shape.set_any(&mut row2, 0, &dt);
342 assert_eq!(shape.get_any(&row2, 0), dt);
343
344 let t = Value::Time(Time::new(14, 30, 45, 123456789).unwrap());
345 let mut row3 = shape.allocate();
346 shape.set_any(&mut row3, 0, &t);
347 assert_eq!(shape.get_any(&row3, 0), t);
348
349 let dur = Value::Duration(Duration::from_seconds(3600).unwrap());
350 let mut row4 = shape.allocate();
351 shape.set_any(&mut row4, 0, &dur);
352 assert_eq!(shape.get_any(&row4, 0), dur);
353 }
354
355 #[test]
356 fn test_any_uuid() {
357 let (_, clock, rng) = test_clock_and_rng();
358 let shape = RowShape::testing(&[Type::Any]);
359
360 let u4 = Value::Uuid4(Uuid4::generate());
361 let mut row = shape.allocate();
362 shape.set_any(&mut row, 0, &u4);
363 assert_eq!(shape.get_any(&row, 0), u4);
364
365 let u7 = Value::Uuid7(Uuid7::generate(&clock, &rng));
366 let mut row2 = shape.allocate();
367 shape.set_any(&mut row2, 0, &u7);
368 assert_eq!(shape.get_any(&row2, 0), u7);
369 }
370
371 #[test]
372 fn test_any_utf8() {
373 let shape = RowShape::testing(&[Type::Any]);
374 let v = Value::Utf8("hello, world!".to_string());
375 let mut row = shape.allocate();
376 shape.set_any(&mut row, 0, &v);
377 assert_eq!(shape.get_any(&row, 0), v);
378 }
379
380 #[test]
381 fn test_any_blob() {
382 let shape = RowShape::testing(&[Type::Any]);
383 let v = Value::Blob(Blob::from_slice(&[0xDE, 0xAD, 0xBE, 0xEF]));
384 let mut row = shape.allocate();
385 shape.set_any(&mut row, 0, &v);
386 assert_eq!(shape.get_any(&row, 0), v);
387 }
388
389 #[test]
390 fn test_any_none_via_set_value() {
391 let shape = RowShape::testing(&[Type::Any]);
392 let mut row = shape.allocate();
393 shape.set_value(&mut row, 0, &Value::none());
394 assert!(!row.is_defined(0));
395 assert_eq!(shape.get_value(&row, 0), Value::none());
396 }
397
398 #[test]
399 fn test_any_roundtrip_via_set_get_value() {
400 let shape = RowShape::testing(&[Type::Any]);
401
402 let cases: &[Value] = &[
403 Value::Boolean(false),
404 Value::Int4(42),
405 Value::Utf8("test".to_string()),
406 Value::Uint8(1234567890),
407 ];
408
409 for inner in cases {
410 let wrapped = Value::any(inner.clone());
411 let mut row = shape.allocate();
412 shape.set_value(&mut row, 0, &wrapped);
413 let retrieved = shape.get_value(&row, 0);
414 assert_eq!(retrieved, wrapped, "roundtrip failed for {:?}", inner);
415 }
416 }
417
418 #[test]
419 fn test_any_multiple_fields() {
420 let shape = RowShape::testing(&[Type::Any, Type::Int4, Type::Any]);
421 let mut row = shape.allocate();
422
423 shape.set_any(&mut row, 0, &Value::Utf8("first".to_string()));
424 shape.set_i32(&mut row, 1, 99);
425 shape.set_any(&mut row, 2, &Value::Boolean(true));
426
427 assert_eq!(shape.get_any(&row, 0), Value::Utf8("first".to_string()));
428 assert_eq!(shape.get_i32(&row, 1), 99);
429 assert_eq!(shape.get_any(&row, 2), Value::Boolean(true));
430 }
431
432 #[test]
433 fn test_update_any() {
434 let shape = RowShape::testing(&[Type::Any]);
435 let mut row = shape.allocate();
436
437 shape.set_any(&mut row, 0, &Value::Int4(42));
438 assert_eq!(shape.get_any(&row, 0), Value::Int4(42));
439
440 shape.set_any(&mut row, 0, &Value::Utf8("hello".to_string()));
442 assert_eq!(shape.get_any(&row, 0), Value::Utf8("hello".to_string()));
443
444 shape.set_any(&mut row, 0, &Value::Boolean(true));
446 assert_eq!(shape.get_any(&row, 0), Value::Boolean(true));
447 }
448
449 #[test]
450 fn test_update_any_with_other_dynamic_fields() {
451 let shape = RowShape::testing(&[Type::Any, Type::Utf8, Type::Any]);
452 let mut row = shape.allocate();
453
454 shape.set_any(&mut row, 0, &Value::Int4(1));
455 shape.set_utf8(&mut row, 1, "middle");
456 shape.set_any(&mut row, 2, &Value::Boolean(false));
457
458 shape.set_any(&mut row, 0, &Value::Utf8("a long string value".to_string()));
460
461 assert_eq!(shape.get_any(&row, 0), Value::Utf8("a long string value".to_string()));
462 assert_eq!(shape.get_utf8(&row, 1), "middle");
463 assert_eq!(shape.get_any(&row, 2), Value::Boolean(false));
464 }
465}