diff --git a/CHANGELOG.md b/CHANGELOG.md index 6dca244c..3c4268d0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Add support for `graphql-ws` pings. [#635](https://github.com/async-graphql/async-graphql/issues/635) - Add feature gate `websocket` for async-graphql-tide. [#636](https://github.com/async-graphql/async-graphql/issues/636) +- Implement GraphQL enum to `Value` conversion. [#617](https://github.com/async-graphql/async-graphql/issues/617) +- Implement `ScalarType` for `HashMap`/`BTreeMap` to use `ToString`/`FromStr`. [#585](https://github.com/async-graphql/async-graphql/issues/585) ## [2.9.15] 2021-09-10 diff --git a/derive/src/enum.rs b/derive/src/enum.rs index 40432691..781d8815 100644 --- a/derive/src/enum.rs +++ b/derive/src/enum.rs @@ -167,7 +167,7 @@ pub fn generate(enum_args: &args::Enum) -> GeneratorResult { } } - impl From<#ident> for #crate_name::Value { + impl ::std::convert::From<#ident> for #crate_name::Value { fn from(value: #ident) -> #crate_name::Value { #crate_name::resolver_utils::enum_value(value) } diff --git a/src/types/external/json_object/btreemap.rs b/src/types/external/json_object/btreemap.rs index 932d53f0..c3f14660 100644 --- a/src/types/external/json_object/btreemap.rs +++ b/src/types/external/json_object/btreemap.rs @@ -1,4 +1,6 @@ use std::collections::BTreeMap; +use std::fmt::Display; +use std::str::FromStr; use crate::{ InputType, InputValueError, InputValueResult, Name, OutputType, Scalar, ScalarType, Value, @@ -6,15 +8,24 @@ use crate::{ /// A scalar that can represent any JSON Object value. #[Scalar(internal, name = "JSONObject")] -impl ScalarType for BTreeMap +impl ScalarType for BTreeMap where + K: ToString + FromStr + Ord + Sync + Send, + K::Err: Display, T: OutputType + InputType, { fn parse(value: Value) -> InputValueResult { match value { Value::Object(map) => map .into_iter() - .map(|(name, value)| Ok((name.to_string(), T::parse(Some(value))?))) + .map(|(name, value)| { + Ok(( + K::from_str(&name).map_err(|err| { + InputValueError::custom(format!("object key: {}", err)) + })?, + T::parse(Some(value))?, + )) + }) .collect::>() .map_err(InputValueError::propagate), _ => Err(InputValueError::expected_type(value)), @@ -24,7 +35,7 @@ where fn to_value(&self) -> Value { let mut map = BTreeMap::new(); for (name, value) in self { - map.insert(Name::new(name), value.to_value()); + map.insert(Name::new(name.to_string()), value.to_value()); } Value::Object(map) } diff --git a/src/types/external/json_object/hashmap.rs b/src/types/external/json_object/hashmap.rs index 3e43d288..d805f6ca 100644 --- a/src/types/external/json_object/hashmap.rs +++ b/src/types/external/json_object/hashmap.rs @@ -1,4 +1,7 @@ use std::collections::{BTreeMap, HashMap}; +use std::fmt::Display; +use std::hash::Hash; +use std::str::FromStr; use crate::{ InputType, InputValueError, InputValueResult, Name, OutputType, Scalar, ScalarType, Value, @@ -6,15 +9,24 @@ use crate::{ /// A scalar that can represent any JSON Object value. #[Scalar(internal, name = "JSONObject")] -impl ScalarType for HashMap +impl ScalarType for HashMap where - T: OutputType + InputType, + K: ToString + FromStr + Eq + Hash + Sync + Send, + K::Err: Display, + V: OutputType + InputType, { fn parse(value: Value) -> InputValueResult { match value { Value::Object(map) => map .into_iter() - .map(|(name, value)| Ok((name.to_string(), T::parse(Some(value))?))) + .map(|(name, value)| { + Ok(( + K::from_str(&name).map_err(|err| { + InputValueError::custom(format!("object key: {}", err)) + })?, + V::parse(Some(value))?, + )) + }) .collect::>() .map_err(InputValueError::propagate), _ => Err(InputValueError::expected_type(value)), @@ -24,7 +36,7 @@ where fn to_value(&self) -> Value { let mut map = BTreeMap::new(); for (name, value) in self { - map.insert(Name::new(name), value.to_value()); + map.insert(Name::new(name.to_string()), value.to_value()); } Value::Object(map) }