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