Replace Value::Int and Value::Float with Value::Number.
This commit is contained in:
parent
01233a9c28
commit
2dc61013be
|
@ -6,7 +6,6 @@ use crate::{Error, Result};
|
||||||
use pest::iterators::Pair;
|
use pest::iterators::Pair;
|
||||||
use pest::Parser;
|
use pest::Parser;
|
||||||
use std::collections::BTreeMap;
|
use std::collections::BTreeMap;
|
||||||
use std::num::{ParseFloatError, ParseIntError};
|
|
||||||
|
|
||||||
#[derive(Parser)]
|
#[derive(Parser)]
|
||||||
#[grammar = "query.pest"]
|
#[grammar = "query.pest"]
|
||||||
|
@ -242,24 +241,17 @@ fn parse_value2(pair: Pair<Rule>, pc: &mut PositionCalculator) -> Result<Value>
|
||||||
Rule::object => parse_object_value(pair, pc)?,
|
Rule::object => parse_object_value(pair, pc)?,
|
||||||
Rule::array => parse_array_value(pair, pc)?,
|
Rule::array => parse_array_value(pair, pc)?,
|
||||||
Rule::variable => Value::Variable(parse_variable(pair, pc)?.into_inner()),
|
Rule::variable => Value::Variable(parse_variable(pair, pc)?.into_inner()),
|
||||||
Rule::float => {
|
Rule::float | Rule::int => {
|
||||||
let pos = pc.step(&pair);
|
let pos = pc.step(&pair);
|
||||||
Value::Float(
|
Value::Number(
|
||||||
pair.as_str()
|
pair.as_str()
|
||||||
.parse()
|
.parse()
|
||||||
.map_err(|err: ParseFloatError| Error {
|
.map_err(|err: serde_json::Error| Error {
|
||||||
pos,
|
pos,
|
||||||
message: err.to_string(),
|
message: err.to_string(),
|
||||||
})?,
|
})?,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
Rule::int => {
|
|
||||||
let pos = pc.step(&pair);
|
|
||||||
Value::Int(pair.as_str().parse().map_err(|err: ParseIntError| Error {
|
|
||||||
pos,
|
|
||||||
message: err.to_string(),
|
|
||||||
})?)
|
|
||||||
}
|
|
||||||
Rule::string => Value::String({
|
Rule::string => Value::String({
|
||||||
let pos = pc.step(&pair);
|
let pos = pc.step(&pair);
|
||||||
unquote_string(pair.as_str(), pos)?
|
unquote_string(pair.as_str(), pos)?
|
||||||
|
@ -531,18 +523,8 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_parse_overflowing_int() {
|
fn test_parse_overflowing_int() {
|
||||||
let query_ok = format!("mutation {{ add(big: {}) }} ", std::i32::MAX);
|
let query_ok = format!("mutation {{ add(big: {}) }} ", std::i32::MAX);
|
||||||
let query_overflow = format!("mutation {{ add(big: {}0) }} ", std::i32::MAX);
|
let query_overflow = format!("mutation {{ add(big: {}0000) }} ", std::i32::MAX);
|
||||||
assert!(parse_query(query_ok).is_ok());
|
assert!(parse_query(query_ok).is_ok());
|
||||||
assert!(parse_query(query_overflow).is_err());
|
|
||||||
}
|
|
||||||
|
|
||||||
#[test]
|
|
||||||
fn test_parse_overflowing_float() {
|
|
||||||
let query_ok = format!("mutation {{ add(big: {:.1}) }} ", std::f64::MAX);
|
|
||||||
let query_overflow = format!("mutation {{ add(big: 1{:.1}) }} ", std::f64::MAX);
|
|
||||||
assert!(parse_query(query_ok).is_ok());
|
|
||||||
|
|
||||||
// NOTE: This is also ok since overflow gets parsed to infinity.
|
|
||||||
assert!(parse_query(query_overflow).is_ok());
|
assert!(parse_query(query_overflow).is_ok());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,8 +33,7 @@ impl Clone for UploadValue {
|
||||||
pub enum Value {
|
pub enum Value {
|
||||||
Null,
|
Null,
|
||||||
Variable(String),
|
Variable(String),
|
||||||
Int(i32),
|
Number(serde_json::Number),
|
||||||
Float(f64),
|
|
||||||
String(String),
|
String(String),
|
||||||
Boolean(bool),
|
Boolean(bool),
|
||||||
Enum(String),
|
Enum(String),
|
||||||
|
@ -51,8 +50,7 @@ impl serde::Serialize for Value {
|
||||||
match self {
|
match self {
|
||||||
Value::Null => serializer.serialize_none(),
|
Value::Null => serializer.serialize_none(),
|
||||||
Value::Variable(variable) => serializer.serialize_str(&format!("${}", variable)),
|
Value::Variable(variable) => serializer.serialize_str(&format!("${}", variable)),
|
||||||
Value::Int(value) => serializer.serialize_i32(*value),
|
Value::Number(value) => value.serialize(serializer),
|
||||||
Value::Float(value) => serializer.serialize_f64(*value),
|
|
||||||
Value::String(value) => serializer.serialize_str(value),
|
Value::String(value) => serializer.serialize_str(value),
|
||||||
Value::Boolean(value) => serializer.serialize_bool(*value),
|
Value::Boolean(value) => serializer.serialize_bool(*value),
|
||||||
Value::Enum(value) => serializer.serialize_str(value),
|
Value::Enum(value) => serializer.serialize_str(value),
|
||||||
|
@ -87,8 +85,7 @@ impl PartialEq for Value {
|
||||||
|
|
||||||
match (self, other) {
|
match (self, other) {
|
||||||
(Variable(a), Variable(b)) => a.eq(b),
|
(Variable(a), Variable(b)) => a.eq(b),
|
||||||
(Int(a), Int(b)) => a.eq(b),
|
(Number(a), Number(b)) => a.eq(b),
|
||||||
(Float(a), Float(b)) => a.eq(b),
|
|
||||||
(String(a), String(b)) => a.eq(b),
|
(String(a), String(b)) => a.eq(b),
|
||||||
(Boolean(a), Boolean(b)) => a.eq(b),
|
(Boolean(a), Boolean(b)) => a.eq(b),
|
||||||
(Null, Null) => true,
|
(Null, Null) => true,
|
||||||
|
@ -145,8 +142,7 @@ impl fmt::Display for Value {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||||
match self {
|
match self {
|
||||||
Value::Variable(name) => write!(f, "${}", name),
|
Value::Variable(name) => write!(f, "${}", name),
|
||||||
Value::Int(num) => write!(f, "{}", *num),
|
Value::Number(num) => write!(f, "{}", *num),
|
||||||
Value::Float(val) => write!(f, "{}", *val),
|
|
||||||
Value::String(ref val) => write_quoted(val, f),
|
Value::String(ref val) => write_quoted(val, f),
|
||||||
Value::Boolean(true) => write!(f, "true"),
|
Value::Boolean(true) => write!(f, "true"),
|
||||||
Value::Boolean(false) => write!(f, "false"),
|
Value::Boolean(false) => write!(f, "false"),
|
||||||
|
@ -188,8 +184,7 @@ impl From<Value> for serde_json::Value {
|
||||||
match value {
|
match value {
|
||||||
Value::Null => serde_json::Value::Null,
|
Value::Null => serde_json::Value::Null,
|
||||||
Value::Variable(name) => name.into(),
|
Value::Variable(name) => name.into(),
|
||||||
Value::Int(n) => n.into(),
|
Value::Number(n) => serde_json::Value::Number(n),
|
||||||
Value::Float(n) => n.into(),
|
|
||||||
Value::String(s) => s.into(),
|
Value::String(s) => s.into(),
|
||||||
Value::Boolean(v) => v.into(),
|
Value::Boolean(v) => v.into(),
|
||||||
Value::Enum(e) => e.into(),
|
Value::Enum(e) => e.into(),
|
||||||
|
@ -213,8 +208,7 @@ impl From<serde_json::Value> for Value {
|
||||||
match value {
|
match value {
|
||||||
serde_json::Value::Null => Value::Null,
|
serde_json::Value::Null => Value::Null,
|
||||||
serde_json::Value::Bool(n) => Value::Boolean(n),
|
serde_json::Value::Bool(n) => Value::Boolean(n),
|
||||||
serde_json::Value::Number(n) if n.is_f64() => Value::Float(n.as_f64().unwrap()),
|
serde_json::Value::Number(n) => Value::Number(n),
|
||||||
serde_json::Value::Number(n) => Value::Int(n.as_i64().unwrap() as i32),
|
|
||||||
serde_json::Value::String(s) => Value::String(s),
|
serde_json::Value::String(s) => Value::String(s),
|
||||||
serde_json::Value::Array(ls) => Value::List(ls.into_iter().map(Into::into).collect()),
|
serde_json::Value::Array(ls) => Value::List(ls.into_iter().map(Into::into).collect()),
|
||||||
serde_json::Value::Object(obj) => Value::Object(
|
serde_json::Value::Object(obj) => Value::Object(
|
||||||
|
|
|
@ -15,12 +15,12 @@ struct StringNumber(i64);
|
||||||
#[Scalar]
|
#[Scalar]
|
||||||
impl ScalarType for StringNumber {
|
impl ScalarType for StringNumber {
|
||||||
fn parse(value: Value) -> InputValueResult<Self> {
|
fn parse(value: Value) -> InputValueResult<Self> {
|
||||||
if let Value::String(value) = value {
|
if let Value::String(value) = &value {
|
||||||
// Parse the integer value
|
// Parse the integer value
|
||||||
value.parse().map(StringNumber)?
|
Ok(value.parse().map(StringNumber)?)
|
||||||
} else {
|
} else {
|
||||||
// If the type does not match
|
// If the type does not match
|
||||||
InputValueError::ExpectedType
|
Err(InputValueError::ExpectedType(value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,12 +15,12 @@ struct StringNumber(i64);
|
||||||
#[Scalar]
|
#[Scalar]
|
||||||
impl ScalarType for StringNumber {
|
impl ScalarType for StringNumber {
|
||||||
fn parse(value: Value) -> InputValueResult<Self> {
|
fn parse(value: Value) -> InputValueResult<Self> {
|
||||||
if let Value::String(value) = value {
|
if let Value::String(value) = &value {
|
||||||
// 解析整数
|
// 解析整数
|
||||||
value.parse().map(StringNumber)?
|
Ok(value.parse().map(StringNumber)?)
|
||||||
} else {
|
} else {
|
||||||
// 类型不匹配
|
// 类型不匹配
|
||||||
InputValueError::ExpectedType
|
Err(InputValueError::ExpectedType(value))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
11
src/base.rs
11
src/base.rs
|
@ -116,15 +116,16 @@ pub trait InputObjectType: InputValueType {}
|
||||||
/// #[Scalar]
|
/// #[Scalar]
|
||||||
/// impl ScalarType for MyInt {
|
/// impl ScalarType for MyInt {
|
||||||
/// fn parse(value: Value) -> InputValueResult<Self> {
|
/// fn parse(value: Value) -> InputValueResult<Self> {
|
||||||
/// if let Value::Int(n) = value {
|
/// if let Value::Number(n) = &value {
|
||||||
/// Ok(MyInt(n as i32))
|
/// if let Some(n) = n.as_i64() {
|
||||||
/// } else {
|
/// return Ok(MyInt(n as i32));
|
||||||
/// Err(InputValueError::ExpectedType(value))
|
/// }
|
||||||
/// }
|
/// }
|
||||||
|
/// Err(InputValueError::ExpectedType(value))
|
||||||
/// }
|
/// }
|
||||||
///
|
///
|
||||||
/// fn to_value(&self) -> Value {
|
/// fn to_value(&self) -> Value {
|
||||||
/// Value::Int(self.0)
|
/// Value::Number(self.0.into())
|
||||||
/// }
|
/// }
|
||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
|
@ -46,7 +46,11 @@ mod test {
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_conversion_ok() {
|
fn test_conversion_ok() {
|
||||||
let value = Value::List(vec![Value::Int(1.into()), Value::Float(2.0), Value::Null]);
|
let value = Value::List(vec![
|
||||||
|
Value::Number(1.into()),
|
||||||
|
Value::Boolean(true),
|
||||||
|
Value::Null,
|
||||||
|
]);
|
||||||
let expected = Any(value.clone());
|
let expected = Any(value.clone());
|
||||||
let output: Any = value.into();
|
let output: Any = value.into();
|
||||||
assert_eq!(output, expected);
|
assert_eq!(output, expected);
|
||||||
|
|
|
@ -1,48 +1,35 @@
|
||||||
use crate::{InputValueError, InputValueResult, ScalarType, Value};
|
use crate::{InputValueError, InputValueResult, ScalarType, Value};
|
||||||
use async_graphql_derive::Scalar;
|
use async_graphql_derive::Scalar;
|
||||||
|
|
||||||
/// The `Float` scalar type represents signed double-precision fractional values as specified by [IEEE 754](https://en.wikipedia.org/wiki/IEEE_floating_point).
|
macro_rules! float_scalar {
|
||||||
#[Scalar(internal, name = "Float")]
|
($($ty:ty),*) => {
|
||||||
impl ScalarType for f32 {
|
$(
|
||||||
fn parse(value: Value) -> InputValueResult<Self> {
|
/// The `Float` scalar type represents signed double-precision fractional values as specified by [IEEE 754](https://en.wikipedia.org/wiki/IEEE_floating_point).
|
||||||
match value {
|
#[Scalar(internal, name = "Float")]
|
||||||
Value::Int(n) => Ok(n as Self),
|
impl ScalarType for $ty {
|
||||||
Value::Float(n) => Ok(n as Self),
|
fn parse(value: Value) -> InputValueResult<Self> {
|
||||||
_ => Err(InputValueError::ExpectedType(value)),
|
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 {
|
fn is_valid(value: &Value) -> bool {
|
||||||
match value {
|
match value {
|
||||||
Value::Int(_) | Value::Float(_) => true,
|
Value::Number(_) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_value(&self) -> Value {
|
fn to_value(&self) -> Value {
|
||||||
Value::Float(*self as f64)
|
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).
|
float_scalar!(f32, f64);
|
||||||
#[Scalar(internal, name = "Float")]
|
|
||||||
impl ScalarType for f64 {
|
|
||||||
fn parse(value: Value) -> InputValueResult<Self> {
|
|
||||||
match value {
|
|
||||||
Value::Int(n) => Ok(n as Self),
|
|
||||||
Value::Float(n) => Ok(n as Self),
|
|
||||||
_ => Err(InputValueError::ExpectedType(value)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_valid(value: &Value) -> bool {
|
|
||||||
match value {
|
|
||||||
Value::Int(_) | Value::Float(_) => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_value(&self) -> Value {
|
|
||||||
Value::Float(*self as f64)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -77,7 +77,7 @@ impl PartialEq<&str> for ID {
|
||||||
impl ScalarType for ID {
|
impl ScalarType for ID {
|
||||||
fn parse(value: Value) -> InputValueResult<Self> {
|
fn parse(value: Value) -> InputValueResult<Self> {
|
||||||
match value {
|
match value {
|
||||||
Value::Int(n) => Ok(ID(n.to_string())),
|
Value::Number(n) if n.is_i64() => Ok(ID(n.to_string())),
|
||||||
Value::String(s) => Ok(ID(s)),
|
Value::String(s) => Ok(ID(s)),
|
||||||
_ => Err(InputValueError::ExpectedType(value)),
|
_ => Err(InputValueError::ExpectedType(value)),
|
||||||
}
|
}
|
||||||
|
@ -85,7 +85,8 @@ impl ScalarType for ID {
|
||||||
|
|
||||||
fn is_valid(value: &Value) -> bool {
|
fn is_valid(value: &Value) -> bool {
|
||||||
match value {
|
match value {
|
||||||
Value::Int(_) | Value::String(_) => true,
|
Value::Number(n) if n.is_i64() => true,
|
||||||
|
Value::String(_) => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,191 +1,85 @@
|
||||||
use crate::{InputValueError, InputValueResult, ScalarType, Value};
|
use crate::{InputValueError, InputValueResult, ScalarType, Value};
|
||||||
use async_graphql_derive::Scalar;
|
use async_graphql_derive::Scalar;
|
||||||
|
|
||||||
/// The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.
|
macro_rules! int_scalar {
|
||||||
#[Scalar(internal, name = "Int")]
|
($($ty:ty),*) => {
|
||||||
impl ScalarType for i8 {
|
$(
|
||||||
fn parse(value: Value) -> InputValueResult<Self> {
|
/// The `Int` scalar type represents non-fractional whole numeric values.
|
||||||
match value {
|
#[Scalar(internal, name = "Int")]
|
||||||
Value::Int(n) => Ok(n as Self),
|
impl ScalarType for $ty {
|
||||||
_ => Err(InputValueError::ExpectedType(value)),
|
fn parse(value: Value) -> InputValueResult<Self> {
|
||||||
}
|
match value {
|
||||||
}
|
Value::Number(n) => {
|
||||||
|
let n = n
|
||||||
fn is_valid(value: &Value) -> bool {
|
.as_i64()
|
||||||
match value {
|
.ok_or_else(|| InputValueError::from("Invalid number"))?;
|
||||||
Value::Int(_) => true,
|
if n < Self::MIN as i64 || n > Self::MAX as i64 {
|
||||||
_ => false,
|
return Err(InputValueError::from(format!(
|
||||||
}
|
"Only integers from {} to {} are accepted.",
|
||||||
}
|
Self::MIN,
|
||||||
|
Self::MAX
|
||||||
fn to_value(&self) -> Value {
|
)));
|
||||||
Value::Int(*self as i32)
|
}
|
||||||
}
|
Ok(n as Self)
|
||||||
}
|
}
|
||||||
|
_ => Err(InputValueError::ExpectedType(value)),
|
||||||
/// The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.
|
|
||||||
#[Scalar(internal, name = "Int")]
|
|
||||||
impl ScalarType for i16 {
|
|
||||||
fn parse(value: Value) -> InputValueResult<Self> {
|
|
||||||
match value {
|
|
||||||
Value::Int(n) => Ok(n as Self),
|
|
||||||
_ => Err(InputValueError::ExpectedType(value)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_valid(value: &Value) -> bool {
|
|
||||||
match value {
|
|
||||||
Value::Int(_) => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_value(&self) -> Value {
|
|
||||||
Value::Int(*self as i32)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.
|
|
||||||
#[Scalar(internal, name = "Int")]
|
|
||||||
impl ScalarType for i32 {
|
|
||||||
fn parse(value: Value) -> InputValueResult<Self> {
|
|
||||||
match value {
|
|
||||||
Value::Int(n) => Ok(n as Self),
|
|
||||||
_ => Err(InputValueError::ExpectedType(value)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_valid(value: &Value) -> bool {
|
|
||||||
match value {
|
|
||||||
Value::Int(_) => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_value(&self) -> Value {
|
|
||||||
Value::Int(*self as i32)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.
|
|
||||||
#[Scalar(internal, name = "Int")]
|
|
||||||
impl ScalarType for u8 {
|
|
||||||
fn parse(value: Value) -> InputValueResult<Self> {
|
|
||||||
match value {
|
|
||||||
Value::Int(n) => Ok(n as Self),
|
|
||||||
_ => Err(InputValueError::ExpectedType(value)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_valid(value: &Value) -> bool {
|
|
||||||
match value {
|
|
||||||
Value::Int(_) => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_value(&self) -> Value {
|
|
||||||
Value::Int(*self as i32)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The `Int` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^31) and 2^31 - 1.
|
|
||||||
#[Scalar(internal, name = "Int")]
|
|
||||||
impl ScalarType for u16 {
|
|
||||||
fn parse(value: Value) -> InputValueResult<Self> {
|
|
||||||
match value {
|
|
||||||
Value::Int(n) => Ok(n as Self),
|
|
||||||
_ => Err(InputValueError::ExpectedType(value)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_valid(value: &Value) -> bool {
|
|
||||||
match value {
|
|
||||||
Value::Int(_) => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_value(&self) -> Value {
|
|
||||||
Value::Int(*self as i32)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The `Int64` scalar type represents non-fractional signed whole numeric values. Int can represent values between -(2^64) and 2^64 - 1.
|
|
||||||
#[Scalar(internal, name = "Int64")]
|
|
||||||
impl ScalarType for i64 {
|
|
||||||
fn parse(value: Value) -> InputValueResult<Self> {
|
|
||||||
match value {
|
|
||||||
Value::Int(n) => Ok(n as Self),
|
|
||||||
Value::String(s) => Ok(s.parse()?),
|
|
||||||
_ => Err(InputValueError::ExpectedType(value)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_valid(value: &Value) -> bool {
|
|
||||||
match value {
|
|
||||||
Value::Int(_) | Value::String(_) => true,
|
|
||||||
_ => false,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_value(&self) -> Value {
|
|
||||||
Value::String(self.to_string())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The `UInt64` scalar type represents non-fractional signed whole numeric values. Int can represent values between 0 and 2^64.
|
|
||||||
#[Scalar(internal, name = "UInt64")]
|
|
||||||
impl ScalarType for u32 {
|
|
||||||
fn parse(value: Value) -> InputValueResult<Self> {
|
|
||||||
match value {
|
|
||||||
Value::Int(n) => {
|
|
||||||
if n < 0 {
|
|
||||||
return Err(InputValueError::Custom("Expect a positive number.".into()));
|
|
||||||
}
|
}
|
||||||
Ok(n as Self)
|
|
||||||
}
|
}
|
||||||
Value::String(s) => Ok(s.parse()?),
|
|
||||||
_ => Err(InputValueError::ExpectedType(value)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_valid(value: &Value) -> bool {
|
fn is_valid(value: &Value) -> bool {
|
||||||
match value {
|
match value {
|
||||||
Value::Int(_) | Value::String(_) => true,
|
Value::Number(n) if n.is_i64() => true,
|
||||||
_ => false,
|
_ => false,
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn to_value(&self) -> Value {
|
|
||||||
Value::String(self.to_string())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// The `UInt64` scalar type represents non-fractional signed whole numeric values. Int can represent values between 0 and 2^64.
|
|
||||||
#[Scalar(internal, name = "UInt64")]
|
|
||||||
impl ScalarType for u64 {
|
|
||||||
fn parse(value: Value) -> InputValueResult<Self> {
|
|
||||||
match value {
|
|
||||||
Value::Int(n) => {
|
|
||||||
if n < 0 {
|
|
||||||
return Err(InputValueError::Custom("Expect a positive number.".into()));
|
|
||||||
}
|
}
|
||||||
Ok(n as Self)
|
|
||||||
}
|
}
|
||||||
Value::String(s) => Ok(s.parse()?),
|
|
||||||
_ => Err(InputValueError::ExpectedType(value)),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn is_valid(value: &Value) -> bool {
|
fn to_value(&self) -> Value {
|
||||||
match value {
|
Value::Number(serde_json::Number::from(*self as i64))
|
||||||
Value::Int(_) | Value::String(_) => true,
|
}
|
||||||
_ => false,
|
|
||||||
}
|
}
|
||||||
}
|
)*
|
||||||
|
};
|
||||||
fn to_value(&self) -> Value {
|
|
||||||
Value::String(self.to_string())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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<Self> {
|
||||||
|
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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)*
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
int_scalar!(i8, i16, i32, i64);
|
||||||
|
uint_scalar!(u8, u16, u32, u64);
|
||||||
|
|
|
@ -4,72 +4,69 @@ use crate::Value;
|
||||||
/// Integer range validator
|
/// Integer range validator
|
||||||
pub struct IntRange {
|
pub struct IntRange {
|
||||||
/// Minimum value, including this value.
|
/// Minimum value, including this value.
|
||||||
pub min: i32,
|
pub min: i64,
|
||||||
|
|
||||||
/// Maximum value, including this value.
|
/// Maximum value, including this value.
|
||||||
pub max: i32,
|
pub max: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InputValueValidator for IntRange {
|
impl InputValueValidator for IntRange {
|
||||||
fn is_valid(&self, value: &Value) -> Option<String> {
|
fn is_valid(&self, value: &Value) -> Option<String> {
|
||||||
if let Value::Int(n) = value {
|
if let Value::Number(n) = value {
|
||||||
if *n < self.min || *n > self.max {
|
if let Some(n) = n.as_i64() {
|
||||||
Some(format!(
|
if n < self.min || n > self.max {
|
||||||
"the value is {}, must be between {} and {}",
|
return Some(format!(
|
||||||
*n, self.min, self.max
|
"the value is {}, must be between {} and {}",
|
||||||
))
|
n, self.min, self.max
|
||||||
} else {
|
));
|
||||||
None
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Integer less then validator
|
/// Integer less then validator
|
||||||
pub struct IntLessThan {
|
pub struct IntLessThan {
|
||||||
/// Less then this value.
|
/// Less then this value.
|
||||||
pub value: i32,
|
pub value: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InputValueValidator for IntLessThan {
|
impl InputValueValidator for IntLessThan {
|
||||||
fn is_valid(&self, value: &Value) -> Option<String> {
|
fn is_valid(&self, value: &Value) -> Option<String> {
|
||||||
if let Value::Int(n) = value {
|
if let Value::Number(n) = value {
|
||||||
if *n >= self.value {
|
if let Some(n) = n.as_i64() {
|
||||||
Some(format!(
|
if n >= self.value {
|
||||||
"the value is {}, must be less than {}",
|
return Some(format!(
|
||||||
*n, self.value
|
"the value is {}, must be less than {}",
|
||||||
))
|
n, self.value
|
||||||
} else {
|
));
|
||||||
None
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Integer greater then validator
|
/// Integer greater then validator
|
||||||
pub struct IntGreaterThan {
|
pub struct IntGreaterThan {
|
||||||
/// Greater then this value.
|
/// Greater then this value.
|
||||||
pub value: i32,
|
pub value: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InputValueValidator for IntGreaterThan {
|
impl InputValueValidator for IntGreaterThan {
|
||||||
fn is_valid(&self, value: &Value) -> Option<String> {
|
fn is_valid(&self, value: &Value) -> Option<String> {
|
||||||
if let Value::Int(n) = value {
|
if let Value::Number(n) = value {
|
||||||
if *n <= self.value {
|
if let Some(n) = n.as_i64() {
|
||||||
Some(format!(
|
if n <= self.value {
|
||||||
"the value is {}, must be greater than {}",
|
return Some(format!(
|
||||||
*n, self.value
|
"the value is {}, must be greater than {}",
|
||||||
))
|
n, self.value
|
||||||
} else {
|
));
|
||||||
None
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -78,37 +75,35 @@ pub struct IntNonZero {}
|
||||||
|
|
||||||
impl InputValueValidator for IntNonZero {
|
impl InputValueValidator for IntNonZero {
|
||||||
fn is_valid(&self, value: &Value) -> Option<String> {
|
fn is_valid(&self, value: &Value) -> Option<String> {
|
||||||
if let Value::Int(n) = value {
|
if let Value::Number(n) = value {
|
||||||
if *n == 0 {
|
if let Some(n) = n.as_i64() {
|
||||||
Some(format!("the value is {}, must be nonzero", *n,))
|
if n == 0 {
|
||||||
} else {
|
return Some(format!("the value is {}, must be nonzero", n));
|
||||||
None
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Integer equal validator
|
/// Integer equal validator
|
||||||
pub struct IntEqual {
|
pub struct IntEqual {
|
||||||
/// equal this value.
|
/// equal this value.
|
||||||
pub value: i32,
|
pub value: i64,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl InputValueValidator for IntEqual {
|
impl InputValueValidator for IntEqual {
|
||||||
fn is_valid(&self, value: &Value) -> Option<String> {
|
fn is_valid(&self, value: &Value) -> Option<String> {
|
||||||
if let Value::Int(n) = value {
|
if let Value::Number(n) = value {
|
||||||
if *n != self.value {
|
if let Some(n) = n.as_i64() {
|
||||||
Some(format!(
|
if n != self.value {
|
||||||
"the value is {}, must be equal to {}",
|
return Some(format!(
|
||||||
*n, self.value
|
"the value is {}, must be equal to {}",
|
||||||
))
|
n, self.value
|
||||||
} else {
|
));
|
||||||
None
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
None
|
|
||||||
}
|
}
|
||||||
|
None
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,13 +6,13 @@ pub async fn test_input_value_custom_error() {
|
||||||
|
|
||||||
#[Object]
|
#[Object]
|
||||||
impl Query {
|
impl Query {
|
||||||
async fn parse_int(&self, _n: i64) -> bool {
|
async fn parse_int(&self, _n: i8) -> bool {
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let schema = Schema::new(Query, EmptyMutation, EmptySubscription);
|
let schema = Schema::new(Query, EmptyMutation, EmptySubscription);
|
||||||
let query = r#"{ parseInt(n:"A") }"#;
|
let query = r#"{ parseInt(n:289) }"#;
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
schema.execute(&query).await.unwrap_err(),
|
schema.execute(&query).await.unwrap_err(),
|
||||||
Error::Query {
|
Error::Query {
|
||||||
|
@ -22,7 +22,7 @@ pub async fn test_input_value_custom_error() {
|
||||||
},
|
},
|
||||||
path: None,
|
path: None,
|
||||||
err: QueryError::ParseInputValue {
|
err: QueryError::ParseInputValue {
|
||||||
reason: "invalid digit found in string".to_string()
|
reason: "Only integers from -128 to 127 are accepted.".to_string()
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
|
@ -84,7 +84,7 @@ impl ScalarType for TestScalar {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn to_value(&self) -> Value {
|
fn to_value(&self) -> Value {
|
||||||
Value::Int(self.0.clone())
|
Value::Number(self.0.into())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user