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