Add StringNumber type.
This commit is contained in:
parent
3e19b23178
commit
089e830d26
|
@ -14,10 +14,11 @@ categories = ["network-programming", "asynchronous"]
|
||||||
readme = "README.md"
|
readme = "README.md"
|
||||||
|
|
||||||
[features]
|
[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"]
|
apollo_tracing = ["chrono"]
|
||||||
multipart = ["multer", "bytes", "tempfile"]
|
multipart = ["multer", "bytes", "tempfile"]
|
||||||
unblock = ["blocking"]
|
unblock = ["blocking"]
|
||||||
|
string_number = ["num-traits"]
|
||||||
# Used for doc(cfg())
|
# Used for doc(cfg())
|
||||||
nightly = []
|
nightly = []
|
||||||
|
|
||||||
|
@ -47,6 +48,7 @@ chrono-tz = { version = "0.5.1", optional = true }
|
||||||
log = { version = "0.4.11", optional = true }
|
log = { version = "0.4.11", optional = true }
|
||||||
tracing = { version = "0.1.19", optional = true }
|
tracing = { version = "0.1.19", optional = true }
|
||||||
url = { version = "2.1.1", optional = true }
|
url = { version = "2.1.1", optional = true }
|
||||||
|
num-traits = { version = "0.2.12", optional = true }
|
||||||
|
|
||||||
bytes = { version = "0.5.4", optional = true }
|
bytes = { version = "0.5.4", optional = true }
|
||||||
multer = { version = "1.2.2", optional = true }
|
multer = { version = "1.2.2", optional = true }
|
||||||
|
|
|
@ -10,6 +10,8 @@ mod json;
|
||||||
mod maybe_undefined;
|
mod maybe_undefined;
|
||||||
mod merged_object;
|
mod merged_object;
|
||||||
mod query_root;
|
mod query_root;
|
||||||
|
#[cfg(feature = "string_number")]
|
||||||
|
mod string_number;
|
||||||
mod upload;
|
mod upload;
|
||||||
|
|
||||||
mod external;
|
mod external;
|
||||||
|
@ -21,6 +23,8 @@ pub use id::ID;
|
||||||
pub use json::{Json, OutputJson};
|
pub use json::{Json, OutputJson};
|
||||||
pub use maybe_undefined::MaybeUndefined;
|
pub use maybe_undefined::MaybeUndefined;
|
||||||
pub use merged_object::{MergedObject, MergedObjectSubscriptionTail, MergedObjectTail};
|
pub use merged_object::{MergedObject, MergedObjectSubscriptionTail, MergedObjectTail};
|
||||||
|
#[cfg(feature = "string_number")]
|
||||||
|
pub use string_number::StringNumber;
|
||||||
pub use upload::Upload;
|
pub use upload::Upload;
|
||||||
|
|
||||||
pub(crate) use query_root::QueryRoot;
|
pub(crate) use query_root::QueryRoot;
|
||||||
|
|
78
src/types/string_number.rs
Normal file
78
src/types/string_number.rs
Normal 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",
|
||||||
|
})
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user