Skip to content

Commit 9e85122

Browse files
RUST-507 Deserialize unsigned integers (#221)
1 parent 5f17b3d commit 9e85122

File tree

2 files changed

+42
-17
lines changed

2 files changed

+42
-17
lines changed

src/de/serde.rs

Lines changed: 21 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
use std::{fmt, vec};
1+
use std::{convert::TryFrom, fmt, vec};
22

33
use serde::de::{
44
self,
@@ -101,10 +101,7 @@ impl<'de> Visitor<'de> for BsonVisitor {
101101
where
102102
E: Error,
103103
{
104-
Err(Error::invalid_type(
105-
Unexpected::Unsigned(value as u64),
106-
&"a signed integer",
107-
))
104+
convert_unsigned_to_signed(value as u64)
108105
}
109106

110107
#[inline]
@@ -120,10 +117,7 @@ impl<'de> Visitor<'de> for BsonVisitor {
120117
where
121118
E: Error,
122119
{
123-
Err(Error::invalid_type(
124-
Unexpected::Unsigned(value as u64),
125-
&"a signed integer",
126-
))
120+
convert_unsigned_to_signed(value as u64)
127121
}
128122

129123
#[inline]
@@ -139,10 +133,7 @@ impl<'de> Visitor<'de> for BsonVisitor {
139133
where
140134
E: Error,
141135
{
142-
Err(Error::invalid_type(
143-
Unexpected::Unsigned(value as u64),
144-
&"a signed integer",
145-
))
136+
convert_unsigned_to_signed(value as u64)
146137
}
147138

148139
#[inline]
@@ -158,10 +149,7 @@ impl<'de> Visitor<'de> for BsonVisitor {
158149
where
159150
E: Error,
160151
{
161-
Err(Error::invalid_type(
162-
Unexpected::Unsigned(value),
163-
&"a signed integer",
164-
))
152+
convert_unsigned_to_signed(value)
165153
}
166154

167155
#[inline]
@@ -235,6 +223,22 @@ impl<'de> Visitor<'de> for BsonVisitor {
235223
}
236224
}
237225

226+
fn convert_unsigned_to_signed<E>(value: u64) -> Result<Bson, E>
227+
where
228+
E: Error,
229+
{
230+
if let Ok(int32) = i32::try_from(value) {
231+
Ok(Bson::Int32(int32))
232+
} else if let Ok(int64) = i64::try_from(value) {
233+
Ok(Bson::Int64(int64))
234+
} else {
235+
Err(Error::custom(format!(
236+
"cannot represent {} as a signed number",
237+
value
238+
)))
239+
}
240+
}
241+
238242
/// Serde Deserializer
239243
pub struct Deserializer {
240244
value: Option<Bson>,

src/tests/serde.rs

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ use crate::{
1212
Binary,
1313
Bson,
1414
Deserializer,
15+
Document,
1516
Serializer,
1617
};
1718
use serde::{Deserialize, Serialize};
@@ -573,3 +574,23 @@ fn test_de_oid_string() {
573574
let oid = ObjectId::with_string("507f1f77bcf86cd799439011").unwrap();
574575
assert_eq!(foo.oid, oid);
575576
}
577+
578+
#[test]
579+
fn test_serialize_deserialize_unsigned_numbers() {
580+
let _guard = LOCK.run_concurrently();
581+
582+
let num = 1;
583+
let json = format!("{{ \"num\": {} }}", num);
584+
let doc: Document = serde_json::from_str(&json).unwrap();
585+
assert_eq!(doc.get_i32("num").unwrap(), num);
586+
587+
let num = i32::MAX as u64 + 1;
588+
let json = format!("{{ \"num\": {} }}", num);
589+
let doc: Document = serde_json::from_str(&json).unwrap();
590+
assert_eq!(doc.get_i64("num").unwrap(), num as i64);
591+
592+
let num = u64::MAX;
593+
let json = format!("{{ \"num\": {} }}", num);
594+
let doc_result: Result<Document, serde_json::Error> = serde_json::from_str(&json);
595+
assert!(doc_result.is_err());
596+
}

0 commit comments

Comments
 (0)