Add StringNumber type.

This commit is contained in:
Sunli 2020-09-26 09:22:54 +08:00
parent 3e19b23178
commit 089e830d26
3 changed files with 85 additions and 1 deletions

View File

@ -14,10 +14,11 @@ categories = ["network-programming", "asynchronous"]
readme = "README.md"
[features]
default = ["apollo_tracing", "uuid", "bson", "chrono", "chrono-tz", "log", "multipart", "tracing", "url", "unblock"]
default = ["apollo_tracing", "uuid", "bson", "chrono", "chrono-tz", "log", "multipart", "tracing", "url", "unblock", "string_number"]
apollo_tracing = ["chrono"]
multipart = ["multer", "bytes", "tempfile"]
unblock = ["blocking"]
string_number = ["num-traits"]
# Used for doc(cfg())
nightly = []
@ -47,6 +48,7 @@ chrono-tz = { version = "0.5.1", optional = true }
log = { version = "0.4.11", optional = true }
tracing = { version = "0.1.19", optional = true }
url = { version = "2.1.1", optional = true }
num-traits = { version = "0.2.12", optional = true }
bytes = { version = "0.5.4", optional = true }
multer = { version = "1.2.2", optional = true }

View File

@ -10,6 +10,8 @@ mod json;
mod maybe_undefined;
mod merged_object;
mod query_root;
#[cfg(feature = "string_number")]
mod string_number;
mod upload;
mod external;
@ -21,6 +23,8 @@ pub use id::ID;
pub use json::{Json, OutputJson};
pub use maybe_undefined::MaybeUndefined;
pub use merged_object::{MergedObject, MergedObjectSubscriptionTail, MergedObjectTail};
#[cfg(feature = "string_number")]
pub use string_number::StringNumber;
pub use upload::Upload;
pub(crate) use query_root::QueryRoot;

View File

@ -0,0 +1,78 @@
use crate::{InputValueError, InputValueResult, Scalar, ScalarType, Value};
use num_traits::Num;
use serde::{Deserialize, Serialize};
use std::fmt::Display;
/// A numeric value represented by a string.
#[derive(Clone, Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Serialize, Deserialize)]
#[serde(transparent)]
#[cfg_attr(feature = "nightly", doc(cfg(feature = "string_number")))]
pub struct StringNumber<T: Num + Display>(pub T);
#[Scalar(internal)]
impl<T: Num + Display + Send + Sync> ScalarType for StringNumber<T>
where
<T as Num>::FromStrRadixErr: Display,
{
fn parse(value: Value) -> InputValueResult<Self> {
match value {
Value::String(s) => {
let n = T::from_str_radix(&s, 10)
.map_err(|err| InputValueError::Custom(err.to_string()))?;
Ok(StringNumber(n))
}
_ => Err(InputValueError::ExpectedType(value)),
}
}
fn is_valid(value: &Value) -> bool {
match value {
Value::String(_) => true,
_ => false,
}
}
fn to_value(&self) -> Value {
Value::String(self.0.to_string())
}
}
#[cfg(test)]
mod test {
use crate::*;
#[async_std::test]
async fn test_string_number() {
struct Query;
#[Object(internal)]
impl Query {
async fn value(&self, n: StringNumber<i32>) -> StringNumber<i32> {
n
}
}
let schema = Schema::new(Query, EmptyMutation, EmptySubscription);
assert_eq!(
schema
.execute(
r#"{
value1: value(n: "100")
value2: value(n: "-100")
value3: value(n: "0")
value4: value(n: "1")
}"#
)
.await
.into_result()
.unwrap()
.data,
serde_json::json!({
"value1": "100",
"value2": "-100",
"value3": "0",
"value4": "1",
})
);
}
}