1use crate::utils::json::{parse_json, JsonValue};
2use std::collections::{BTreeMap, HashMap};
3use std::fmt;
4use std::ops::{Index, IndexMut};
5
6pub type Map<K, V> = BTreeMap<K, V>;
7
8#[derive(Debug, Clone, PartialEq)]
9pub enum Value {
10 Null,
11 Bool(bool),
12 Integer(i64),
13 Number(f64),
14 Decimal(String),
15 String(String),
16 Array(Vec<Value>),
17 Object(Map<String, Value>),
18}
19
20impl fmt::Display for Value {
21 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
22 f.write_str(&self.to_string_compact())
23 }
24}
25
26impl Value {
27 pub fn as_str(&self) -> Option<&str> {
28 match self {
29 Value::String(s) => Some(s.as_str()),
30 _ => None,
31 }
32 }
33
34 pub fn as_f64(&self) -> Option<f64> {
35 match self {
36 Value::Number(n) => Some(*n),
37 Value::Integer(n) => Some(*n as f64),
38 Value::Decimal(n) => n.parse::<f64>().ok(),
39 _ => None,
40 }
41 }
42
43 pub fn as_i64(&self) -> Option<i64> {
44 match self {
45 Value::Integer(n) => Some(*n),
46 Value::Number(n) => Some(*n as i64),
47 Value::Decimal(n) => n.parse::<i64>().ok(),
48 _ => None,
49 }
50 }
51
52 pub fn as_u64(&self) -> Option<u64> {
53 match self {
54 Value::Integer(n) if *n >= 0 => Some(*n as u64),
55 Value::Number(n) if *n >= 0.0 => Some(*n as u64),
56 Value::Decimal(n) => n.parse::<u64>().ok(),
57 _ => None,
58 }
59 }
60
61 pub fn as_bool(&self) -> Option<bool> {
62 match self {
63 Value::Bool(b) => Some(*b),
64 _ => None,
65 }
66 }
67
68 pub fn as_array(&self) -> Option<&[Value]> {
69 match self {
70 Value::Array(values) => Some(values.as_slice()),
71 _ => None,
72 }
73 }
74
75 pub fn as_object(&self) -> Option<&Map<String, Value>> {
76 match self {
77 Value::Object(map) => Some(map),
78 _ => None,
79 }
80 }
81
82 pub fn get(&self, key: &str) -> Option<&Value> {
83 if let Value::Object(map) = self {
84 map.get(key)
85 } else {
86 None
87 }
88 }
89
90 pub fn to_string_compact(&self) -> String {
91 let mut out = String::new();
92 self.write_compact(&mut out);
93 out
94 }
95
96 pub fn to_string_pretty(&self) -> String {
97 let mut out = String::new();
98 self.write_pretty(&mut out, 0);
99 out
100 }
101
102 fn write_compact(&self, out: &mut String) {
103 match self {
104 Value::Null => out.push_str("null"),
105 Value::Bool(b) => out.push_str(if *b { "true" } else { "false" }),
106 Value::Integer(n) => out.push_str(&format!("{n}")),
107 Value::Number(n) => {
108 if n.fract() == 0.0 {
109 out.push_str(&format!("{}", *n as i64));
110 } else {
111 out.push_str(&format!("{}", n));
112 }
113 }
114 Value::Decimal(n) => out.push_str(n),
115 Value::String(s) => {
116 out.push('"');
117 out.push_str(&escape_string(s));
118 out.push('"');
119 }
120 Value::Array(values) => {
121 out.push('[');
122 for (idx, value) in values.iter().enumerate() {
123 if idx > 0 {
124 out.push(',');
125 }
126 value.write_compact(out);
127 }
128 out.push(']');
129 }
130 Value::Object(map) => {
131 out.push('{');
132 for (idx, (key, value)) in map.iter().enumerate() {
133 if idx > 0 {
134 out.push(',');
135 }
136 out.push('"');
137 out.push_str(&escape_string(key));
138 out.push('"');
139 out.push(':');
140 value.write_compact(out);
141 }
142 out.push('}');
143 }
144 }
145 }
146
147 fn write_pretty(&self, out: &mut String, indent: usize) {
148 match self {
149 Value::Null
150 | Value::Bool(_)
151 | Value::Integer(_)
152 | Value::Number(_)
153 | Value::Decimal(_)
154 | Value::String(_) => {
155 out.push_str(&self.to_string_compact());
156 }
157 Value::Array(values) => {
158 out.push('[');
159 if !values.is_empty() {
160 out.push('\n');
161 for (idx, value) in values.iter().enumerate() {
162 if idx > 0 {
163 out.push_str(",\n");
164 }
165 out.push_str(&" ".repeat(indent + 1));
166 value.write_pretty(out, indent + 1);
167 }
168 out.push('\n');
169 out.push_str(&" ".repeat(indent));
170 }
171 out.push(']');
172 }
173 Value::Object(map) => {
174 out.push('{');
175 if !map.is_empty() {
176 out.push('\n');
177 for (idx, (key, value)) in map.iter().enumerate() {
178 if idx > 0 {
179 out.push_str(",\n");
180 }
181 out.push_str(&" ".repeat(indent + 1));
182 out.push('"');
183 out.push_str(&escape_string(key));
184 out.push_str("\": ");
185 value.write_pretty(out, indent + 1);
186 }
187 out.push('\n');
188 out.push_str(&" ".repeat(indent));
189 }
190 out.push('}');
191 }
192 }
193 }
194}
195
196fn escape_string(input: &str) -> String {
197 use std::fmt::Write as _;
202 let mut out = String::with_capacity(input.len());
203 for ch in input.chars() {
204 match ch {
205 '"' => out.push_str("\\\""),
206 '\\' => out.push_str("\\\\"),
207 '\n' => out.push_str("\\n"),
208 '\r' => out.push_str("\\r"),
209 '\t' => out.push_str("\\t"),
210 '\u{08}' => out.push_str("\\b"),
211 '\u{0C}' => out.push_str("\\f"),
212 c if (c as u32) < 0x20 => {
213 let _ = write!(out, "\\u{:04x}", c as u32);
214 }
215 c => out.push(c),
216 }
217 }
218 out
219}
220
221#[cfg(test)]
222mod tests {
223 use super::*;
224 use crate::json;
225 use std::borrow::Cow;
226 use std::collections::HashMap;
227
228 fn encode(s: &str) -> String {
229 Value::String(s.to_string()).to_string_compact()
230 }
231
232 #[test]
235 fn escape_string_handles_every_control_byte() {
236 for byte in 0x00u8..0x20 {
237 let original: String = std::char::from_u32(byte as u32).unwrap().to_string();
238 let encoded = encode(&original);
239 let parsed: String = from_str(&encoded).unwrap_or_else(|err| {
241 panic!("byte 0x{byte:02x} encoded as {encoded:?} failed to parse: {err}")
242 });
243 assert_eq!(
244 parsed, original,
245 "byte 0x{byte:02x} did not round-trip (encoded={encoded:?})"
246 );
247 }
248 }
249
250 #[test]
251 fn escape_string_handles_standard_escapes() {
252 assert_eq!(encode("\""), "\"\\\"\"");
253 assert_eq!(encode("\\"), "\"\\\\\"");
254 assert_eq!(encode("\n"), "\"\\n\"");
255 assert_eq!(encode("\r"), "\"\\r\"");
256 assert_eq!(encode("\t"), "\"\\t\"");
257 assert_eq!(encode("\u{08}"), "\"\\b\"");
258 assert_eq!(encode("\u{0C}"), "\"\\f\"");
259 }
260
261 #[test]
262 fn escape_string_handles_mixed_payload() {
263 let input = "name=\"x\"\n\\path\t\x01end";
264 let encoded = encode(input);
265 let parsed: String = from_str(&encoded).expect("mixed payload must parse");
266 assert_eq!(parsed, input);
267 }
268
269 #[test]
275 fn audit_log_preserves_low_control_bytes() {
276 let payload = "collection\x01name\x07with\x1fbells";
277 let encoded = encode(payload);
278
279 assert!(
282 encoded.contains("\\u0001"),
283 "expected \\u0001 escape in {encoded:?}"
284 );
285 assert!(
286 encoded.contains("\\u0007"),
287 "expected \\u0007 escape in {encoded:?}"
288 );
289 assert!(
290 encoded.contains("\\u001f"),
291 "expected \\u001f escape in {encoded:?}"
292 );
293 assert!(
294 !encoded.contains('\x01'),
295 "raw \\x01 must not appear in encoded output"
296 );
297
298 let parsed: String = from_str(&encoded).expect("audit payload must parse");
300 assert_eq!(parsed, payload);
301 }
302
303 #[test]
304 fn value_accessors_indexing_and_pretty_printing_cover_all_shapes() {
305 let mut object = Map::new();
306 object.insert("null".to_string(), Value::Null);
307 object.insert("bool".to_string(), Value::Bool(true));
308 object.insert("number".to_string(), Value::Number(42.5));
309 object.insert(
310 "decimal".to_string(),
311 Value::Decimal("3.14159265358979323846".to_string()),
312 );
313 object.insert("string".to_string(), Value::String("reddb".to_string()));
314 object.insert(
315 "array".to_string(),
316 Value::Array(vec![Value::Number(1.0), Value::String("two".to_string())]),
317 );
318 let value = Value::Object(object);
319
320 assert_eq!(value.get("string").and_then(Value::as_str), Some("reddb"));
321 assert_eq!(value.get("number").and_then(Value::as_f64), Some(42.5));
322 assert_eq!(value.get("number").and_then(Value::as_i64), Some(42));
323 assert_eq!(value.get("number").and_then(Value::as_u64), Some(42));
324 assert_eq!(value.get("bool").and_then(Value::as_bool), Some(true));
325 assert_eq!(
326 value.get("array").and_then(Value::as_array).map(<[_]>::len),
327 Some(2)
328 );
329 assert_eq!(value.as_object().map(Map::len), Some(6));
330 assert_eq!(
331 value.get("decimal").and_then(Value::as_f64),
332 Some(3.141592653589793)
333 );
334 assert!(Value::Number(-1.0).as_u64().is_none());
335 assert!(Value::Null.as_str().is_none());
336
337 assert_eq!(value["missing"], Value::Null);
338 assert_eq!(value["string"], Value::String("reddb".to_string()));
339 let pretty = value.to_string_pretty();
340 assert!(pretty.contains('\n'));
341 assert!(pretty.contains("\"array\": ["));
342 assert_eq!(Value::Array(Vec::new()).to_string_pretty(), "[]");
343 assert_eq!(Value::Object(Map::new()).to_string_pretty(), "{}");
344 assert_eq!(
345 value.get("decimal").unwrap().to_string_compact(),
346 "3.14159265358979323846"
347 );
348
349 let mut created_from_index = Value::Null;
350 created_from_index["created"] = Value::Bool(true);
351 assert_eq!(created_from_index["created"], Value::Bool(true));
352 }
353
354 #[test]
355 fn json_encode_decode_traits_cover_scalars_collections_and_errors() {
356 assert_eq!(to_value(&true), Value::Bool(true));
357 assert_eq!(to_value(&-7i64), Value::Number(-7.0));
358 assert_eq!(to_value(&-3i32), Value::Number(-3.0));
359 assert_eq!(to_value(&7u8), Value::Number(7.0));
360 assert_eq!(to_value(&8u16), Value::Number(8.0));
361 assert_eq!(to_value(&9u32), Value::Number(9.0));
362 assert_eq!(to_value(&10u64), Value::Number(10.0));
363 assert_eq!(to_value(&11usize), Value::Number(11.0));
364 assert_eq!(to_value(&1.5f64), Value::Number(1.5));
365 assert_eq!(to_value(&2.5f32), Value::Number(2.5));
366 assert_eq!(to_value(&"borrowed"), Value::String("borrowed".to_string()));
367 assert_eq!(
368 to_value(&"owned".to_string()),
369 Value::String("owned".to_string())
370 );
371 let cow: Cow<'_, str> = Cow::Borrowed("cow");
372 assert_eq!(to_value(&cow), Value::String("cow".to_string()));
373 assert_eq!(
374 to_value(&vec![1u8, 2, 3]),
375 Value::Array(vec![
376 Value::Number(1.0),
377 Value::Number(2.0),
378 Value::Number(3.0)
379 ])
380 );
381 assert_eq!(
382 to_value(&[4u8, 5, 6]),
383 Value::Array(vec![
384 Value::Number(4.0),
385 Value::Number(5.0),
386 Value::Number(6.0)
387 ])
388 );
389 assert_eq!(to_value(&Some(12u16)), Value::Number(12.0));
390 assert_eq!(to_value(&Option::<u16>::None), Value::Null);
391
392 let mut hash = HashMap::new();
393 hash.insert("a".to_string(), 1u8);
394 let Value::Object(map) = to_value(&hash) else {
395 panic!("hash map should encode to object");
396 };
397 assert_eq!(map.get("a"), Some(&Value::Number(1.0)));
398
399 assert_eq!(
400 from_value::<String>(Value::String("x".to_string())).unwrap(),
401 "x"
402 );
403 assert!(from_value::<String>(Value::Bool(true)).is_err());
404 assert!(!from_value::<bool>(Value::Bool(false)).unwrap());
405 assert!(from_value::<bool>(Value::String("no".to_string())).is_err());
406 assert_eq!(from_value::<u8>(Value::Number(255.0)).unwrap(), 255);
407 assert_eq!(from_value::<u16>(Value::Number(256.0)).unwrap(), 256);
408 assert_eq!(from_value::<u32>(Value::Number(257.0)).unwrap(), 257);
409 assert_eq!(from_value::<u64>(Value::Number(258.0)).unwrap(), 258);
410 assert_eq!(from_value::<usize>(Value::Number(259.0)).unwrap(), 259);
411 assert_eq!(from_value::<i64>(Value::Number(-260.0)).unwrap(), -260);
412 assert_eq!(from_value::<i32>(Value::Number(-261.0)).unwrap(), -261);
413 assert_eq!(from_value::<f32>(Value::Number(1.25)).unwrap(), 1.25);
414 assert!(from_value::<u8>(Value::String("no".to_string())).is_err());
415 assert!(from_value::<Vec<u8>>(Value::Bool(false)).is_err());
416 assert_eq!(
417 from_value::<Vec<u8>>(Value::Array(vec![Value::Number(1.0), Value::Number(2.0)]))
418 .unwrap(),
419 vec![1, 2]
420 );
421
422 let mut object = Map::new();
423 object.insert("x".to_string(), Value::Number(7.0));
424 let decoded: HashMap<String, u8> = from_value(Value::Object(object)).unwrap();
425 assert_eq!(decoded.get("x"), Some(&7));
426 assert!(from_value::<HashMap<String, u8>>(Value::Null).is_err());
427
428 assert_eq!(from_value::<Option<u8>>(Value::Null).unwrap(), None);
429 assert_eq!(
430 from_value::<Option<u8>>(Value::Number(9.0)).unwrap(),
431 Some(9)
432 );
433 assert_eq!(
434 from_value::<[u8; 3]>(Value::Array(vec![
435 Value::Number(1.0),
436 Value::Number(2.0),
437 Value::Number(3.0),
438 ]))
439 .unwrap(),
440 [1, 2, 3]
441 );
442 assert!(from_value::<[u8; 3]>(Value::Array(vec![Value::Number(1.0)])).is_err());
443 assert!(from_value::<[u8; 3]>(Value::Null).is_err());
444 }
445
446 #[test]
447 fn string_and_byte_entry_points_round_trip_and_reject_bad_inputs() {
448 let bytes = to_vec(&vec![1u8, 2, 3]).unwrap();
449 assert_eq!(from_slice::<Vec<u8>>(&bytes).unwrap(), vec![1, 2, 3]);
450 assert!(from_slice::<Value>(&[0xff]).is_err());
451
452 let compact = to_string(&json!({ "b": true, "n": 2 })).unwrap();
453 assert_eq!(from_str::<Value>(&compact).unwrap()["b"], Value::Bool(true));
454
455 let pretty = to_string_pretty(&json!([1, 2])).unwrap();
456 assert!(pretty.contains('\n'));
457 }
458}
459
460impl From<JsonValue> for Value {
461 fn from(value: JsonValue) -> Self {
462 match value {
463 JsonValue::Null => Value::Null,
464 JsonValue::Bool(b) => Value::Bool(b),
465 JsonValue::Integer(n) => Value::Integer(n),
466 JsonValue::Number(n) => Value::Number(n),
467 JsonValue::Decimal(n) => Value::Decimal(n),
468 JsonValue::String(s) => Value::String(s),
469 JsonValue::Array(values) => Value::Array(values.into_iter().map(Value::from).collect()),
470 JsonValue::Object(entries) => {
471 let mut map = Map::new();
472 for (k, v) in entries {
473 map.insert(k, Value::from(v));
474 }
475 Value::Object(map)
476 }
477 }
478 }
479}
480
481impl Index<&str> for Value {
482 type Output = Value;
483
484 fn index(&self, key: &str) -> &Self::Output {
485 static NULL: Value = Value::Null;
486 match self {
487 Value::Object(map) => map.get(key).unwrap_or(&NULL),
488 _ => &NULL,
489 }
490 }
491}
492
493impl IndexMut<&str> for Value {
494 fn index_mut(&mut self, key: &str) -> &mut Self::Output {
495 match self {
496 Value::Object(map) => map.entry(key.to_string()).or_insert(Value::Null),
497 _ => {
498 *self = Value::Object(Map::new());
499 match self {
500 Value::Object(map) => map.entry(key.to_string()).or_insert(Value::Null),
501 _ => unreachable!(),
502 }
503 }
504 }
505 }
506}
507
508pub trait JsonEncode {
509 fn to_json_value(&self) -> Value;
510}
511
512impl<T: JsonEncode + ?Sized> JsonEncode for &T {
513 fn to_json_value(&self) -> Value {
514 (*self).to_json_value()
515 }
516}
517
518pub trait JsonDecode: Sized {
519 fn from_json_value(value: Value) -> Result<Self, String>;
520}
521
522impl JsonEncode for Value {
523 fn to_json_value(&self) -> Value {
524 self.clone()
525 }
526}
527
528impl JsonDecode for Value {
529 fn from_json_value(value: Value) -> Result<Self, String> {
530 Ok(value)
531 }
532}
533
534impl JsonEncode for bool {
535 fn to_json_value(&self) -> Value {
536 Value::Bool(*self)
537 }
538}
539
540impl JsonEncode for i64 {
541 fn to_json_value(&self) -> Value {
542 Value::Number(*self as f64)
543 }
544}
545
546impl JsonEncode for i32 {
547 fn to_json_value(&self) -> Value {
548 Value::Number(*self as f64)
549 }
550}
551
552impl JsonEncode for u8 {
553 fn to_json_value(&self) -> Value {
554 Value::Number(*self as f64)
555 }
556}
557
558impl JsonEncode for u16 {
559 fn to_json_value(&self) -> Value {
560 Value::Number(*self as f64)
561 }
562}
563
564impl JsonEncode for u32 {
565 fn to_json_value(&self) -> Value {
566 Value::Number(*self as f64)
567 }
568}
569
570impl JsonEncode for u64 {
571 fn to_json_value(&self) -> Value {
572 Value::Number(*self as f64)
573 }
574}
575
576impl JsonEncode for usize {
577 fn to_json_value(&self) -> Value {
578 Value::Number(*self as f64)
579 }
580}
581
582impl JsonEncode for f64 {
583 fn to_json_value(&self) -> Value {
584 Value::Number(*self)
585 }
586}
587
588impl JsonEncode for f32 {
589 fn to_json_value(&self) -> Value {
590 Value::Number(*self as f64)
591 }
592}
593
594impl JsonEncode for String {
595 fn to_json_value(&self) -> Value {
596 Value::String(self.clone())
597 }
598}
599
600impl JsonEncode for &str {
601 fn to_json_value(&self) -> Value {
602 Value::String(self.to_string())
603 }
604}
605
606impl<'a> JsonEncode for std::borrow::Cow<'a, str> {
607 fn to_json_value(&self) -> Value {
608 Value::String(self.to_string())
609 }
610}
611
612impl<T: JsonEncode> JsonEncode for Vec<T> {
613 fn to_json_value(&self) -> Value {
614 Value::Array(self.iter().map(|v| v.to_json_value()).collect())
615 }
616}
617
618impl<T: JsonEncode> JsonEncode for [T] {
619 fn to_json_value(&self) -> Value {
620 Value::Array(self.iter().map(|v| v.to_json_value()).collect())
621 }
622}
623
624impl<T: JsonEncode> JsonEncode for Option<T> {
625 fn to_json_value(&self) -> Value {
626 match self {
627 Some(value) => value.to_json_value(),
628 None => Value::Null,
629 }
630 }
631}
632
633impl<const N: usize> JsonEncode for [u8; N] {
634 fn to_json_value(&self) -> Value {
635 Value::Array(self.iter().map(|b| Value::Number(*b as f64)).collect())
636 }
637}
638
639impl<T: JsonEncode> JsonEncode for HashMap<String, T> {
640 fn to_json_value(&self) -> Value {
641 let mut map = Map::new();
642 for (k, v) in self {
643 map.insert(k.clone(), v.to_json_value());
644 }
645 Value::Object(map)
646 }
647}
648
649impl JsonDecode for String {
650 fn from_json_value(value: Value) -> Result<Self, String> {
651 match value {
652 Value::String(s) => Ok(s),
653 _ => Err("expected string".to_string()),
654 }
655 }
656}
657
658impl JsonDecode for bool {
659 fn from_json_value(value: Value) -> Result<Self, String> {
660 match value {
661 Value::Bool(b) => Ok(b),
662 _ => Err("expected bool".to_string()),
663 }
664 }
665}
666
667impl JsonDecode for u8 {
668 fn from_json_value(value: Value) -> Result<Self, String> {
669 match value {
670 Value::Integer(n) => Ok(n as u8),
671 Value::Number(n) => Ok(n as u8),
672 _ => Err("expected number".to_string()),
673 }
674 }
675}
676
677impl JsonDecode for u16 {
678 fn from_json_value(value: Value) -> Result<Self, String> {
679 match value {
680 Value::Integer(n) => Ok(n as u16),
681 Value::Number(n) => Ok(n as u16),
682 _ => Err("expected number".to_string()),
683 }
684 }
685}
686
687impl JsonDecode for u32 {
688 fn from_json_value(value: Value) -> Result<Self, String> {
689 match value {
690 Value::Integer(n) => Ok(n as u32),
691 Value::Number(n) => Ok(n as u32),
692 _ => Err("expected number".to_string()),
693 }
694 }
695}
696
697impl JsonDecode for u64 {
698 fn from_json_value(value: Value) -> Result<Self, String> {
699 match value {
700 Value::Integer(n) => Ok(n as u64),
701 Value::Number(n) => Ok(n as u64),
702 _ => Err("expected number".to_string()),
703 }
704 }
705}
706
707impl JsonDecode for usize {
708 fn from_json_value(value: Value) -> Result<Self, String> {
709 match value {
710 Value::Integer(n) => Ok(n as usize),
711 Value::Number(n) => Ok(n as usize),
712 _ => Err("expected number".to_string()),
713 }
714 }
715}
716
717impl JsonDecode for i64 {
718 fn from_json_value(value: Value) -> Result<Self, String> {
719 match value {
720 Value::Integer(n) => Ok(n),
721 Value::Number(n) => Ok(n as i64),
722 _ => Err("expected number".to_string()),
723 }
724 }
725}
726
727impl JsonDecode for i32 {
728 fn from_json_value(value: Value) -> Result<Self, String> {
729 match value {
730 Value::Integer(n) => Ok(n as i32),
731 Value::Number(n) => Ok(n as i32),
732 _ => Err("expected number".to_string()),
733 }
734 }
735}
736
737impl JsonDecode for f32 {
738 fn from_json_value(value: Value) -> Result<Self, String> {
739 match value {
740 Value::Integer(n) => Ok(n as f32),
741 Value::Number(n) => Ok(n as f32),
742 _ => Err("expected number".to_string()),
743 }
744 }
745}
746
747impl<T: JsonDecode> JsonDecode for Vec<T> {
748 fn from_json_value(value: Value) -> Result<Self, String> {
749 match value {
750 Value::Array(values) => values.into_iter().map(T::from_json_value).collect(),
751 _ => Err("expected array".to_string()),
752 }
753 }
754}
755
756impl<T: JsonDecode> JsonDecode for HashMap<String, T> {
757 fn from_json_value(value: Value) -> Result<Self, String> {
758 match value {
759 Value::Object(map) => map
760 .into_iter()
761 .map(|(k, v)| Ok((k, T::from_json_value(v)?)))
762 .collect(),
763 _ => Err("expected object".to_string()),
764 }
765 }
766}
767
768impl<T: JsonDecode> JsonDecode for Option<T> {
769 fn from_json_value(value: Value) -> Result<Self, String> {
770 match value {
771 Value::Null => Ok(None),
772 other => Ok(Some(T::from_json_value(other)?)),
773 }
774 }
775}
776
777impl<const N: usize> JsonDecode for [u8; N] {
778 fn from_json_value(value: Value) -> Result<Self, String> {
779 match value {
780 Value::Array(values) => {
781 if values.len() != N {
782 return Err("invalid array length".to_string());
783 }
784 let mut out = [0u8; N];
785 for (idx, val) in values.into_iter().enumerate() {
786 out[idx] = u8::from_json_value(val)?;
787 }
788 Ok(out)
789 }
790 _ => Err("expected array".to_string()),
791 }
792 }
793}
794
795pub fn to_value<T: JsonEncode + ?Sized>(value: &T) -> Value {
796 value.to_json_value()
797}
798
799pub fn to_string<T: JsonEncode + ?Sized>(value: &T) -> Result<String, String> {
800 Ok(to_value(value).to_string_compact())
801}
802
803pub fn to_string_pretty<T: JsonEncode + ?Sized>(value: &T) -> Result<String, String> {
804 Ok(to_value(value).to_string_pretty())
805}
806
807pub fn to_vec<T: JsonEncode + ?Sized>(value: &T) -> Result<Vec<u8>, String> {
808 Ok(to_string(value)?.into_bytes())
809}
810
811pub fn from_str<T: JsonDecode>(input: &str) -> Result<T, String> {
812 let value = parse_json(input).map(Value::from)?;
813 T::from_json_value(value)
814}
815
816pub fn from_slice<T: JsonDecode>(input: &[u8]) -> Result<T, String> {
817 let s = std::str::from_utf8(input).map_err(|e| e.to_string())?;
818 from_str(s)
819}
820
821pub fn from_value<T: JsonDecode>(value: Value) -> Result<T, String> {
822 T::from_json_value(value)
823}
824
825#[macro_export]
826macro_rules! json {
827 (null) => {
828 $crate::serde_json::Value::Null
829 };
830 ([ $( $elem:expr ),* $(,)? ]) => {
831 $crate::serde_json::Value::Array(vec![ $( $crate::json!($elem) ),* ])
832 };
833 ({}) => {
834 $crate::serde_json::Value::Object($crate::serde_json::Map::new())
835 };
836 ({ $( $key:literal : $value:expr ),* $(,)? }) => {{
837 let mut map = $crate::serde_json::Map::new();
838 $( map.insert($key.to_string(), $crate::json!($value)); )*
839 $crate::serde_json::Value::Object(map)
840 }};
841 ($other:expr) => {
842 $crate::serde_json::to_value(&$other)
843 };
844}
845
846pub use crate::json;
847
848#[cfg(test)]
849mod json_macro_tests {
850 use super::Value;
851 use crate::json;
852
853 #[test]
854 fn object_macro_supports_empty_and_non_empty_objects() {
855 assert_eq!(json!({}), Value::Object(Default::default()));
856
857 let value = json!({ "name": "reddb", "ok": true });
858 let Value::Object(map) = value else {
859 panic!("non-empty object macro should produce an object");
860 };
861 assert_eq!(map.get("name"), Some(&Value::String("reddb".to_string())));
862 assert_eq!(map.get("ok"), Some(&Value::Bool(true)));
863 }
864}