dare/
display.rs

1use crate::Value;
2
3use std::{
4    any::TypeId,
5    collections::HashMap,
6    fmt::{self, Display, Formatter},
7    sync::OnceLock,
8};
9
10pub trait ValueFormatter: Send + Sync {
11    fn format(&self, value: &dyn std::any::Any, f: &mut Formatter) -> fmt::Result;
12}
13
14pub struct FormatterRegistry {
15    formatters: HashMap<TypeId, Box<dyn ValueFormatter>>,
16}
17
18impl FormatterRegistry {
19    fn new() -> Self { Self { formatters: HashMap::new() } }
20
21    fn register<T: 'static>(&mut self, formatter: Box<dyn ValueFormatter>) { self.formatters.insert(TypeId::of::<T>(), formatter); }
22
23    pub fn get(&self, type_id: TypeId) -> Option<&dyn ValueFormatter> { self.formatters.get(&type_id).map(|boxed| boxed.as_ref()) }
24}
25
26pub static FORMATTER_REGISTRY: OnceLock<FormatterRegistry> = OnceLock::new();
27
28pub fn init_registry() -> FormatterRegistry {
29    let mut registry = FormatterRegistry::new();
30
31    registry.register::<()>(Box::new(NullFormatter));
32    registry.register::<bool>(Box::new(SimpleFormatter));
33    registry.register::<usize>(Box::new(SimpleFormatter));
34    registry.register::<f64>(Box::new(SimpleFormatter));
35    registry.register::<String>(Box::new(StringFormatter));
36    registry.register::<&'static str>(Box::new(StringFormatter));
37    registry.register::<Vec<Value>>(Box::new(SequenceFormatter::new("[", "]")));
38    registry.register::<&'static [Value]>(Box::new(SequenceFormatter::new("[", "]")));
39    registry.register::<HashMap<String, Value>>(Box::new(MapFormatter));
40
41    registry
42}
43
44struct NullFormatter;
45impl ValueFormatter for NullFormatter {
46    fn format(&self, _: &dyn std::any::Any, f: &mut Formatter) -> fmt::Result { f.write_str("null") }
47}
48
49struct SimpleFormatter;
50impl ValueFormatter for SimpleFormatter {
51    fn format(&self, value: &dyn std::any::Any, f: &mut Formatter) -> fmt::Result {
52        if let Some(v) = value.downcast_ref::<bool>() {
53            v.fmt(f)
54        } else if let Some(v) = value.downcast_ref::<usize>() {
55            v.fmt(f)
56        } else if let Some(v) = value.downcast_ref::<f64>() {
57            v.fmt(f)
58        } else {
59            Err(fmt::Error)
60        }
61    }
62}
63
64struct StringFormatter;
65impl ValueFormatter for StringFormatter {
66    fn format(&self, value: &dyn std::any::Any, f: &mut Formatter) -> fmt::Result {
67        if let Some(s) = value.downcast_ref::<String>() {
68            write!(f, "{s}")
69        } else if let Some(s) = value.downcast_ref::<&'static str>() {
70            write!(f, "{s}")
71        } else {
72            Err(fmt::Error)
73        }
74    }
75}
76
77struct SequenceFormatter {
78    start: &'static str,
79    end: &'static str,
80}
81
82impl SequenceFormatter {
83    fn new(start: &'static str, end: &'static str) -> Self { Self { start, end } }
84}
85
86impl ValueFormatter for SequenceFormatter {
87    fn format(&self, value: &dyn std::any::Any, f: &mut Formatter) -> fmt::Result {
88        f.write_str(self.start)?;
89        let mut first = true;
90
91        if let Some(vec) = value.downcast_ref::<Vec<Value>>() {
92            for item in vec.iter() {
93                if !first {
94                    f.write_str(", ")?;
95                }
96                item.fmt(f)?;
97                first = false;
98            }
99        } else if let Some(slice) = value.downcast_ref::<&'static [Value]>() {
100            for item in *slice {
101                if !first {
102                    f.write_str(", ")?;
103                }
104                item.fmt(f)?;
105                first = false;
106            }
107        } else {
108            return Err(fmt::Error);
109        }
110
111        f.write_str(self.end)
112    }
113}
114
115struct MapFormatter;
116impl ValueFormatter for MapFormatter {
117    fn format(&self, value: &dyn std::any::Any, f: &mut Formatter) -> fmt::Result {
118        if let Some(map) = value.downcast_ref::<HashMap<String, Value>>() {
119            f.write_str("{")?;
120            let mut first = true;
121            for (key, value) in map {
122                if !first {
123                    f.write_str(", ")?;
124                }
125                write!(f, "\"{}\": {}", key, value)?;
126                first = false;
127            }
128            f.write_str("}")
129        } else {
130            Err(fmt::Error)
131        }
132    }
133}