diff --git a/src/scalars/datetime.rs b/src/scalars/datetime.rs index 31de70f7..855970c8 100644 --- a/src/scalars/datetime.rs +++ b/src/scalars/datetime.rs @@ -1,15 +1,32 @@ use crate::{InputValueError, InputValueResult, ScalarType, Value}; use async_graphql_derive::Scalar; -use chrono::{DateTime, FixedOffset, Utc}; +use chrono::{DateTime, FixedOffset, Local, Utc}; /// Implement the DateTime scalar /// /// The input/output is a string in RFC3339 format. -#[Scalar(internal, name = "DateTimeFixedOffset")] +#[Scalar(internal, name = "DateTime")] impl ScalarType for DateTime { fn parse(value: Value) -> InputValueResult { match &value { - Value::String(s) => Ok(DateTime::parse_from_rfc3339(s)?), + Value::String(s) => Ok(s.parse::>()?), + _ => Err(InputValueError::ExpectedType(value)), + } + } + + fn to_value(&self) -> Value { + Value::String(self.to_rfc3339()) + } +} + +/// Implement the DateTime scalar +/// +/// The input/output is a string in RFC3339 format. +#[Scalar(internal, name = "DateTime")] +impl ScalarType for DateTime { + fn parse(value: Value) -> InputValueResult { + match &value { + Value::String(s) => Ok(s.parse::>()?), _ => Err(InputValueError::ExpectedType(value)), } } @@ -22,7 +39,7 @@ impl ScalarType for DateTime { /// Implement the DateTime scalar /// /// The input/output is a string in RFC3339 format. -#[Scalar(internal, name = "DateTimeUtc")] +#[Scalar(internal, name = "DateTime")] impl ScalarType for DateTime { fn parse(value: Value) -> InputValueResult { match &value { diff --git a/src/scalars/floats.rs b/src/scalars/floats.rs index 04adacc1..1aae5207 100644 --- a/src/scalars/floats.rs +++ b/src/scalars/floats.rs @@ -1,35 +1,52 @@ use crate::{InputValueError, InputValueResult, ScalarType, Value}; use async_graphql_derive::Scalar; -macro_rules! float_scalar { - ($($ty:ty),*) => { - $( - /// The `Float` scalar type represents signed double-precision fractional values as specified by [IEEE 754](https://en.wikipedia.org/wiki/IEEE_floating_point). - #[Scalar(internal, name = "Float")] - impl ScalarType for $ty { - fn parse(value: Value) -> InputValueResult { - match value { - Value::Number(n) => Ok(n - .as_f64() - .ok_or_else(|| InputValueError::from("Invalid number"))? - as Self), - _ => Err(InputValueError::ExpectedType(value)), - } - } - - fn is_valid(value: &Value) -> bool { - match value { - Value::Number(_) => true, - _ => false, - } - } - - fn to_value(&self) -> Value { - Value::Number(serde_json::Number::from_f64(*self as f64).unwrap()) - } +/// The `Float` scalar type represents signed double-precision fractional values as specified by [IEEE 754](https://en.wikipedia.org/wiki/IEEE_floating_point). +#[Scalar(internal, name = "Float")] +impl ScalarType for f32 { + fn parse(value: Value) -> InputValueResult { + match value { + Value::Number(n) => Ok(n + .as_f64() + .ok_or_else(|| InputValueError::from("Invalid number"))? + as Self), + _ => Err(InputValueError::ExpectedType(value)), } - )* + } + + fn is_valid(value: &Value) -> bool { + match value { + Value::Number(_) => true, + _ => false, + } + } + + fn to_value(&self) -> Value { + Value::Number(serde_json::Number::from_f64(*self as f64).unwrap()) } } -float_scalar!(f32, f64); +/// The `Float` scalar type represents signed double-precision fractional values as specified by [IEEE 754](https://en.wikipedia.org/wiki/IEEE_floating_point). +#[Scalar(internal, name = "Float")] +impl ScalarType for f64 { + fn parse(value: Value) -> InputValueResult { + match value { + Value::Number(n) => Ok(n + .as_f64() + .ok_or_else(|| InputValueError::from("Invalid number"))? + as Self), + _ => Err(InputValueError::ExpectedType(value)), + } + } + + fn is_valid(value: &Value) -> bool { + match value { + Value::Number(_) => true, + _ => false, + } + } + + fn to_value(&self) -> Value { + Value::Number(serde_json::Number::from_f64(*self as f64).unwrap()) + } +} diff --git a/src/scalars/integers.rs b/src/scalars/integers.rs index 13d2dc61..e7a32c93 100644 --- a/src/scalars/integers.rs +++ b/src/scalars/integers.rs @@ -1,85 +1,274 @@ use crate::{InputValueError, InputValueResult, ScalarType, Value}; use async_graphql_derive::Scalar; -macro_rules! int_scalar { - ($($ty:ty),*) => { - $( - /// The `Int` scalar type represents non-fractional whole numeric values. - #[Scalar(internal, name = "Int")] - impl ScalarType for $ty { - fn parse(value: Value) -> InputValueResult { - match value { - Value::Number(n) => { - let n = n - .as_i64() - .ok_or_else(|| InputValueError::from("Invalid number"))?; - if n < Self::MIN as i64 || n > Self::MAX as i64 { - return Err(InputValueError::from(format!( - "Only integers from {} to {} are accepted.", - Self::MIN, - Self::MAX - ))); - } - Ok(n as Self) - } - _ => Err(InputValueError::ExpectedType(value)), +/// The `Int` scalar type represents non-fractional whole numeric values. +#[Scalar(internal, name = "Int")] +impl ScalarType for i8 { + fn parse(value: Value) -> InputValueResult { + match value { + Value::Number(n) => { + let n = n + .as_i64() + .ok_or_else(|| InputValueError::from("Invalid number"))?; + if n < Self::MIN as i64 || n > Self::MAX as i64 { + return Err(InputValueError::from(format!( + "Only integers from {} to {} are accepted.", + Self::MIN, + Self::MAX + ))); } + Ok(n as Self) } - - fn is_valid(value: &Value) -> bool { - match value { - Value::Number(n) if n.is_i64() => true, - _ => false, - } - } - - fn to_value(&self) -> Value { - Value::Number(serde_json::Number::from(*self as i64)) - } + _ => Err(InputValueError::ExpectedType(value)), } - )* - }; + } + + fn is_valid(value: &Value) -> bool { + match value { + Value::Number(n) if n.is_i64() => true, + _ => false, + } + } + + fn to_value(&self) -> Value { + Value::Number(serde_json::Number::from(*self as i64)) + } } -macro_rules! uint_scalar { - ($($ty:ty),*) => { - $( - /// The `Int` scalar type represents non-fractional whole numeric values. - #[Scalar(internal, name = "Int")] - impl ScalarType for $ty { - fn parse(value: Value) -> InputValueResult { - match value { - Value::Number(n) => { - let n = n - .as_u64() - .ok_or_else(|| InputValueError::from("Invalid number"))?; - if n > Self::MAX as u64 { - return Err(InputValueError::from(format!( - "Only integers from {} to {} are accepted.", - 0, - Self::MAX - ))); - } - Ok(n as Self) - } - _ => Err(InputValueError::ExpectedType(value)), +/// The `Int` scalar type represents non-fractional whole numeric values. +#[Scalar(internal, name = "Int")] +impl ScalarType for i16 { + fn parse(value: Value) -> InputValueResult { + match value { + Value::Number(n) => { + let n = n + .as_i64() + .ok_or_else(|| InputValueError::from("Invalid number"))?; + if n < Self::MIN as i64 || n > Self::MAX as i64 { + return Err(InputValueError::from(format!( + "Only integers from {} to {} are accepted.", + Self::MIN, + Self::MAX + ))); } + Ok(n as Self) } - - fn is_valid(value: &Value) -> bool { - match value { - Value::Number(n) if n.is_u64() => true, - _ => false, - } - } - - fn to_value(&self) -> Value { - Value::Number(serde_json::Number::from(*self as u64)) - } + _ => Err(InputValueError::ExpectedType(value)), } - )* - }; + } + + fn is_valid(value: &Value) -> bool { + match value { + Value::Number(n) if n.is_i64() => true, + _ => false, + } + } + + fn to_value(&self) -> Value { + Value::Number(serde_json::Number::from(*self as i64)) + } } -int_scalar!(i8, i16, i32, i64); -uint_scalar!(u8, u16, u32, u64); +/// The `Int` scalar type represents non-fractional whole numeric values. +#[Scalar(internal, name = "Int")] +impl ScalarType for i32 { + fn parse(value: Value) -> InputValueResult { + match value { + Value::Number(n) => { + let n = n + .as_i64() + .ok_or_else(|| InputValueError::from("Invalid number"))?; + if n < Self::MIN as i64 || n > Self::MAX as i64 { + return Err(InputValueError::from(format!( + "Only integers from {} to {} are accepted.", + Self::MIN, + Self::MAX + ))); + } + Ok(n as Self) + } + _ => Err(InputValueError::ExpectedType(value)), + } + } + + fn is_valid(value: &Value) -> bool { + match value { + Value::Number(n) if n.is_i64() => true, + _ => false, + } + } + + fn to_value(&self) -> Value { + Value::Number(serde_json::Number::from(*self as i64)) + } +} + +/// The `Int` scalar type represents non-fractional whole numeric values. +#[Scalar(internal, name = "Int")] +impl ScalarType for i64 { + fn parse(value: Value) -> InputValueResult { + match value { + Value::Number(n) => { + let n = n + .as_i64() + .ok_or_else(|| InputValueError::from("Invalid number"))?; + if n < Self::MIN as i64 || n > Self::MAX as i64 { + return Err(InputValueError::from(format!( + "Only integers from {} to {} are accepted.", + Self::MIN, + Self::MAX + ))); + } + Ok(n as Self) + } + _ => Err(InputValueError::ExpectedType(value)), + } + } + + fn is_valid(value: &Value) -> bool { + match value { + Value::Number(n) if n.is_i64() => true, + _ => false, + } + } + + fn to_value(&self) -> Value { + Value::Number(serde_json::Number::from(*self as i64)) + } +} + +/// The `Int` scalar type represents non-fractional whole numeric values. +#[Scalar(internal, name = "Int")] +impl ScalarType for u8 { + fn parse(value: Value) -> InputValueResult { + match value { + Value::Number(n) => { + let n = n + .as_u64() + .ok_or_else(|| InputValueError::from("Invalid number"))?; + if n > Self::MAX as u64 { + return Err(InputValueError::from(format!( + "Only integers from {} to {} are accepted.", + 0, + Self::MAX + ))); + } + Ok(n as Self) + } + _ => Err(InputValueError::ExpectedType(value)), + } + } + + fn is_valid(value: &Value) -> bool { + match value { + Value::Number(n) if n.is_u64() => true, + _ => false, + } + } + + fn to_value(&self) -> Value { + Value::Number(serde_json::Number::from(*self as u64)) + } +} + +/// The `Int` scalar type represents non-fractional whole numeric values. +#[Scalar(internal, name = "Int")] +impl ScalarType for u16 { + fn parse(value: Value) -> InputValueResult { + match value { + Value::Number(n) => { + let n = n + .as_u64() + .ok_or_else(|| InputValueError::from("Invalid number"))?; + if n > Self::MAX as u64 { + return Err(InputValueError::from(format!( + "Only integers from {} to {} are accepted.", + 0, + Self::MAX + ))); + } + Ok(n as Self) + } + _ => Err(InputValueError::ExpectedType(value)), + } + } + + fn is_valid(value: &Value) -> bool { + match value { + Value::Number(n) if n.is_u64() => true, + _ => false, + } + } + + fn to_value(&self) -> Value { + Value::Number(serde_json::Number::from(*self as u64)) + } +} + +/// The `Int` scalar type represents non-fractional whole numeric values. +#[Scalar(internal, name = "Int")] +impl ScalarType for u32 { + fn parse(value: Value) -> InputValueResult { + match value { + Value::Number(n) => { + let n = n + .as_u64() + .ok_or_else(|| InputValueError::from("Invalid number"))?; + if n > Self::MAX as u64 { + return Err(InputValueError::from(format!( + "Only integers from {} to {} are accepted.", + 0, + Self::MAX + ))); + } + Ok(n as Self) + } + _ => Err(InputValueError::ExpectedType(value)), + } + } + + fn is_valid(value: &Value) -> bool { + match value { + Value::Number(n) if n.is_u64() => true, + _ => false, + } + } + + fn to_value(&self) -> Value { + Value::Number(serde_json::Number::from(*self as u64)) + } +} + +/// The `Int` scalar type represents non-fractional whole numeric values. +#[Scalar(internal, name = "Int")] +impl ScalarType for u64 { + fn parse(value: Value) -> InputValueResult { + match value { + Value::Number(n) => { + let n = n + .as_u64() + .ok_or_else(|| InputValueError::from("Invalid number"))?; + if n > Self::MAX as u64 { + return Err(InputValueError::from(format!( + "Only integers from {} to {} are accepted.", + 0, + Self::MAX + ))); + } + Ok(n as Self) + } + _ => Err(InputValueError::ExpectedType(value)), + } + } + + fn is_valid(value: &Value) -> bool { + match value { + Value::Number(n) if n.is_u64() => true, + _ => false, + } + } + + fn to_value(&self) -> Value { + Value::Number(serde_json::Number::from(*self as u64)) + } +} diff --git a/src/scalars/mod.rs b/src/scalars/mod.rs index 2cf2e585..d6081810 100644 --- a/src/scalars/mod.rs +++ b/src/scalars/mod.rs @@ -25,7 +25,7 @@ mod tests { use super::ID; use crate::Type; use bson::oid::ObjectId; - use chrono::{DateTime, FixedOffset, NaiveDate, NaiveTime, Utc}; + use chrono::{DateTime, FixedOffset, Local, NaiveDate, NaiveTime, Utc}; use uuid::Uuid; #[test] @@ -54,19 +54,22 @@ mod tests { assert_eq!(::type_name(), "NaiveTime"); assert_eq!(::qualified_type_name(), "NaiveTime!"); - assert_eq!( as Type>::type_name(), "DateTimeUtc"); + assert_eq!( as Type>::type_name(), "DateTime"); assert_eq!( as Type>::qualified_type_name(), - "DateTimeUtc!" + "DateTime!" ); + assert_eq!( as Type>::type_name(), "DateTime"); assert_eq!( - as Type>::type_name(), - "DateTimeFixedOffset" + as Type>::qualified_type_name(), + "DateTime!" ); + + assert_eq!( as Type>::type_name(), "DateTime"); assert_eq!( as Type>::qualified_type_name(), - "DateTimeFixedOffset!" + "DateTime!" ); assert_eq!(::type_name(), "UUID");