libhaystack/haystack/encoding/json/
encode.rs1use chrono::SecondsFormat;
8use std::borrow::Cow;
9
10use crate::{
11 haystack::val::{
12 Column, Coord, Date, DateTime, Dict, Grid, Marker, Na, Number, Ref, Remove, Symbol, Time,
13 Uri, Value as HVal, XStr,
14 },
15 val::HaystackDict,
16};
17
18use serde::ser::{Serialize, SerializeMap, SerializeSeq, Serializer};
19
20impl Serialize for Column {
22 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
23 let mut map = serializer.serialize_map(Some(if self.meta.is_none() { 1 } else { 2 }))?;
24 map.serialize_entry("name", &self.name)?;
25 if self.meta.is_some() {
26 map.serialize_entry("meta", &self.meta)?;
27 }
28 map.end()
29 }
30}
31
32impl Serialize for Marker {
33 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
34 let mut map = serializer.serialize_map(Some(1))?;
35 map.serialize_entry("_kind", "marker")?;
36 map.end()
37 }
38}
39
40impl Serialize for Na {
41 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
42 let mut map = serializer.serialize_map(Some(1))?;
43 map.serialize_entry("_kind", "na")?;
44 map.end()
45 }
46}
47
48impl Serialize for Remove {
49 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
50 let mut map = serializer.serialize_map(Some(1))?;
51 map.serialize_entry("_kind", "remove")?;
52 map.end()
53 }
54}
55
56impl Serialize for Ref {
57 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
58 let mut map = serializer.serialize_map(Some(if self.dis.is_none() { 2 } else { 3 }))?;
59 map.serialize_entry("_kind", "ref")?;
60 map.serialize_entry("val", &self.value)?;
61 if self.dis.is_some() {
62 let dis = self.dis.clone();
63 map.serialize_entry("dis", &dis)?;
64 }
65 map.end()
66 }
67}
68
69impl Serialize for Uri {
70 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
71 let mut map = serializer.serialize_map(Some(2))?;
72 map.serialize_entry("_kind", "uri")?;
73 map.serialize_entry("val", &self.value)?;
74 map.end()
75 }
76}
77
78impl Serialize for Symbol {
79 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
80 let mut map = serializer.serialize_map(Some(2))?;
81 map.serialize_entry("_kind", "symbol")?;
82 map.serialize_entry("val", &self.value)?;
83 map.end()
84 }
85}
86
87impl Serialize for Number {
88 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
89 if let Some(unit) = self.unit {
90 let mut map = serializer.serialize_map(Some(3))?;
91 map.serialize_entry("_kind", "number")?;
92 map.serialize_entry("val", &self.value)?;
93 map.serialize_entry("unit", unit.symbol())?;
94 map.end()
95 } else if self.value.fract() == 0.0 {
96 serializer.serialize_i64(self.value as i64)
97 } else {
98 serializer.serialize_f64(self.value)
99 }
100 }
101}
102
103impl Serialize for Date {
104 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
105 let mut map = serializer.serialize_map(Some(2))?;
106 map.serialize_entry("_kind", "date")?;
107 map.serialize_entry("val", &self.to_string())?;
108 map.end()
109 }
110}
111
112impl Serialize for Time {
113 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
114 let mut map = serializer.serialize_map(Some(2))?;
115 map.serialize_entry("_kind", "time")?;
116 map.serialize_entry("val", &self.to_string())?;
117 map.end()
118 }
119}
120
121impl Serialize for DateTime {
122 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
123 let mut map = serializer.serialize_map(Some(2))?;
124 map.serialize_entry("_kind", "dateTime")?;
125 map.serialize_entry("val", &self.to_rfc3339_opts(SecondsFormat::AutoSi, true))?;
126 if !self.is_utc() {
127 map.serialize_entry("tz", &self.timezone_short_name())?;
128 }
129 map.end()
130 }
131}
132
133impl Serialize for Coord {
134 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
135 let mut map = serializer.serialize_map(Some(3))?;
136 map.serialize_entry("_kind", "coord")?;
137 map.serialize_entry("lat", &self.lat)?;
138 map.serialize_entry("lng", &self.long)?;
139 map.end()
140 }
141}
142
143impl Serialize for XStr {
144 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
145 let mut map = serializer.serialize_map(Some(3))?;
146 map.serialize_entry("_kind", "xstr")?;
147 map.serialize_entry("type", &self.r#type)?;
148 map.serialize_entry("val", &self.value)?;
149 map.end()
150 }
151}
152
153impl Serialize for Dict {
154 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
155 let mut map = serializer.serialize_map(Some(self.len()))?;
156 for (k, v) in self.iter() {
157 map.serialize_entry(k, v)?;
158 }
159 map.end()
160 }
161}
162
163impl Serialize for Grid {
164 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
165 let mut map = serializer.serialize_map(Some(4))?;
166 map.serialize_entry("_kind", "grid")?;
167
168 let meta = ensure_meta_has_ver(self.meta.as_ref());
169 map.serialize_entry("meta", meta.as_ref())?;
170
171 map.serialize_entry("cols", &self.columns)?;
172 map.serialize_entry("rows", &self.rows)?;
173 map.end()
174 }
175}
176
177fn ensure_meta_has_ver<'a>(meta: Option<&'a Dict>) -> Cow<'a, Dict> {
178 match meta {
179 Some(meta) if meta.has("ver") => Cow::Borrowed(meta),
180 Some(meta) => {
181 let mut with_ver = meta.clone();
182 with_ver.insert("ver".into(), "3.0".into());
183 Cow::Owned(with_ver)
184 }
185 None => {
186 let mut meta = Dict::new();
187 meta.insert("ver".into(), "3.0".into());
188 Cow::Owned(meta)
189 }
190 }
191}
192
193impl Serialize for HVal {
197 fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
198 match self {
199 HVal::Null => serializer.serialize_none(),
200
201 HVal::Remove => Remove::serialize(&Remove, serializer),
202
203 HVal::Marker => Marker::serialize(&Marker, serializer),
204
205 HVal::Bool(value) => serializer.serialize_bool(value.value),
206
207 HVal::Na => Na::serialize(&Na, serializer),
208
209 HVal::Number(val) => Number::serialize(val, serializer),
210
211 HVal::Str(val) => serializer.serialize_str(val.value.as_str()),
212
213 HVal::Ref(val) => Ref::serialize(val, serializer),
214
215 HVal::Symbol(val) => Symbol::serialize(val, serializer),
216
217 HVal::Uri(val) => Uri::serialize(val, serializer),
218
219 HVal::Date(val) => Date::serialize(val, serializer),
220
221 HVal::Time(val) => Time::serialize(val, serializer),
222
223 HVal::DateTime(val) => DateTime::serialize(val, serializer),
224
225 HVal::Coord(val) => Coord::serialize(val, serializer),
226
227 HVal::XStr(val) => XStr::serialize(val, serializer),
228
229 HVal::List(val) => {
230 let mut seq = serializer.serialize_seq(Some(val.len()))?;
231 for el in val {
232 seq.serialize_element(el)?;
233 }
234 seq.end()
235 }
236
237 HVal::Dict(val) => Dict::serialize(val, serializer),
238
239 HVal::Grid(val) => Grid::serialize(val, serializer),
240 }
241 }
242}
243
244#[cfg(test)]
245mod tests {
246 use super::*;
247
248 #[test]
249 fn ensure_meta_has_ver_when_ver_exists() {
250 let mut meta = Dict::new();
251 meta.insert("ver".into(), "3.0".into());
252 meta.insert("site".into(), "alpha".into());
253
254 let result = ensure_meta_has_ver(Some(&meta));
255
256 assert!(result.has("ver"));
257 assert!(result.has("site"));
258 }
259
260 #[test]
261 fn ensure_meta_has_ver_when_missing() {
262 let mut meta = Dict::new();
263 meta.insert("site".into(), "alpha".into());
264
265 let result = ensure_meta_has_ver(Some(&meta));
266
267 assert!(result.has("ver"));
268 assert!(result.has("site"));
269 assert!(!meta.has("ver"));
270 }
271
272 #[test]
273 fn ensure_meta_has_ver_creates_meta_when_none() {
274 let result = ensure_meta_has_ver(None);
275
276 assert!(result.has("ver"));
277 assert_eq!(result.len(), 1);
278 }
279}