Implement ScalarType for HashMap/BTreeMap to use ToString/FromStr. #585

This commit is contained in:
Sunli 2021-09-17 09:16:22 +08:00
parent 296a59225e
commit ee0e917813
4 changed files with 33 additions and 8 deletions

View File

@ -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

View File

@ -167,7 +167,7 @@ pub fn generate(enum_args: &args::Enum) -> GeneratorResult<TokenStream> {
}
}
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)
}

View File

@ -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<T> ScalarType for BTreeMap<String, T>
impl<K, T> ScalarType for BTreeMap<K, T>
where
K: ToString + FromStr + Ord + Sync + Send,
K::Err: Display,
T: OutputType + InputType,
{
fn parse(value: Value) -> InputValueResult<Self> {
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::<Result<_, _>>()
.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)
}

View File

@ -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<T> ScalarType for HashMap<String, T>
impl<K, V> ScalarType for HashMap<K, V>
where
T: OutputType + InputType,
K: ToString + FromStr + Eq + Hash + Sync + Send,
K::Err: Display,
V: OutputType + InputType,
{
fn parse(value: Value) -> InputValueResult<Self> {
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::<Result<_, _>>()
.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)
}