Repository: serde-rs/json (language: rust)

Issue:
Support i128 and u128
These types gained Serialize and Deserialize impls in [Serde 1.0.60](https://github.com/serde-rs/serde/releases/tag/v1.0.60) but still needs to be implemented in serde_json.


Discussion / hints:

Fix patch:
diff --git a/Cargo.toml b/Cargo.toml
index 938cf314f..0216476d8 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -16,7 +16,7 @@ travis-ci = { repository = "serde-rs/json" }
 appveyor = { repository = "serde-rs/json" }
 
 [dependencies]
-serde = "1.0"
+serde = "1.0.60"
 linked-hash-map = { version = "0.5", optional = true }
 itoa = "0.4"
 dtoa = "0.4"
diff --git a/src/de.rs b/src/de.rs
index f39443faf..0e298e797 100644
--- a/src/de.rs
+++ b/src/de.rs
@@ -274,6 +274,34 @@ impl<'de, R: Read<'de>> Deserializer<R> {
         }
     }
 
+    serde_if_integer128! {
+        fn scan_integer128(&mut self, buf: &mut String) -> Result<()> {
+            match try!(self.next_char_or_null()) {
+                b'0' => {
+                    buf.push('0');
+                    // There can be only one leading '0'.
+                    match try!(self.peek_or_null()) {
+                        b'0'...b'9' => {
+                            Err(self.peek_error(ErrorCode::InvalidNumber))
+                        }
+                        _ => Ok(()),
+                    }
+                }
+                c @ b'1'...b'9' => {
+                    buf.push(c as char);
+                    while let c @ b'0'...b'9' = try!(self.peek_or_null()) {
+                        self.eat_char();
+                        buf.push(c as char);
+                    }
+                    Ok(())
+                }
+                _ => {
+                    Err(self.error(ErrorCode::InvalidNumber))
+                }
+            }
+        }
+    }
+
     #[cold]
     fn fix_position(&self, err: Error) -> Error {
         err.fix_position(move |code| self.error(code))
@@ -1098,6 +1126,70 @@ impl<'de, 'a, R: Read<'de>> de::Deserializer<'de> for &'a mut Deserializer<R> {
     deserialize_prim_number!(deserialize_f32);
     deserialize_prim_number!(deserialize_f64);
 
+    serde_if_integer128! {
+        fn deserialize_i128<V>(self, visitor: V) -> Result<V::Value>
+        where
+            V: de::Visitor<'de>,
+        {
+            let mut buf = String::new();
+
+            match try!(self.parse_whitespace()) {
+                Some(b'-') => {
+                    self.eat_char();
+                    buf.push('-');
+                }
+                Some(_) => {}
+                None => {
+                    return Err(self.peek_error(ErrorCode::EofWhileParsingValue));
+                }
+            };
+
+            try!(self.scan_integer128(&mut buf));
+
+            let value = match buf.parse() {
+                Ok(int) => visitor.visit_i128(int),
+                Err(_) => {
+                    return Err(self.error(ErrorCode::NumberOutOfRange));
+                }
+            };
+
+            match value {
+                Ok(value) => Ok(value),
+                Err(err) => Err(self.fix_position(err)),
+            }
+        }
+
+        fn deserialize_u128<V>(self, visitor: V) -> Result<V::Value>
+        where
+            V: de::Visitor<'de>,
+        {
+            match try!(self.parse_whitespace()) {
+                Some(b'-') => {
+                    return Err(self.peek_error(ErrorCode::NumberOutOfRange));
+                }
+                Some(_) => {}
+                None => {
+                    return Err(self.peek_error(ErrorCode::EofWhileParsingValue));
+                }
+            }
+
+            let mut buf = String::new();
+            try!(self.scan_integer128(&mut buf));
+
+            let value = match buf.parse() {
+                Ok(int) => visitor.visit_u128(int),
+                Err(_) => {
+                    return Err(self.error(ErrorCode::NumberOutOfRange));
+                }
+            };
+
+            match value {
+                Ok(value) => Ok(value),
+                Err(err) => Err(self.fix_position(err)),
+            }
+        }
+    }
+
     fn deserialize_char<V>(self, visitor: V) -> Result<V::Value>
     where
         V: de::Visitor<'de>,
@@ -1800,6 +1892,11 @@ where
     deserialize_integer_key!(deserialize_u32 => visit_u32);
     deserialize_integer_key!(deserialize_u64 => visit_u64);
 
+    serde_if_integer128! {
+        deserialize_integer_key!(deserialize_i128 => visit_i128);
+        deserialize_integer_key!(deserialize_u128 => visit_u128);
+    }
+
     #[inline]
     fn deserialize_option<V>(self, visitor: V) -> Result<V::Value>
     where
diff --git a/src/number.rs b/src/number.rs
index 8149ae3a4..949bc5c07 100644
--- a/src/number.rs
+++ b/src/number.rs
@@ -565,6 +565,11 @@ impl<'de> Deserializer<'de> for Number {
     deserialize_number!(deserialize_f32 => visit_f32);
     deserialize_number!(deserialize_f64 => visit_f64);
 
+    serde_if_integer128! {
+        deserialize_number!(deserialize_i128 => visit_i128);
+        deserialize_number!(deserialize_u128 => visit_u128);
+    }
+
     forward_to_deserialize_any! {
         bool char str string bytes byte_buf option unit unit_struct
         newtype_struct seq tuple tuple_struct map struct enum identifier
@@ -588,6 +593,11 @@ impl<'de, 'a> Deserializer<'de> for &'a Number {
     deserialize_number!(deserialize_f32 => visit_f32);
     deserialize_number!(deserialize_f64 => visit_f64);
 
+    serde_if_integer128! {
+        deserialize_number!(deserialize_i128 => visit_i128);
+        deserialize_number!(deserialize_u128 => visit_u128);
+    }
+
     forward_to_deserialize_any! {
         bool char str string bytes byte_buf option unit unit_struct
         newtype_struct seq tuple tuple_struct map struct enum identifier
@@ -639,9 +649,9 @@ impl<'de> Deserializer<'de> for NumberFieldDeserializer {
     }
 
     forward_to_deserialize_any! {
-        bool u8 u16 u32 u64 i8 i16 i32 i64 f32 f64 char str string seq
-        bytes byte_buf map struct option unit newtype_struct
-        ignored_any unit_struct tuple_struct tuple enum identifier
+        bool u8 u16 u32 u64 u128 i8 i16 i32 i64 i128 f32 f64 char str string seq
+        bytes byte_buf map struct option unit newtype_struct ignored_any
+        unit_struct tuple_struct tuple enum identifier
     }
 }
 
diff --git a/src/ser.rs b/src/ser.rs
index 8ff9eccec..acc0bc006 100644
--- a/src/ser.rs
+++ b/src/ser.rs
@@ -141,6 +141,14 @@ where
         Ok(())
     }
 
+    serde_if_integer128! {
+        fn serialize_i128(self, value: i128) -> Result<()> {
+            self.formatter
+                .write_number_str(&mut self.writer, &value.to_string())
+                .map_err(Error::io)
+        }
+    }
+
     #[inline]
     fn serialize_u8(self, value: u8) -> Result<()> {
         try!(
@@ -181,6 +189,14 @@ where
         Ok(())
     }
 
+    serde_if_integer128! {
+        fn serialize_u128(self, value: u128) -> Result<()> {
+            self.formatter
+                .write_number_str(&mut self.writer, &value.to_string())
+                .map_err(Error::io)
+        }
+    }
+
     #[inline]
     fn serialize_f32(self, value: f32) -> Result<()> {
         match value.classify() {
@@ -1010,6 +1026,15 @@ where
         Ok(())
     }
 
+    serde_if_integer128! {
+        fn serialize_i128(self, value: i128) -> Result<()> {
+            self.ser
+                .formatter
+                .write_number_str(&mut self.ser.writer, &value.to_string())
+                .map_err(Error::io)
+        }
+    }
+
     fn serialize_u8(self, value: u8) -> Result<()> {
         try!(
             self.ser
@@ -1098,6 +1123,15 @@ where
         Ok(())
     }
 
+    serde_if_integer128! {
+        fn serialize_u128(self, value: u128) -> Result<()> {
+            self.ser
+                .formatter
+                .write_number_str(&mut self.ser.writer, &value.to_string())
+                .map_err(Error::io)
+        }
+    }
+
     fn serialize_f32(self, _value: f32) -> Result<()> {
         Err(key_must_be_a_string())
     }
@@ -1227,6 +1261,12 @@ impl<'a, W: io::Write, F: Formatter> ser::Serializer for NumberStrEmitter<'a, W,
         Err(invalid_number())
     }
 
+    serde_if_integer128! {
+        fn serialize_i128(self, _v: i128) -> Result<Self::Ok> {
+            Err(invalid_number())
+        }
+    }
+
     fn serialize_u8(self, _v: u8) -> Result<Self::Ok> {
         Err(invalid_number())
     }
@@ -1243,6 +1283,12 @@ impl<'a, W: io::Write, F: Formatter> ser::Serializer for NumberStrEmitter<'a, W,
         Err(invalid_number())
     }
 
+    serde_if_integer128! {
+        fn serialize_u128(self, _v: u128) -> Result<Self::Ok> {
+            Err(invalid_number())
+        }
+    }
+
     fn serialize_f32(self, _v: f32) -> Result<Self::Ok> {
         Err(invalid_number())
     }
diff --git a/src/value/de.rs b/src/value/de.rs
index d4f9b614a..162e05e74 100644
--- a/src/value/de.rs
+++ b/src/value/de.rs
@@ -316,6 +316,11 @@ impl<'de> serde::Deserializer<'de> for Value {
     deserialize_prim_number!(deserialize_f32);
     deserialize_prim_number!(deserialize_f64);
 
+    serde_if_integer128! {
+        deserialize_prim_number!(deserialize_i128);
+        deserialize_prim_number!(deserialize_u128);
+    }
+
     #[inline]
     fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error>
     where
@@ -656,8 +661,8 @@ impl<'de> serde::Deserializer<'de> for SeqDeserializer {
     }
 
     forward_to_deserialize_any! {
-        bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
-        byte_buf option unit unit_struct newtype_struct seq tuple
+        bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
+        bytes byte_buf option unit unit_struct newtype_struct seq tuple
         tuple_struct map struct enum identifier ignored_any
     }
 }
@@ -746,8 +751,8 @@ impl<'de> serde::Deserializer<'de> for MapDeserializer {
     }
 
     forward_to_deserialize_any! {
-        bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
-        byte_buf option unit unit_struct newtype_struct seq tuple
+        bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
+        bytes byte_buf option unit unit_struct newtype_struct seq tuple
         tuple_struct map struct enum identifier ignored_any
     }
 }
@@ -842,6 +847,11 @@ impl<'de> serde::Deserializer<'de> for &'de Value {
     deserialize_value_ref_number!(deserialize_f32);
     deserialize_value_ref_number!(deserialize_f64);
 
+    serde_if_integer128! {
+        deserialize_prim_number!(deserialize_i128);
+        deserialize_prim_number!(deserialize_u128);
+    }
+
     fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error>
     where
         V: Visitor<'de>,
@@ -1177,8 +1187,8 @@ impl<'de> serde::Deserializer<'de> for SeqRefDeserializer<'de> {
     }
 
     forward_to_deserialize_any! {
-        bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
-        byte_buf option unit unit_struct newtype_struct seq tuple
+        bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
+        bytes byte_buf option unit unit_struct newtype_struct seq tuple
         tuple_struct map struct enum identifier ignored_any
     }
 }
@@ -1267,8 +1277,8 @@ impl<'de> serde::Deserializer<'de> for MapRefDeserializer<'de> {
     }
 
     forward_to_deserialize_any! {
-        bool i8 i16 i32 i64 u8 u16 u32 u64 f32 f64 char str string bytes
-        byte_buf option unit unit_struct newtype_struct seq tuple
+        bool i8 i16 i32 i64 i128 u8 u16 u32 u64 u128 f32 f64 char str string
+        bytes byte_buf option unit unit_struct newtype_struct seq tuple
         tuple_struct map struct enum identifier ignored_any
     }
 }
