Skip to content

Commit f99d86e

Browse files
committed
fix: add missing support for 128-bit integers serialization
1 parent 0cc776e commit f99d86e

5 files changed

Lines changed: 122 additions & 0 deletions

File tree

src/de.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,15 @@ impl<'de> de::Deserializer<'de> for Value {
8585
visitor.visit_i64(num)
8686
}
8787

88+
#[inline]
89+
fn deserialize_i128<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
90+
let num = self.into_int128()?;
91+
let num = num.try_into().map_err(|_| {
92+
ConfigError::invalid_type(None, Unexpected::I128(num), "a signed 128 bit integer")
93+
})?;
94+
visitor.visit_i128(num)
95+
}
96+
8897
#[inline]
8998
fn deserialize_u8<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
9099
let num = try_convert_number!(unsigned, self, "8");
@@ -109,6 +118,15 @@ impl<'de> de::Deserializer<'de> for Value {
109118
visitor.visit_u64(num)
110119
}
111120

121+
#[inline]
122+
fn deserialize_u128<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
123+
let num = self.into_uint128()?;
124+
let num = num.try_into().map_err(|_| {
125+
ConfigError::invalid_type(None, Unexpected::U128(num), "an unsigned 128 bit integer")
126+
})?;
127+
visitor.visit_u128(num)
128+
}
129+
112130
#[inline]
113131
fn deserialize_f32<V: de::Visitor<'de>>(self, visitor: V) -> Result<V::Value> {
114132
visitor.visit_f32(self.into_float()? as f32)

src/ser.rs

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,24 @@ impl<'a> ser::Serializer for &'a mut ConfigSerializer {
108108
self.serialize_primitive(v)
109109
}
110110

111+
fn serialize_i128(self, v: i128) -> Result<Self::Ok> {
112+
if v > i64::MAX.into() {
113+
Err(ConfigError::Message(format!(
114+
"value {} is greater than the max {}",
115+
v,
116+
i64::MAX
117+
)))
118+
} else if v < i64::MIN.into() {
119+
Err(ConfigError::Message(format!(
120+
"value {} is less than the min {}",
121+
v,
122+
i64::MIN
123+
)))
124+
} else {
125+
self.serialize_i64(v as i64)
126+
}
127+
}
128+
111129
fn serialize_u8(self, v: u8) -> Result<Self::Ok> {
112130
self.serialize_u64(v.into())
113131
}
@@ -132,6 +150,18 @@ impl<'a> ser::Serializer for &'a mut ConfigSerializer {
132150
}
133151
}
134152

153+
fn serialize_u128(self, v: u128) -> Result<Self::Ok> {
154+
if v > (i64::MAX as u128) {
155+
Err(ConfigError::Message(format!(
156+
"value {} is greater than the max {}",
157+
v,
158+
i64::MAX
159+
)))
160+
} else {
161+
self.serialize_i64(v as i64)
162+
}
163+
}
164+
135165
fn serialize_f32(self, v: f32) -> Result<Self::Ok> {
136166
self.serialize_f64(v.into())
137167
}

tests/testsuite/i128.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#![cfg(feature = "preserve_order")]
2+
3+
use serde::Deserialize;
4+
5+
#[derive(Debug, Deserialize, Eq, PartialEq)]
6+
struct Container<T> {
7+
inner: T,
8+
}
9+
10+
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
11+
struct I128 {
12+
val: i128,
13+
}
14+
15+
impl From<I128> for config::ValueKind {
16+
fn from(i: I128) -> Self {
17+
let mut properties = indexmap::IndexMap::new();
18+
properties.insert("val".to_owned(), config::Value::from(i.val));
19+
20+
Self::Table(properties)
21+
}
22+
}
23+
24+
#[test]
25+
fn test_deserialize_i128_min() {
26+
let num = I128 { val: i128::MIN };
27+
let container = Container { inner: num };
28+
let built = config::Config::builder()
29+
.set_default("inner", num)
30+
.unwrap()
31+
.build()
32+
.unwrap();
33+
34+
let deserialized = built.clone().try_deserialize::<Container<I128>>().unwrap();
35+
assert_eq!(deserialized, container);
36+
}

tests/testsuite/main.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,11 +16,13 @@ pub mod file_ron;
1616
pub mod file_toml;
1717
pub mod file_yaml;
1818
pub mod get;
19+
pub mod i128;
1920
pub mod integer_range;
2021
pub mod log;
2122
pub mod merge;
2223
pub mod ron_enum;
2324
pub mod set;
25+
pub mod u128;
2426
pub mod unsigned_int;
2527
pub mod unsigned_int_hm;
2628
pub mod weird_keys;

tests/testsuite/u128.rs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
#![cfg(feature = "preserve_order")]
2+
3+
use serde::Deserialize;
4+
5+
#[derive(Debug, Deserialize, Eq, PartialEq)]
6+
struct Container<T> {
7+
inner: T,
8+
}
9+
10+
#[derive(Clone, Copy, Debug, Deserialize, Eq, PartialEq)]
11+
struct U128 {
12+
val: u128,
13+
}
14+
15+
impl From<U128> for config::ValueKind {
16+
fn from(i: U128) -> Self {
17+
let mut properties = indexmap::IndexMap::new();
18+
properties.insert("val".to_owned(), config::Value::from(i.val));
19+
20+
Self::Table(properties)
21+
}
22+
}
23+
24+
#[test]
25+
fn test_deserialize_u128_min() {
26+
let num = U128 { val: u128::MIN };
27+
let container = Container { inner: num };
28+
let built = config::Config::builder()
29+
.set_default("inner", num)
30+
.unwrap()
31+
.build()
32+
.unwrap();
33+
34+
let deserialized = built.clone().try_deserialize::<Container<U128>>().unwrap();
35+
assert_eq!(deserialized, container);
36+
}

0 commit comments

Comments
 (0)