1use crate::sql;
2use crate::sql::constant::ConstantValue;
3use crate::sql::Number;
4use crate::sql::Value;
5use serde::Serialize;
6use serde_json::json;
7use serde_json::Map;
8use serde_json::Value as JsonValue;
9
10impl From<Value> for serde_json::Value {
11 fn from(value: Value) -> Self {
12 match value {
13 Value::None | Value::Null => JsonValue::Null,
17 Value::Bool(boolean) => boolean.into(),
18 Value::Number(number) => match number {
19 Number::Int(int) => int.into(),
20 Number::Float(float) => float.into(),
21 Number::Decimal(decimal) => json!(decimal),
22 },
23 Value::Strand(strand) => strand.0.into(),
24 Value::Duration(duration) => duration.to_raw().into(),
25 Value::Datetime(datetime) => json!(datetime.0),
26 Value::Uuid(uuid) => json!(uuid.0),
27 Value::Array(array) => JsonValue::Array(Array::from(array).0),
28 Value::Object(object) => JsonValue::Object(Object::from(object).0),
29 Value::Geometry(geo) => Geometry::from(geo).0,
30 Value::Bytes(bytes) => json!(bytes.0),
31 Value::Thing(thing) => thing.to_string().into(),
32 Value::Param(param) => json!(param),
36 Value::Idiom(idiom) => json!(idiom),
37 Value::Table(table) => json!(table),
38 Value::Mock(mock) => json!(mock),
39 Value::Regex(regex) => json!(regex),
40 Value::Block(block) => json!(block),
41 Value::Range(range) => json!(range),
42 Value::Edges(edges) => json!(edges),
43 Value::Future(future) => json!(future),
44 Value::Constant(constant) => match constant.value() {
45 ConstantValue::Datetime(datetime) => json!(datetime.0),
46 ConstantValue::Float(float) => float.into(),
47 ConstantValue::Duration(duration) => duration.to_string().into(),
48 },
49 Value::Cast(cast) => json!(cast),
50 Value::Function(function) => json!(function),
51 Value::Model(model) => json!(model),
52 Value::Query(query) => json!(query),
53 Value::Subquery(subquery) => json!(subquery),
54 Value::Expression(expression) => json!(expression),
55 Value::Closure(closure) => json!(closure),
56 Value::Refs(_) => json!(sql::Array::new()),
57 }
58 }
59}
60
61#[derive(Serialize)]
62struct Array(Vec<JsonValue>);
63
64impl From<sql::Array> for Array {
65 fn from(arr: sql::Array) -> Self {
66 let mut vec = Vec::with_capacity(arr.len());
67 for value in arr {
68 vec.push(value.into());
69 }
70 Self(vec)
71 }
72}
73
74#[derive(Serialize)]
75struct Object(Map<String, JsonValue>);
76
77impl From<sql::Object> for Object {
78 fn from(obj: sql::Object) -> Self {
79 let mut map = Map::with_capacity(obj.len());
80 for (key, value) in obj {
81 map.insert(key.to_owned(), value.into());
82 }
83 Self(map)
84 }
85}
86
87#[derive(Serialize)]
88enum CoordinatesType {
89 Point,
90 LineString,
91 Polygon,
92 MultiPoint,
93 MultiLineString,
94 MultiPolygon,
95}
96
97#[derive(Serialize)]
98struct Coordinates {
99 #[serde(rename = "type")]
100 typ: CoordinatesType,
101 coordinates: JsonValue,
102}
103
104struct GeometryCollection;
105
106impl Serialize for GeometryCollection {
107 fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
108 where
109 S: serde::Serializer,
110 {
111 s.serialize_str("GeometryCollection")
112 }
113}
114
115#[derive(Serialize)]
116struct Geometries {
117 #[serde(rename = "type")]
118 typ: GeometryCollection,
119 geometries: Vec<JsonValue>,
120}
121
122#[derive(Serialize)]
123struct Geometry(JsonValue);
124
125impl From<sql::Geometry> for Geometry {
126 fn from(geo: sql::Geometry) -> Self {
127 Self(match geo {
128 sql::Geometry::Point(v) => json!(Coordinates {
129 typ: CoordinatesType::Point,
130 coordinates: vec![json!(v.x()), json!(v.y())].into(),
131 }),
132 sql::Geometry::Line(v) => json!(Coordinates {
133 typ: CoordinatesType::LineString,
134 coordinates: v
135 .points()
136 .map(|p| vec![json!(p.x()), json!(p.y())].into())
137 .collect::<Vec<JsonValue>>()
138 .into(),
139 }),
140 sql::Geometry::Polygon(v) => json!(Coordinates {
141 typ: CoordinatesType::Polygon,
142 coordinates: vec![v
143 .exterior()
144 .points()
145 .map(|p| vec![json!(p.x()), json!(p.y())].into())
146 .collect::<Vec<JsonValue>>()]
147 .into_iter()
148 .chain(
149 v.interiors()
150 .iter()
151 .map(|i| {
152 i.points()
153 .map(|p| vec![json!(p.x()), json!(p.y())].into())
154 .collect::<Vec<JsonValue>>()
155 })
156 .collect::<Vec<Vec<JsonValue>>>(),
157 )
158 .collect::<Vec<Vec<JsonValue>>>()
159 .into(),
160 }),
161 sql::Geometry::MultiPoint(v) => json!(Coordinates {
162 typ: CoordinatesType::MultiPoint,
163 coordinates: v
164 .0
165 .iter()
166 .map(|v| vec![json!(v.x()), json!(v.y())].into())
167 .collect::<Vec<JsonValue>>()
168 .into()
169 }),
170 sql::Geometry::MultiLine(v) => json!(Coordinates {
171 typ: CoordinatesType::MultiLineString,
172 coordinates: v
173 .0
174 .iter()
175 .map(|v| {
176 v.points()
177 .map(|v| vec![json!(v.x()), json!(v.y())].into())
178 .collect::<Vec<JsonValue>>()
179 })
180 .collect::<Vec<Vec<JsonValue>>>()
181 .into()
182 }),
183 sql::Geometry::MultiPolygon(v) => json!(Coordinates {
184 typ: CoordinatesType::MultiPolygon,
185 coordinates: v
186 .0
187 .iter()
188 .map(|v| {
189 vec![v
190 .exterior()
191 .points()
192 .map(|p| vec![json!(p.x()), json!(p.y())].into())
193 .collect::<Vec<JsonValue>>()]
194 .into_iter()
195 .chain(
196 v.interiors()
197 .iter()
198 .map(|i| {
199 i.points()
200 .map(|p| vec![json!(p.x()), json!(p.y())].into())
201 .collect::<Vec<JsonValue>>()
202 })
203 .collect::<Vec<Vec<JsonValue>>>(),
204 )
205 .collect::<Vec<Vec<JsonValue>>>()
206 })
207 .collect::<Vec<Vec<Vec<JsonValue>>>>()
208 .into(),
209 }),
210 sql::Geometry::Collection(v) => json!(Geometries {
211 typ: GeometryCollection,
212 geometries: v.into_iter().map(Geometry::from).map(|x| x.0).collect(),
213 }),
214 })
215 }
216}
217
218#[cfg(test)]
219mod tests {
220 mod into_json {
221 use crate::sql;
222 use crate::sql::from_value;
223 use crate::sql::Value;
224 use chrono::DateTime;
225 use chrono::Utc;
226 use geo::line_string;
227 use geo::point;
228 use geo::polygon;
229 use geo::LineString;
230 use geo::MultiLineString;
231 use geo::MultiPoint;
232 use geo::MultiPolygon;
233 use geo::Point;
234 use geo::Polygon;
235 use rust_decimal::Decimal;
236 use serde_json::json;
237 use serde_json::Value as Json;
238 use std::collections::BTreeMap;
239 use std::time::Duration;
240 use uuid::Uuid;
241
242 #[test]
243 fn none_or_null() {
244 for value in [Value::None, Value::Null] {
245 let simple_json = Json::from(value.clone());
246 assert_eq!(simple_json, json!(null));
247
248 let response: Option<String> = from_value(value).unwrap();
249 assert_eq!(response, None);
250 }
251 }
252
253 #[test]
254 fn bool() {
255 for boolean in [true, false] {
256 let value = Value::Bool(boolean);
257
258 let simple_json = Json::from(value.clone());
259 assert_eq!(simple_json, json!(boolean));
260
261 let response: bool = from_value(value).unwrap();
262 assert_eq!(response, boolean);
263 }
264 }
265
266 #[test]
267 fn number_int() {
268 for num in [i64::MIN, 0, i64::MAX] {
269 let value = Value::Number(sql::Number::Int(num));
270
271 let simple_json = Json::from(value.clone());
272 assert_eq!(simple_json, json!(num));
273
274 let response: i64 = from_value(value).unwrap();
275 assert_eq!(response, num);
276 }
277 }
278
279 #[test]
280 fn number_float() {
281 for num in [f64::NEG_INFINITY, f64::MIN, 0.0, f64::MAX, f64::INFINITY, f64::NAN] {
282 let value = Value::Number(sql::Number::Float(num));
283
284 let simple_json = Json::from(value.clone());
285 assert_eq!(simple_json, json!(num));
286
287 let response: f64 = from_value(value).unwrap();
288 if response.is_finite() {
289 assert_eq!(response, num);
291 }
292 }
293 }
294
295 #[test]
296 fn number_decimal() {
297 for num in [i64::MIN, 0, i64::MAX] {
298 let num = Decimal::new(num, 0);
299 let value = Value::Number(sql::Number::Decimal(num));
300
301 let simple_json = Json::from(value.clone());
302 assert_eq!(simple_json, json!(num.to_string()));
303
304 let response: Decimal = from_value(value).unwrap();
305 assert_eq!(response, num);
306 }
307 }
308
309 #[test]
310 fn strand() {
311 for str in ["", "foo"] {
312 let value = Value::Strand(str.into());
313
314 let simple_json = Json::from(value.clone());
315 assert_eq!(simple_json, json!(str));
316
317 let response: String = from_value(value).unwrap();
318 assert_eq!(response, str);
319 }
320 }
321
322 #[test]
323 fn duration() {
324 for duration in [Duration::ZERO, Duration::MAX] {
325 let value = Value::Duration(duration.into());
326
327 let simple_json = Json::from(value.clone());
328 assert_eq!(simple_json, json!(sql::Duration(duration).to_raw()));
329
330 let response: Duration = from_value(value).unwrap();
331 assert_eq!(response, duration);
332 }
333 }
334
335 #[test]
336 fn datetime() {
337 for datetime in [DateTime::<Utc>::MIN_UTC, DateTime::<Utc>::MAX_UTC] {
338 let value = Value::Datetime(datetime.into());
339
340 let simple_json = Json::from(value.clone());
341 assert_eq!(simple_json, json!(datetime));
342
343 let response: DateTime<Utc> = from_value(value).unwrap();
344 assert_eq!(response, datetime);
345 }
346 }
347
348 #[test]
349 fn uuid() {
350 for uuid in [Uuid::nil(), Uuid::max()] {
351 let value = Value::Uuid(uuid.into());
352
353 let simple_json = Json::from(value.clone());
354 assert_eq!(simple_json, json!(uuid));
355
356 let response: Uuid = from_value(value).unwrap();
357 assert_eq!(response, uuid);
358 }
359 }
360
361 #[test]
362 fn array() {
363 for vec in [vec![], vec![true, false]] {
364 let value =
365 Value::Array(sql::Array(vec.iter().copied().map(Value::from).collect()));
366
367 let simple_json = Json::from(value.clone());
368 assert_eq!(simple_json, json!(vec));
369
370 let response: Vec<bool> = from_value(value).unwrap();
371 assert_eq!(response, vec);
372 }
373 }
374
375 #[test]
376 fn object() {
377 for map in [BTreeMap::new(), map!("done".to_owned() => true)] {
378 let value = Value::Object(sql::Object(
379 map.iter().map(|(key, value)| (key.clone(), Value::from(*value))).collect(),
380 ));
381
382 let simple_json = Json::from(value.clone());
383 assert_eq!(simple_json, json!(map));
384
385 let response: BTreeMap<String, bool> = from_value(value).unwrap();
386 assert_eq!(response, map);
387 }
388 }
389
390 #[test]
391 fn geometry_point() {
392 let point = point! { x: 10., y: 20. };
393 let value = Value::Geometry(sql::Geometry::Point(point));
394
395 let simple_json = Json::from(value.clone());
396 assert_eq!(simple_json, json!({ "type": "Point", "coordinates": [10., 20.]}));
397
398 let response: Point = from_value(value).unwrap();
399 assert_eq!(response, point);
400 }
401
402 #[test]
403 fn geometry_line() {
404 let line_string = line_string![
405 ( x: 0., y: 0. ),
406 ( x: 10., y: 0. ),
407 ];
408 let value = Value::Geometry(sql::Geometry::Line(line_string.clone()));
409
410 let simple_json = Json::from(value.clone());
411 assert_eq!(
412 simple_json,
413 json!({ "type": "LineString", "coordinates": [[0., 0.], [10., 0.]]})
414 );
415
416 let response: LineString = from_value(value).unwrap();
417 assert_eq!(response, line_string);
418 }
419
420 #[test]
421 fn geometry_polygon() {
422 let polygon = polygon![
423 (x: -111., y: 45.),
424 (x: -111., y: 41.),
425 (x: -104., y: 41.),
426 (x: -104., y: 45.),
427 ];
428 let value = Value::Geometry(sql::Geometry::Polygon(polygon.clone()));
429
430 let simple_json = Json::from(value.clone());
431 assert_eq!(
432 simple_json,
433 json!({ "type": "Polygon", "coordinates": [[
434 [-111., 45.],
435 [-111., 41.],
436 [-104., 41.],
437 [-104., 45.],
438 [-111., 45.],
439 ]]})
440 );
441
442 let response: Polygon = from_value(value).unwrap();
443 assert_eq!(response, polygon);
444 }
445
446 #[test]
447 fn geometry_multi_point() {
448 let multi_point: MultiPoint =
449 vec![point! { x: 0., y: 0. }, point! { x: 1., y: 2. }].into();
450 let value = Value::Geometry(sql::Geometry::MultiPoint(multi_point.clone()));
451
452 let simple_json = Json::from(value.clone());
453 assert_eq!(
454 simple_json,
455 json!({ "type": "MultiPoint", "coordinates": [[0., 0.], [1., 2.]]})
456 );
457
458 let response: MultiPoint = from_value(value).unwrap();
459 assert_eq!(response, multi_point);
460 }
461
462 #[test]
463 fn geometry_multi_line() {
464 let multi_line = MultiLineString::new(vec![line_string![
465 ( x: 0., y: 0. ),
466 ( x: 1., y: 2. ),
467 ]]);
468 let value = Value::Geometry(sql::Geometry::MultiLine(multi_line.clone()));
469
470 let simple_json = Json::from(value.clone());
471 assert_eq!(
472 simple_json,
473 json!({ "type": "MultiLineString", "coordinates": [[[0., 0.], [1., 2.]]]})
474 );
475
476 let response: MultiLineString = from_value(value).unwrap();
477 assert_eq!(response, multi_line);
478 }
479
480 #[test]
481 fn geometry_multi_polygon() {
482 let multi_polygon: MultiPolygon = vec![polygon![
483 (x: -111., y: 45.),
484 (x: -111., y: 41.),
485 (x: -104., y: 41.),
486 (x: -104., y: 45.),
487 ]]
488 .into();
489 let value = Value::Geometry(sql::Geometry::MultiPolygon(multi_polygon.clone()));
490
491 let simple_json = Json::from(value.clone());
492 assert_eq!(
493 simple_json,
494 json!({ "type": "MultiPolygon", "coordinates": [[[
495 [-111., 45.],
496 [-111., 41.],
497 [-104., 41.],
498 [-104., 45.],
499 [-111., 45.],
500 ]]]})
501 );
502
503 let response: MultiPolygon = from_value(value).unwrap();
504 assert_eq!(response, multi_polygon);
505 }
506
507 #[test]
508 fn geometry_collection() {
509 for geometries in [vec![], vec![sql::Geometry::Point(point! { x: 10., y: 20. })]] {
510 let value = Value::Geometry(geometries.clone().into());
511
512 let simple_json = Json::from(value.clone());
513 assert_eq!(
514 simple_json,
515 json!({
516 "type": "GeometryCollection",
517 "geometries": geometries.clone().into_iter().map(|geo| Json::from(Value::from(geo))).collect::<Vec<_>>(),
518 })
519 );
520
521 let response: Vec<sql::Geometry> = from_value(value).unwrap();
522 assert_eq!(response, geometries);
523 }
524 }
525
526 #[test]
527 fn bytes() {
528 for bytes in [vec![], b"foo".to_vec()] {
529 let value = Value::Bytes(sql::Bytes(bytes.clone()));
530
531 let simple_json = Json::from(value.clone());
532 assert_eq!(simple_json, json!(bytes));
533
534 let sql::Bytes(response) = from_value(value).unwrap();
535 assert_eq!(response, bytes);
536 }
537 }
538
539 #[test]
540 fn thing() {
541 let record_id = "foo:bar";
542 let thing = sql::thing(record_id).unwrap();
543 let value = Value::Thing(thing.clone());
544
545 let simple_json = Json::from(value.clone());
546 assert_eq!(simple_json, json!(record_id));
547
548 let response: sql::Thing = from_value(value).unwrap();
549 assert_eq!(response, thing);
550 }
551 }
552}