juniper_puff/integrations/
bson.rs

1//! GraphQL support for [bson](https://github.com/mongodb/bson-rust) types.
2
3use crate::{graphql_scalar, InputValue, ScalarValue, Value};
4
5#[graphql_scalar(with = object_id, parse_token(String))]
6type ObjectId = bson::oid::ObjectId;
7
8mod object_id {
9    use super::*;
10
11    pub(super) fn to_output<S: ScalarValue>(v: &ObjectId) -> Value<S> {
12        Value::scalar(v.to_hex())
13    }
14
15    pub(super) fn from_input<S: ScalarValue>(v: &InputValue<S>) -> Result<ObjectId, String> {
16        v.as_string_value()
17            .ok_or_else(|| format!("Expected `String`, found: {v}"))
18            .and_then(|s| {
19                ObjectId::parse_str(s).map_err(|e| format!("Failed to parse `ObjectId`: {e}"))
20            })
21    }
22}
23
24#[graphql_scalar(with = utc_date_time, parse_token(String))]
25type UtcDateTime = bson::DateTime;
26
27mod utc_date_time {
28    use super::*;
29
30    pub(super) fn to_output<S: ScalarValue>(v: &UtcDateTime) -> Value<S> {
31        Value::scalar(
32            (*v).try_to_rfc3339_string()
33                .unwrap_or_else(|e| panic!("failed to format `UtcDateTime` as RFC3339: {e}")),
34        )
35    }
36
37    pub(super) fn from_input<S: ScalarValue>(v: &InputValue<S>) -> Result<UtcDateTime, String> {
38        v.as_string_value()
39            .ok_or_else(|| format!("Expected `String`, found: {v}"))
40            .and_then(|s| {
41                UtcDateTime::parse_rfc3339_str(s)
42                    .map_err(|e| format!("Failed to parse `UtcDateTime`: {e}"))
43            })
44    }
45}
46
47#[cfg(test)]
48mod test {
49    use bson::{oid::ObjectId, DateTime as UtcDateTime};
50
51    use crate::{graphql_input_value, FromInputValue, InputValue};
52
53    #[test]
54    fn objectid_from_input() {
55        let raw = "53e37d08776f724e42000000";
56        let input: InputValue = graphql_input_value!((raw));
57
58        let parsed: ObjectId = FromInputValue::from_input_value(&input).unwrap();
59        let id = ObjectId::parse_str(raw).unwrap();
60
61        assert_eq!(parsed, id);
62    }
63
64    #[test]
65    fn utcdatetime_from_input() {
66        use chrono::{DateTime, Utc};
67
68        let raw = "2020-03-23T17:38:32.446+00:00";
69        let input: InputValue = graphql_input_value!((raw));
70
71        let parsed: UtcDateTime = FromInputValue::from_input_value(&input).unwrap();
72        let date_time = UtcDateTime::from_chrono(
73            DateTime::parse_from_rfc3339(raw)
74                .unwrap()
75                .with_timezone(&Utc),
76        );
77
78        assert_eq!(parsed, date_time);
79    }
80}