1use serde::{Deserialize, Deserializer, Serialize, Serializer};
4
5#[derive(Debug, Clone, PartialEq)]
13pub enum Value {
14 Null,
16 Bool(bool),
18 I32(i32),
20 I64(i64),
22 F64(f64),
24 Decimal(rust_decimal::Decimal),
26 DateTime(chrono::NaiveDateTime),
28 Uuid(uuid::Uuid),
30 Json(serde_json::Value),
32 String(String),
34 Bytes(Vec<u8>),
36 Array(Vec<Value>),
38 Array2D(Vec<Vec<Value>>),
40 Enum {
47 value: String,
49 type_name: String,
51 },
52}
53
54impl From<bool> for Value {
55 fn from(v: bool) -> Self {
56 Value::Bool(v)
57 }
58}
59
60impl From<i32> for Value {
61 fn from(v: i32) -> Self {
62 Value::I32(v)
63 }
64}
65
66impl From<i64> for Value {
67 fn from(v: i64) -> Self {
68 Value::I64(v)
69 }
70}
71
72impl From<f64> for Value {
73 fn from(v: f64) -> Self {
74 Value::F64(v)
75 }
76}
77
78impl From<rust_decimal::Decimal> for Value {
79 fn from(v: rust_decimal::Decimal) -> Self {
80 Value::Decimal(v)
81 }
82}
83
84impl From<chrono::NaiveDateTime> for Value {
85 fn from(v: chrono::NaiveDateTime) -> Self {
86 Value::DateTime(v)
87 }
88}
89
90impl From<uuid::Uuid> for Value {
91 fn from(v: uuid::Uuid) -> Self {
92 Value::Uuid(v)
93 }
94}
95
96impl From<serde_json::Value> for Value {
97 fn from(v: serde_json::Value) -> Self {
98 Value::Json(v)
99 }
100}
101
102impl From<String> for Value {
103 fn from(v: String) -> Self {
104 Value::String(v)
105 }
106}
107
108impl From<&str> for Value {
109 fn from(v: &str) -> Self {
110 Value::String(v.to_string())
111 }
112}
113
114impl From<Vec<u8>> for Value {
115 fn from(v: Vec<u8>) -> Self {
116 Value::Bytes(v)
117 }
118}
119
120macro_rules! impl_vec_from {
124 ($($t:ty),* $(,)?) => {
125 $(
126 impl From<Vec<$t>> for Value {
127 fn from(v: Vec<$t>) -> Self {
128 Value::Array(v.into_iter().map(|x| x.into()).collect())
129 }
130 }
131
132 impl From<Vec<Vec<$t>>> for Value {
133 fn from(v: Vec<Vec<$t>>) -> Self {
134 Value::Array2D(
135 v.into_iter()
136 .map(|row| row.into_iter().map(|x| x.into()).collect())
137 .collect(),
138 )
139 }
140 }
141 )*
142 };
143}
144
145impl_vec_from!(
146 i32,
147 i64,
148 f64,
149 bool,
150 String,
151 rust_decimal::Decimal,
152 uuid::Uuid,
153 chrono::NaiveDateTime,
154 serde_json::Value,
155);
156
157macro_rules! impl_option_from {
161 ($($t:ty),* $(,)?) => {
162 $(
163 impl From<Option<$t>> for Value {
164 fn from(v: Option<$t>) -> Self {
165 v.map(|x| x.into()).unwrap_or(Value::Null)
166 }
167 }
168 )*
169 };
170}
171
172impl_option_from!(
173 bool,
174 i32,
175 i64,
176 f64,
177 String,
178 rust_decimal::Decimal,
179 uuid::Uuid,
180 chrono::NaiveDateTime,
181);
182
183impl From<Option<&str>> for Value {
184 fn from(v: Option<&str>) -> Self {
185 v.map(|s| Value::String(s.to_string()))
186 .unwrap_or(Value::Null)
187 }
188}
189
190impl Serialize for Value {
192 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
193 where
194 S: Serializer,
195 {
196 match self {
197 Value::Null => serializer.serialize_none(),
198 Value::Bool(b) => serializer.serialize_bool(*b),
199 Value::I32(i) => serializer.serialize_i32(*i),
200 Value::I64(i) => serializer.serialize_i64(*i),
201 Value::F64(f) => serializer.serialize_f64(*f),
202 Value::Decimal(d) => serializer.serialize_str(&d.to_string()),
203 Value::DateTime(dt) => {
204 serializer.serialize_str(&dt.format("%Y-%m-%dT%H:%M:%S%.fZ").to_string())
206 }
207 Value::Uuid(u) => serializer.serialize_str(&u.to_string()),
208 Value::Bytes(b) => {
209 use base64::Engine;
211 serializer.serialize_str(&base64::engine::general_purpose::STANDARD.encode(b))
212 }
213 Value::Json(j) => j.serialize(serializer),
214 Value::String(s) => serializer.serialize_str(s),
215 Value::Array(arr) => {
216 use serde::ser::SerializeSeq;
217 let mut seq = serializer.serialize_seq(Some(arr.len()))?;
218 for item in arr {
219 seq.serialize_element(item)?;
220 }
221 seq.end()
222 }
223 Value::Array2D(arr2d) => {
224 use serde::ser::SerializeSeq;
225 let mut seq = serializer.serialize_seq(Some(arr2d.len()))?;
226 for row in arr2d {
227 let row_values: Vec<_> = row.iter().collect();
228 seq.serialize_element(&row_values)?;
229 }
230 seq.end()
231 }
232 Value::Enum { value, .. } => serializer.serialize_str(value),
233 }
234 }
235}
236
237impl<'de> Deserialize<'de> for Value {
247 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
248 where
249 D: Deserializer<'de>,
250 {
251 let json: serde_json::Value = Deserialize::deserialize(deserializer)?;
253 Ok(json_to_value_ref(&json))
254 }
255}
256
257pub(crate) fn json_to_value_ref(json: &serde_json::Value) -> Value {
268 match json {
269 serde_json::Value::Null => Value::Null,
270 serde_json::Value::Bool(b) => Value::Bool(*b),
271 serde_json::Value::Number(n) => {
272 if let Some(i) = n.as_i64() {
273 if i >= i32::MIN as i64 && i <= i32::MAX as i64 {
275 Value::I32(i as i32)
276 } else {
277 Value::I64(i)
278 }
279 } else if let Some(f) = n.as_f64() {
280 Value::F64(f)
281 } else {
282 Value::String(n.to_string())
283 }
284 }
285 serde_json::Value::String(s) => Value::String(s.clone()),
286 serde_json::Value::Array(arr) => Value::Array(arr.iter().map(json_to_value_ref).collect()),
287 serde_json::Value::Object(_) => Value::Json(json.clone()),
288 }
289}
290
291#[cfg(test)]
292mod tests {
293 use core::f64;
294
295 use super::*;
296
297 #[test]
298 fn test_value_variants() {
299 assert_eq!(Value::Null, Value::Null);
300 assert_eq!(Value::Bool(true), Value::from(true));
301 assert_eq!(Value::I32(42), Value::from(42i32));
302 assert_eq!(Value::I64(42), Value::from(42i64));
303 assert_eq!(Value::F64(2.5), Value::from(2.5f64));
304 assert_eq!(Value::String("hello".to_string()), Value::from("hello"));
305 assert_eq!(Value::Bytes(vec![1, 2, 3]), Value::from(vec![1u8, 2, 3]));
306
307 use rust_decimal::Decimal;
309 let dec = Decimal::new(12345, 2); assert_eq!(Value::Decimal(dec), Value::from(dec));
311
312 use chrono::NaiveDate;
313 let dt = NaiveDate::from_ymd_opt(2024, 1, 1)
314 .unwrap()
315 .and_hms_opt(12, 0, 0)
316 .unwrap();
317 assert_eq!(Value::DateTime(dt), Value::from(dt));
318
319 use uuid::Uuid;
320 let id = Uuid::nil();
321 assert_eq!(Value::Uuid(id), Value::from(id));
322
323 use serde_json::json;
324 let j = json!({"key": "value"});
325 assert_eq!(Value::Json(j.clone()), Value::from(j));
326 }
327
328 #[test]
329 fn test_value_serialization_null() {
330 let value = Value::Null;
331 let json = serde_json::to_value(&value).unwrap();
332 assert_eq!(json, serde_json::Value::Null);
333
334 let deserialized: Value = serde_json::from_value(json).unwrap();
335 assert_eq!(deserialized, Value::Null);
336 }
337
338 #[test]
339 fn test_value_serialization_bool() {
340 let value = Value::Bool(true);
341 let json = serde_json::to_value(&value).unwrap();
342 assert_eq!(json, serde_json::Value::Bool(true));
343
344 let deserialized: Value = serde_json::from_value(json).unwrap();
345 assert_eq!(deserialized, Value::Bool(true));
346 }
347
348 #[test]
349 fn test_value_serialization_numbers() {
350 let value = Value::I32(42);
352 let json = serde_json::to_value(&value).unwrap();
353 assert_eq!(json.as_i64(), Some(42));
354
355 let value = Value::I64(9007199254740991);
357 let json = serde_json::to_value(&value).unwrap();
358 assert_eq!(json.as_i64(), Some(9007199254740991));
359
360 let value = Value::F64(f64::consts::PI);
362 let json = serde_json::to_value(&value).unwrap();
363 assert_eq!(json.as_f64(), Some(f64::consts::PI));
364 }
365
366 #[test]
367 fn test_value_serialization_string() {
368 let value = Value::String("hello world".to_string());
369 let json = serde_json::to_value(&value).unwrap();
370 assert_eq!(json.as_str(), Some("hello world"));
371
372 let deserialized: Value = serde_json::from_value(json).unwrap();
373 assert_eq!(deserialized, Value::String("hello world".to_string()));
374 }
375
376 #[test]
377 fn test_value_serialization_decimal() {
378 use rust_decimal::Decimal;
379 let dec = Decimal::new(12345, 2); let value = Value::Decimal(dec);
381
382 let json = serde_json::to_value(&value).unwrap();
383 assert_eq!(json.as_str(), Some("123.45"));
384 }
385
386 #[test]
387 fn test_value_serialization_datetime() {
388 use chrono::NaiveDate;
389 let dt = NaiveDate::from_ymd_opt(2026, 2, 18)
390 .unwrap()
391 .and_hms_opt(10, 30, 45)
392 .unwrap();
393 let value = Value::DateTime(dt);
394
395 let json = serde_json::to_value(&value).unwrap();
396 let s = json.as_str().unwrap();
397 assert!(s.starts_with("2026-02-18T10:30:45"));
398 }
399
400 #[test]
401 fn test_value_serialization_uuid() {
402 use uuid::Uuid;
403 let id = Uuid::parse_str("550e8400-e29b-41d4-a716-446655440000").unwrap();
404 let value = Value::Uuid(id);
405
406 let json = serde_json::to_value(&value).unwrap();
407 assert_eq!(json.as_str(), Some("550e8400-e29b-41d4-a716-446655440000"));
408 }
409
410 #[test]
411 fn test_value_serialization_bytes() {
412 let value = Value::Bytes(vec![72, 101, 108, 108, 111]); let json = serde_json::to_value(&value).unwrap();
415 assert_eq!(json.as_str(), Some("SGVsbG8="));
417 }
418
419 #[test]
420 fn test_value_serialization_json() {
421 use serde_json::json;
422 let j = json!({"name": "Alice", "age": 30});
423 let value = Value::Json(j.clone());
424
425 let serialized = serde_json::to_value(&value).unwrap();
426 assert_eq!(serialized, j);
427
428 let deserialized: Value = serde_json::from_value(serialized).unwrap();
429 assert_eq!(deserialized, Value::Json(j));
430 }
431
432 #[test]
433 fn test_value_serialization_array() {
434 let value = Value::Array(vec![
435 Value::String("a".to_string()),
436 Value::String("b".to_string()),
437 Value::String("c".to_string()),
438 ]);
439
440 let json = serde_json::to_value(&value).unwrap();
441 assert_eq!(json[0].as_str(), Some("a"));
442 assert_eq!(json[1].as_str(), Some("b"));
443 assert_eq!(json[2].as_str(), Some("c"));
444
445 let deserialized: Value = serde_json::from_value(json).unwrap();
446 assert_eq!(deserialized, value);
447 }
448
449 #[test]
450 fn test_value_serialization_array2d() {
451 let value = Value::Array2D(vec![
452 vec![Value::I32(1), Value::I32(2)],
453 vec![Value::I32(3), Value::I32(4)],
454 ]);
455
456 let json = serde_json::to_value(&value).unwrap();
459 assert_eq!(json[0][0].as_i64(), Some(1));
460 assert_eq!(json[0][1].as_i64(), Some(2));
461 assert_eq!(json[1][0].as_i64(), Some(3));
462 assert_eq!(json[1][1].as_i64(), Some(4));
463
464 let expected = Value::Array(vec![
469 Value::Array(vec![Value::I32(1), Value::I32(2)]),
470 Value::Array(vec![Value::I32(3), Value::I32(4)]),
471 ]);
472 let deserialized: Value = serde_json::from_value(json).unwrap();
473 assert_eq!(deserialized, expected);
474 }
475
476 #[test]
477 fn test_value_round_trip() {
478 let values = vec![
479 Value::Null,
480 Value::Bool(false),
481 Value::I32(-42),
482 Value::I64(9007199254740991), Value::F64(f64::consts::E),
484 Value::String("test".to_string()),
485 Value::Array(vec![Value::I32(1), Value::I32(2)]),
486 ];
487
488 for value in values {
489 let json = serde_json::to_value(&value).unwrap();
490 let deserialized: Value = serde_json::from_value(json).unwrap();
491 assert_eq!(deserialized, value);
492 }
493 }
494}