use std::borrow::Cow; use crate::{ parser::types::Field, registry, ContextSelectionSet, InputType, InputValueError, InputValueResult, OutputType, Positioned, ServerResult, Value, }; impl InputType for Option { type RawValueType = T::RawValueType; 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() } 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, } } fn as_raw_value(&self) -> Option<&Self::RawValueType> { match self { Some(value) => value.as_raw_value(), None => None, } } } #[async_trait::async_trait] impl OutputType 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() } async fn resolve( &self, ctx: &ContextSelectionSet<'_>, field: &Positioned, ) -> ServerResult { if let Some(inner) = self { match OutputType::resolve(inner, ctx, field).await { Ok(value) => Ok(value), Err(err) => { ctx.add_error(err); Ok(Value::Null) } } } else { Ok(Value::Null) } } } #[cfg(test)] mod tests { use crate::InputType; #[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"); } }