haystack_core/kinds/
kind.rs1use super::*;
2use chrono::{NaiveDate, NaiveTime};
3use std::fmt;
4
5#[derive(Debug, Clone, PartialEq)]
7pub enum Kind {
8 Null,
9 Marker,
10 NA,
11 Remove,
12 Bool(bool),
13 Number(Number),
14 Str(String),
15 Ref(HRef),
16 Uri(Uri),
17 Symbol(Symbol),
18 Date(NaiveDate),
19 Time(NaiveTime),
20 DateTime(HDateTime),
21 Coord(Coord),
22 XStr(XStr),
23 List(Vec<Kind>),
24 Dict(Box<crate::data::HDict>),
25 Grid(Box<crate::data::HGrid>),
26}
27
28impl fmt::Display for Kind {
29 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
30 match self {
31 Kind::Null => write!(f, "null"),
32 Kind::Marker => write!(f, "{}", super::singletons::Marker),
33 Kind::NA => write!(f, "{}", super::singletons::NA),
34 Kind::Remove => write!(f, "{}", super::singletons::Remove),
35 Kind::Bool(v) => write!(f, "{v}"),
36 Kind::Number(n) => write!(f, "{n}"),
37 Kind::Str(s) => write!(f, "{s}"),
38 Kind::Ref(r) => write!(f, "{r}"),
39 Kind::Uri(u) => write!(f, "{u}"),
40 Kind::Symbol(s) => write!(f, "{s}"),
41 Kind::Date(d) => write!(f, "{d}"),
42 Kind::Time(t) => write!(f, "{}", t.format("%H:%M:%S")),
43 Kind::DateTime(dt) => write!(f, "{dt}"),
44 Kind::Coord(c) => write!(f, "{c}"),
45 Kind::XStr(x) => write!(f, "{x}"),
46 Kind::List(items) => {
47 write!(f, "[")?;
48 for (i, item) in items.iter().enumerate() {
49 if i > 0 {
50 write!(f, ", ")?;
51 }
52 write!(f, "{item}")?;
53 }
54 write!(f, "]")
55 }
56 Kind::Dict(d) => write!(f, "{d}"),
57 Kind::Grid(g) => write!(f, "{g}"),
58 }
59 }
60}
61
62impl From<bool> for Kind {
64 fn from(v: bool) -> Self {
65 Kind::Bool(v)
66 }
67}
68
69impl From<Number> for Kind {
70 fn from(n: Number) -> Self {
71 Kind::Number(n)
72 }
73}
74
75impl From<HRef> for Kind {
76 fn from(r: HRef) -> Self {
77 Kind::Ref(r)
78 }
79}
80
81impl From<String> for Kind {
82 fn from(s: String) -> Self {
83 Kind::Str(s)
84 }
85}
86
87impl From<&str> for Kind {
88 fn from(s: &str) -> Self {
89 Kind::Str(s.to_string())
90 }
91}
92
93impl From<Uri> for Kind {
94 fn from(u: Uri) -> Self {
95 Kind::Uri(u)
96 }
97}
98
99impl From<Symbol> for Kind {
100 fn from(s: Symbol) -> Self {
101 Kind::Symbol(s)
102 }
103}
104
105impl From<Coord> for Kind {
106 fn from(c: Coord) -> Self {
107 Kind::Coord(c)
108 }
109}
110
111impl From<XStr> for Kind {
112 fn from(x: XStr) -> Self {
113 Kind::XStr(x)
114 }
115}
116
117impl From<NaiveDate> for Kind {
118 fn from(d: NaiveDate) -> Self {
119 Kind::Date(d)
120 }
121}
122
123impl From<NaiveTime> for Kind {
124 fn from(t: NaiveTime) -> Self {
125 Kind::Time(t)
126 }
127}
128
129impl From<HDateTime> for Kind {
130 fn from(dt: HDateTime) -> Self {
131 Kind::DateTime(dt)
132 }
133}
134
135#[cfg(test)]
136mod tests {
137 use super::*;
138
139 #[test]
140 fn kind_null() {
141 assert_eq!(Kind::Null.to_string(), "null");
142 }
143
144 #[test]
145 fn kind_marker() {
146 assert_eq!(Kind::Marker.to_string(), "\u{2713}");
147 }
148
149 #[test]
150 fn kind_bool() {
151 assert_eq!(Kind::Bool(true).to_string(), "true");
152 assert_eq!(Kind::Bool(false).to_string(), "false");
153 }
154
155 #[test]
156 fn kind_number() {
157 let k = Kind::Number(Number::new(72.5, Some("°F".into())));
158 assert_eq!(k.to_string(), "72.5°F");
159 }
160
161 #[test]
162 fn kind_str() {
163 let k = Kind::Str("hello".into());
164 assert_eq!(k.to_string(), "hello");
165 }
166
167 #[test]
168 fn kind_ref() {
169 let k = Kind::Ref(HRef::from_val("site-1"));
170 assert_eq!(k.to_string(), "@site-1");
171 }
172
173 #[test]
174 fn kind_list() {
175 let k = Kind::List(vec![
176 Kind::Number(Number::unitless(1.0)),
177 Kind::Str("two".into()),
178 ]);
179 assert_eq!(k.to_string(), "[1, two]");
180 }
181
182 #[test]
183 fn kind_equality() {
184 assert_eq!(Kind::Marker, Kind::Marker);
185 assert_ne!(Kind::Marker, Kind::NA);
186 assert_eq!(
187 Kind::Number(Number::unitless(42.0)),
188 Kind::Number(Number::unitless(42.0))
189 );
190 }
191
192 #[test]
193 fn kind_from_conversions() {
194 let _: Kind = true.into();
195 let _: Kind = Number::unitless(1.0).into();
196 let _: Kind = HRef::from_val("x").into();
197 let _: Kind = "hello".into();
198 let _: Kind = String::from("hello").into();
199 }
200}