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