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