use std::borrow::Cow; use crate::parser::types::Field; use crate::{ registry, ContextSelectionSet, InputType, InputValueError, InputValueResult, OutputType, Positioned, ServerResult, Type, Value, }; impl Type for Option { fn type_name() -> Cow<'static, str> { T::type_name() } fn qualified_type_name() -> String { T::type_name().to_string() } fn create_type_info(registry: &mut registry::Registry) -> String { T::create_type_info(registry); T::type_name().to_string() } } impl InputType for Option { fn parse(value: Option) -> InputValueResult { match value.unwrap_or_default() { Value::Null => Ok(None), value => Ok(Some( T::parse(Some(value)).map_err(InputValueError::propagate)?, )), } } fn to_value(&self) -> Value { match self { Some(value) => value.to_value(), None => Value::Null, } } } #[async_trait::async_trait] impl OutputType for Option { async fn resolve( &self, ctx: &ContextSelectionSet<'_>, field: &Positioned, ) -> ServerResult { if let Some(inner) = self { OutputType::resolve(inner, ctx, field).await } else { Ok(Value::Null) } } } #[cfg(test)] mod tests { use crate::Type; #[test] fn test_optional_type() { assert_eq!(Option::::type_name(), "Int"); assert_eq!(Option::::qualified_type_name(), "Int"); assert_eq!(&Option::::type_name(), "Int"); assert_eq!(&Option::::qualified_type_name(), "Int"); } }