From 46cde4fb85007690d609037f2d696ea13d91536c Mon Sep 17 00:00:00 2001
From: Kai Ren <tyranron@gmail.com>
Date: Thu, 8 Oct 2020 03:40:36 +0300
Subject: [PATCH] Fix parsing f64 from Scalar::Int (#777)

---
 juniper/src/types/scalars.rs | 47 +++++++++++++++++++++++++++++++++---
 1 file changed, 44 insertions(+), 3 deletions(-)

diff --git a/juniper/src/types/scalars.rs b/juniper/src/types/scalars.rs
index 2f50eefd..830847e4 100644
--- a/juniper/src/types/scalars.rs
+++ b/juniper/src/types/scalars.rs
@@ -325,7 +325,11 @@ where
 
     fn from_str<'a>(value: ScalarToken<'a>) -> ParseScalarResult<'a, S> {
         match value {
-            ScalarToken::Int(v) | ScalarToken::Float(v) => v
+            ScalarToken::Int(v) => v
+                .parse()
+                .map_err(|_| ParseError::UnexpectedToken(Token::Scalar(value)))
+                .map(|s: i32| f64::from(s).into()),
+            ScalarToken::Float(v) => v
                 .parse()
                 .map_err(|_| ParseError::UnexpectedToken(Token::Scalar(value)))
                 .map(|s: f64| s.into()),
@@ -334,7 +338,7 @@ where
     }
 }
 
-/// Utillity type to define read-only schemas
+/// Utility type to define read-only schemas
 ///
 /// If you instantiate `RootNode` with this as the mutation, no mutation will be
 /// generated for the schema.
@@ -457,12 +461,13 @@ impl<T> Default for EmptySubscription<T> {
 
 #[cfg(test)]
 mod tests {
-    use super::{EmptyMutation, EmptySubscription, ID};
     use crate::{
         parser::ScalarToken,
         value::{DefaultScalarValue, ParseScalarValue},
     };
 
+    use super::{EmptyMutation, EmptySubscription, ID};
+
     #[test]
     fn test_id_from_string() {
         let actual = ID::from(String::from("foo"));
@@ -505,6 +510,42 @@ mod tests {
         );
     }
 
+    #[test]
+    fn parse_f64_from_int() {
+        for (v, expected) in &[
+            ("0", 0),
+            ("128", 128),
+            ("1601942400", 1601942400),
+            ("1696550400", 1696550400),
+            ("-1", -1),
+        ] {
+            let n = <f64 as ParseScalarValue<DefaultScalarValue>>::from_str(ScalarToken::Int(v));
+            assert!(n.is_ok(), "A parsing error occurred: {:?}", n.unwrap_err());
+
+            let n: Option<f64> = n.unwrap().into();
+            assert!(n.is_some(), "No f64 returned");
+            assert_eq!(n.unwrap(), f64::from(*expected));
+        }
+    }
+
+    #[test]
+    fn parse_f64_from_float() {
+        for (v, expected) in &[
+            ("0.", 0.),
+            ("1.2", 1.2),
+            ("1601942400.", 1601942400.),
+            ("1696550400.", 1696550400.),
+            ("-1.2", -1.2),
+        ] {
+            let n = <f64 as ParseScalarValue<DefaultScalarValue>>::from_str(ScalarToken::Float(v));
+            assert!(n.is_ok(), "A parsing error occurred: {:?}", n.unwrap_err());
+
+            let n: Option<f64> = n.unwrap().into();
+            assert!(n.is_some(), "No f64 returned");
+            assert_eq!(n.unwrap(), *expected);
+        }
+    }
+
     #[test]
     fn empty_mutation_is_send() {
         fn check_if_send<T: Send>() {}