entity_async_graphql/ent/
value.rs

1use async_graphql::{
2    InputValueError, InputValueResult, Name, Number as AsyncGraphqlNumber, Scalar, ScalarType,
3    Value as AsyncGraphqlValue,
4};
5use derive_more::{From, Into};
6use entity::{Number, Primitive, Value, ValueLike};
7use std::collections::HashMap;
8
9/// Represents a wrapper around a `Value` to expose as graphql
10#[derive(Clone, PartialOrd, PartialEq, Eq, Hash, From, Into)]
11pub struct GqlValue(Value);
12
13impl ValueLike for GqlValue {
14    fn into_value(self) -> Value {
15        self.0
16    }
17
18    fn try_from_value(value: Value) -> Result<Self, Value> {
19        Ok(Self(value))
20    }
21}
22
23#[Scalar]
24impl ScalarType for GqlValue {
25    fn parse(value: AsyncGraphqlValue) -> InputValueResult<Self> {
26        match value {
27            AsyncGraphqlValue::Null => Ok(Value::Optional(None)),
28            AsyncGraphqlValue::Number(x) => Ok(x
29                .as_u64()
30                .map(Value::from)
31                .or_else(|| x.as_i64().map(Value::from))
32                .or_else(|| x.as_f64().map(Value::from))
33                .expect("Incoming number not u64/i64/f64")),
34            AsyncGraphqlValue::String(x) => Ok(Value::from(x)),
35            AsyncGraphqlValue::Boolean(x) => Ok(Value::from(x)),
36            AsyncGraphqlValue::List(x) => Ok(Value::from(
37                x.into_iter()
38                    .map(GqlValue::parse)
39                    .collect::<Result<Vec<GqlValue>, InputValueError<Self>>>()?,
40            )),
41            AsyncGraphqlValue::Object(x) => Ok(Value::from(
42                x.into_iter()
43                    .map(|(name, value)| {
44                        GqlValue::parse(value).map(|value| (name.as_str().to_string(), value))
45                    })
46                    .collect::<Result<HashMap<String, GqlValue>, InputValueError<Self>>>()?,
47            )),
48            AsyncGraphqlValue::Enum(_) => Err(InputValueError::expected_type(value)),
49        }
50        .map(GqlValue::from)
51    }
52
53    fn to_value(&self) -> AsyncGraphqlValue {
54        match &self.0 {
55            Value::List(x) => AsyncGraphqlValue::List(
56                x.iter()
57                    .map(|x| GqlValue::from(x.clone()).to_value())
58                    .collect(),
59            ),
60            Value::Map(x) => AsyncGraphqlValue::Object(
61                x.iter()
62                    .map(|(k, v)| (Name::new(k), Self::from(v.clone()).to_value()))
63                    .collect(),
64            ),
65            Value::Optional(None) => AsyncGraphqlValue::Null,
66            Value::Optional(Some(x)) => Self::from(*x.clone()).to_value(),
67            Value::Primitive(Primitive::Bool(x)) => AsyncGraphqlValue::Boolean(*x),
68            Value::Primitive(Primitive::Char(x)) => AsyncGraphqlValue::String(x.to_string()),
69            Value::Primitive(Primitive::Unit) => AsyncGraphqlValue::from(()),
70            Value::Primitive(Primitive::Number(x)) => match x {
71                Number::F32(x) => AsyncGraphqlNumber::from_f64(*x as f64)
72                    .map(AsyncGraphqlValue::Number)
73                    .unwrap_or(AsyncGraphqlValue::Null),
74                Number::F64(x) => AsyncGraphqlNumber::from_f64(*x)
75                    .map(AsyncGraphqlValue::Number)
76                    .unwrap_or(AsyncGraphqlValue::Null),
77                Number::I128(x) => AsyncGraphqlValue::Number(AsyncGraphqlNumber::from(*x as i64)),
78                Number::I64(x) => AsyncGraphqlValue::Number(AsyncGraphqlNumber::from(*x)),
79                Number::I32(x) => AsyncGraphqlValue::Number(AsyncGraphqlNumber::from(*x)),
80                Number::I16(x) => AsyncGraphqlValue::Number(AsyncGraphqlNumber::from(*x)),
81                Number::I8(x) => AsyncGraphqlValue::Number(AsyncGraphqlNumber::from(*x)),
82                Number::Isize(x) => AsyncGraphqlValue::Number(AsyncGraphqlNumber::from(*x)),
83                Number::U128(x) => AsyncGraphqlValue::Number(AsyncGraphqlNumber::from(*x as u64)),
84                Number::U64(x) => AsyncGraphqlValue::Number(AsyncGraphqlNumber::from(*x)),
85                Number::U32(x) => AsyncGraphqlValue::Number(AsyncGraphqlNumber::from(*x)),
86                Number::U16(x) => AsyncGraphqlValue::Number(AsyncGraphqlNumber::from(*x)),
87                Number::U8(x) => AsyncGraphqlValue::Number(AsyncGraphqlNumber::from(*x)),
88                Number::Usize(x) => AsyncGraphqlValue::Number(AsyncGraphqlNumber::from(*x)),
89            },
90            Value::Text(x) => AsyncGraphqlValue::String(x.to_string()),
91        }
92    }
93}