@@ -1311,6 +1321,11 @@ impl<'de> serde::Deserializer<'de> for MapKeyDeserializer<'de> {
     deserialize_integer_key!(deserialize_u32 => visit_u32);
     deserialize_integer_key!(deserialize_u64 => visit_u64);
 
+    serde_if_integer128! {
+        deserialize_integer_key!(deserialize_i128 => visit_i128);
+        deserialize_integer_key!(deserialize_u128 => visit_u128);
+    }
+
     #[inline]
     fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Error>
     where


Test patch:
diff --git a/tests/test.rs b/tests/test.rs
index 61e0d2dc9..a7d21092f 100644
--- a/tests/test.rs
+++ b/tests/test.rs
@@ -1983,3 +1983,40 @@ fn null_invalid_type() {
         String::from("invalid type: null, expected a string at line 1 column 4")
     );
 }
+
+#[test]
+fn test_integer128() {
+    let signed = &[i128::min_value(), -1, 0, 1, i128::max_value()];
+    let unsigned = &[0, 1, u128::max_value()];
+
+    for integer128 in signed {
+        let expected = integer128.to_string();
+        assert_eq!(to_string(integer128).unwrap(), expected);
+        assert_eq!(from_str::<i128>(&expected).unwrap(), *integer128);
+    }
+
+    for integer128 in unsigned {
+        let expected = integer128.to_string();
+        assert_eq!(to_string(integer128).unwrap(), expected);
+        assert_eq!(from_str::<u128>(&expected).unwrap(), *integer128);
+    }
+
+    test_parse_err::<i128>(&[
+        (
+            "-170141183460469231731687303715884105729",
+            "number out of range at line 1 column 40",
+        ),
+        (
+            "170141183460469231731687303715884105728",
+            "number out of range at line 1 column 39",
+        ),
+    ]);
+
+    test_parse_err::<u128>(&[
+        ("-1", "number out of range at line 1 column 1"),
+        (
+            "340282366920938463463374607431768211456",
+            "number out of range at line 1 column 39",
+        ),
+    ]);
+}