1use std::fmt::Display;
2
3use serde_json::{Map, Number};
4
5use crate::{Instant, Timestamp, Uuid, Value};
6
7#[derive(Clone, Copy)]
9pub enum Shown<'a> {
10 Null,
11 Bool(bool),
12 Integer(i64),
13 Float(f64),
14 Number(&'a Number),
15 Text(&'a str),
16 Uuid(Uuid),
18 Instant(Instant),
20 Formatted(&'a dyn Display),
21 List(&'a dyn Items),
22 Record(&'a dyn Fields),
23}
24
25pub trait Show {
26 fn show(&self) -> Shown<'_>;
27}
28
29pub trait Items {
30 fn item(&self, index: usize) -> Option<Shown<'_>>;
31}
32
33pub trait Fields {
35 fn name(&self, index: usize) -> Option<&str>;
36
37 fn get(&self, name: &str) -> Option<Shown<'_>>;
38
39 fn names(&self) -> Box<dyn Iterator<Item = &str> + '_> {
41 Box::new((0..).map_while(|index| self.name(index)))
42 }
43}
44
45impl<V: Value> Show for V
46where
47 V::Inner: Show,
48{
49 fn show(&self) -> Shown<'_> {
50 self.inner().show()
51 }
52}
53
54impl Show for serde_json::Value {
55 fn show(&self) -> Shown<'_> {
56 match self {
57 Self::Null => Shown::Null,
58 Self::Bool(flag) => Shown::Bool(*flag),
59 Self::Number(number) => Shown::Number(number),
60 Self::String(text) => Shown::Text(text),
61 Self::Array(items) => Shown::List(items),
62 Self::Object(fields) => Shown::Record(fields),
63 }
64 }
65}
66
67impl Fields for Map<String, serde_json::Value> {
68 fn name(&self, index: usize) -> Option<&str> {
69 self.keys().nth(index).map(String::as_str)
70 }
71
72 fn get(&self, name: &str) -> Option<Shown<'_>> {
73 self.get(name).map(Show::show)
74 }
75
76 fn names(&self) -> Box<dyn Iterator<Item = &str> + '_> {
77 Box::new(self.keys().map(String::as_str))
78 }
79}
80
81impl<T: Show> Items for Vec<T> {
82 fn item(&self, index: usize) -> Option<Shown<'_>> {
83 self.get(index).map(Show::show)
84 }
85}
86
87impl<T: Show> Show for Vec<T> {
88 fn show(&self) -> Shown<'_> {
89 Shown::List(self)
90 }
91}
92
93impl<T: Show> Show for Option<T> {
94 fn show(&self) -> Shown<'_> {
95 self.as_ref().map_or(Shown::Null, Show::show)
96 }
97}
98
99macro_rules! show {
100 ($($type:ty => |$value:ident| $shown:expr),* $(,)?) => {
101 $(impl Show for $type { fn show(&self) -> Shown<'_> { let $value = self; $shown } })*
102 };
103}
104
105show! {
106 bool => |flag| Shown::Bool(*flag), String => |text| Shown::Text(text),
107 i64 => |number| Shown::Integer(*number), i32 => |number| Shown::Integer(i64::from(*number)),
108 u64 => |number| i64::try_from(*number).map_or(Shown::Formatted(number), Shown::Integer),
109 f64 => |number| Shown::Float(*number), Uuid => |uuid| Shown::Uuid(*uuid),
110 Timestamp => |timestamp| Shown::Instant(Instant::from(*timestamp)), jiff::civil::Date => |day| Shown::Formatted(day),
111}