From 9b43b136e8a89d3fc53efe07436d6e3c324b36e8 Mon Sep 17 00:00:00 2001 From: Sunli Date: Fri, 21 Jan 2022 10:25:50 +0800 Subject: [PATCH] Implement `InputType` for `Box` and `Arc`. #792 --- CHANGELOG.md | 3 +++ src/types/external/string.rs | 41 ++++++++++++++++++++++++++++++++++-- tests/input_value.rs | 27 ++++++++++++++++++++++++ 3 files changed, 69 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 51668248..0e265baa 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 # [3.0.23] 2022-1-19 - Bump hashbrown from `0.11.2` to `0.12.0`. +- Implement `InputType` for `Box` and `Arc`. [#792](https://github.com/async-graphql/async-graphql/issues/792) +- Add scalars for the `time` crate's datetime types. [#791](https://github.com/async-graphql/async-graphql/pull/791) +- Add `DataContext` trait. [#786](https://github.com/async-graphql/async-graphql/pull/786) ## [3.0.22] 2022-1-11 diff --git a/src/types/external/string.rs b/src/types/external/string.rs index 7c7dbf15..523ef63d 100644 --- a/src/types/external/string.rs +++ b/src/types/external/string.rs @@ -1,9 +1,10 @@ use std::borrow::Cow; use crate::parser::types::Field; +use crate::registry::Registry; use crate::{ - registry, ContextSelectionSet, InputValueError, InputValueResult, OutputType, Positioned, - Scalar, ScalarType, ServerResult, Value, + registry, ContextSelectionSet, InputType, InputValueError, InputValueResult, OutputType, + Positioned, Scalar, ScalarType, ServerResult, Value, }; /// The `String` scalar type represents textual data, represented as UTF-8 character sequences. The String type is most often used by GraphQL to represent free-form human-readable text. @@ -25,6 +26,42 @@ impl ScalarType for String { } } +macro_rules! impl_input_string_for_smart_ptr { + ($ty:ty) => { + #[async_trait::async_trait] + impl InputType for $ty { + type RawValueType = Self; + + fn type_name() -> Cow<'static, str> { + Cow::Borrowed("String") + } + + fn create_type_info(registry: &mut Registry) -> String { + ::create_type_info(registry) + } + + fn parse(value: Option) -> InputValueResult { + let value = value.unwrap_or_default(); + match value { + Value::String(s) => Ok(s.into()), + _ => Err(InputValueError::expected_type(value)), + } + } + + fn to_value(&self) -> Value { + Value::String(self.to_string()) + } + + fn as_raw_value(&self) -> Option<&Self::RawValueType> { + Some(self) + } + } + }; +} + +impl_input_string_for_smart_ptr!(Box); +impl_input_string_for_smart_ptr!(std::sync::Arc); + #[async_trait::async_trait] impl OutputType for str { fn type_name() -> Cow<'static, str> { diff --git a/tests/input_value.rs b/tests/input_value.rs index 6ea3f871..387c05cf 100644 --- a/tests/input_value.rs +++ b/tests/input_value.rs @@ -1,4 +1,5 @@ use async_graphql::*; +use std::sync::Arc; #[tokio::test] pub async fn test_input_value_custom_error() { @@ -28,3 +29,29 @@ pub async fn test_input_value_custom_error() { }], ); } + +#[tokio::test] +pub async fn test_input_box_str() { + struct Query; + + #[Object] + impl Query { + async fn box_str(&self, s: Box) -> String { + s.to_string() + } + + async fn arc_str(&self, s: Arc) -> String { + s.to_string() + } + } + + let schema = Schema::new(Query, EmptyMutation, EmptySubscription); + let query = r#"{ boxStr(s: "abc") arcStr(s: "def") }"#; + assert_eq!( + schema.execute(query).await.into_result().unwrap().data, + value!({ + "boxStr": "abc", + "arcStr": "def", + }) + ); +}