async_graphql/types/external/
optional.rs

1use std::borrow::Cow;
2
3use crate::{
4    parser::types::Field, registry, ContextSelectionSet, InputType, InputValueError,
5    InputValueResult, OutputType, Positioned, ServerResult, Value,
6};
7
8impl<T: InputType> InputType for Option<T> {
9    type RawValueType = T::RawValueType;
10
11    fn type_name() -> Cow<'static, str> {
12        T::type_name()
13    }
14
15    fn qualified_type_name() -> String {
16        T::type_name().to_string()
17    }
18
19    fn create_type_info(registry: &mut registry::Registry) -> String {
20        T::create_type_info(registry);
21        T::type_name().to_string()
22    }
23
24    fn parse(value: Option<Value>) -> InputValueResult<Self> {
25        match value.unwrap_or_default() {
26            Value::Null => Ok(None),
27            value => Ok(Some(
28                T::parse(Some(value)).map_err(InputValueError::propagate)?,
29            )),
30        }
31    }
32
33    fn to_value(&self) -> Value {
34        match self {
35            Some(value) => value.to_value(),
36            None => Value::Null,
37        }
38    }
39
40    fn as_raw_value(&self) -> Option<&Self::RawValueType> {
41        match self {
42            Some(value) => value.as_raw_value(),
43            None => None,
44        }
45    }
46}
47
48#[cfg_attr(feature = "boxed-trait", async_trait::async_trait)]
49impl<T: OutputType + Sync> OutputType for Option<T> {
50    fn type_name() -> Cow<'static, str> {
51        T::type_name()
52    }
53
54    fn qualified_type_name() -> String {
55        T::type_name().to_string()
56    }
57
58    fn create_type_info(registry: &mut registry::Registry) -> String {
59        T::create_type_info(registry);
60        T::type_name().to_string()
61    }
62
63    async fn resolve(
64        &self,
65        ctx: &ContextSelectionSet<'_>,
66        field: &Positioned<Field>,
67    ) -> ServerResult<Value> {
68        if let Some(inner) = self {
69            match OutputType::resolve(inner, ctx, field).await {
70                Ok(value) => Ok(value),
71                Err(err) => {
72                    ctx.add_error(err);
73                    Ok(Value::Null)
74                }
75            }
76        } else {
77            Ok(Value::Null)
78        }
79    }
80}
81
82#[cfg(test)]
83mod tests {
84    use crate::InputType;
85
86    #[test]
87    fn test_optional_type() {
88        assert_eq!(Option::<i32>::type_name(), "Int");
89        assert_eq!(Option::<i32>::qualified_type_name(), "Int");
90        assert_eq!(&Option::<i32>::type_name(), "Int");
91        assert_eq!(&Option::<i32>::qualified_type_name(), "Int");
92    }
93}