Skip to content

Commit 4a19ba6

Browse files
marcelbuesingkyeah
authored andcommitted
Add u2i feature (#94) (#95)
Closes #94.
1 parent 961f9bb commit 4a19ba6

File tree

7 files changed

+128
-10
lines changed

7 files changed

+128
-10
lines changed

.travis.yml

+1
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,5 @@ sudo: false
1515
script:
1616
- cargo build -v
1717
- cargo test -v --no-fail-fast
18+
- cargo test -v --no-fail-fast --features u2i
1819
- cd serde-tests && cargo test -v --no-fail-fast

Cargo.toml

+8
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,12 @@ readme = "README.md"
1111
homepage = "https://github.com/zonyitoo/bson-rs"
1212
documentation = "https://docs.rs/crate/bson"
1313

14+
[features]
15+
# no features by default
16+
default = []
17+
# attempt to encode unsigned types in signed types
18+
u2i = []
19+
1420
[lib]
1521
name = "bson"
1622

@@ -26,7 +32,9 @@ linked-hash-map = "0.5"
2632
hostname = "0.1"
2733
hex = "0.3"
2834
md5 = "0.3"
35+
try_from = "0.2"
2936

3037
[dev-dependencies]
38+
assert_matches = "1.2"
3139
serde_derive = "1.0"
3240
serde_bytes = "0.10"

src/encoder/error.rs

+11
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ pub enum EncoderError {
1010
InvalidMapKeyType(Bson),
1111
Unknown(String),
1212
UnsupportedUnsignedType,
13+
UnsignedTypesValueExceedsRange(u64),
1314
}
1415

1516
impl From<io::Error> for EncoderError {
@@ -25,6 +26,14 @@ impl fmt::Display for EncoderError {
2526
&EncoderError::InvalidMapKeyType(ref bson) => write!(fmt, "Invalid map key type: {:?}", bson),
2627
&EncoderError::Unknown(ref inner) => inner.fmt(fmt),
2728
&EncoderError::UnsupportedUnsignedType => write!(fmt, "BSON does not support unsigned type"),
29+
&EncoderError::UnsignedTypesValueExceedsRange(value) => {
30+
write!(
31+
fmt,
32+
"BSON does not support unsigned types.
33+
An attempt to encode the value: {} in a signed type failed due to the values size.",
34+
value
35+
)
36+
},
2837
}
2938
}
3039
}
@@ -36,6 +45,8 @@ impl error::Error for EncoderError {
3645
&EncoderError::InvalidMapKeyType(_) => "Invalid map key type",
3746
&EncoderError::Unknown(ref inner) => inner,
3847
&EncoderError::UnsupportedUnsignedType => "BSON does not support unsigned type",
48+
&EncoderError::UnsignedTypesValueExceedsRange(_) => "BSON does not support unsigned types.
49+
An attempt to encode the value: {} in a signed type failed due to the values size."
3950
}
4051
}
4152
fn cause(&self) -> Option<&error::Error> {

src/encoder/serde.rs

+28-8
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use serde::ser::{Serialize, SerializeMap, SerializeSeq, SerializeStruct, Seriali
33

44
use bson::{Array, Bson, Document, UtcDateTime};
55
use oid::ObjectId;
6+
use try_from::TryFrom;
67

78
use super::{to_bson, EncoderError, EncoderResult};
89

@@ -88,8 +89,12 @@ impl Serializer for Encoder {
8889
}
8990

9091
#[inline]
91-
fn serialize_u8(self, _value: u8) -> EncoderResult<Bson> {
92-
Err(EncoderError::UnsupportedUnsignedType)
92+
fn serialize_u8(self, value: u8) -> EncoderResult<Bson> {
93+
if cfg!(feature = "u2i") {
94+
Ok(Bson::I32(value as i32))
95+
} else {
96+
Err(EncoderError::UnsupportedUnsignedType)
97+
}
9398
}
9499

95100
#[inline]
@@ -98,8 +103,12 @@ impl Serializer for Encoder {
98103
}
99104

100105
#[inline]
101-
fn serialize_u16(self, _value: u16) -> EncoderResult<Bson> {
102-
Err(EncoderError::UnsupportedUnsignedType)
106+
fn serialize_u16(self, value: u16) -> EncoderResult<Bson> {
107+
if cfg!(feature = "u2i") {
108+
Ok(Bson::I32(value as i32))
109+
} else {
110+
Err(EncoderError::UnsupportedUnsignedType)
111+
}
103112
}
104113

105114
#[inline]
@@ -108,8 +117,12 @@ impl Serializer for Encoder {
108117
}
109118

110119
#[inline]
111-
fn serialize_u32(self, _value: u32) -> EncoderResult<Bson> {
112-
Err(EncoderError::UnsupportedUnsignedType)
120+
fn serialize_u32(self, value: u32) -> EncoderResult<Bson> {
121+
if cfg!(feature = "u2i") {
122+
Ok(Bson::I64(value as i64))
123+
} else {
124+
Err(EncoderError::UnsupportedUnsignedType)
125+
}
113126
}
114127

115128
#[inline]
@@ -118,8 +131,15 @@ impl Serializer for Encoder {
118131
}
119132

120133
#[inline]
121-
fn serialize_u64(self, _value: u64) -> EncoderResult<Bson> {
122-
Err(EncoderError::UnsupportedUnsignedType)
134+
fn serialize_u64(self, value: u64) -> EncoderResult<Bson> {
135+
if cfg!(feature = "u2i") {
136+
match i64::try_from(value) {
137+
Ok(ivalue) => Ok(Bson::I64(ivalue)),
138+
Err(_) => Err(EncoderError::UnsignedTypesValueExceedsRange(value)),
139+
}
140+
} else {
141+
Err(EncoderError::UnsupportedUnsignedType)
142+
}
123143
}
124144

125145
#[inline]

src/lib.rs

+1
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ extern crate serde;
5454
extern crate serde_json;
5555
extern crate md5;
5656
extern crate time;
57+
extern crate try_from;
5758

5859
pub use self::bson::{Array, Bson, Document, TimeStamp, UtcDateTime};
5960
pub use self::decoder::{decode_document, decode_document_utf8_lossy, from_bson, Decoder, DecoderError, DecoderResult};

tests/lib.rs

+2
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
#[macro_use(assert_matches)]
2+
extern crate assert_matches;
13
#[macro_use(bson, doc)]
24
extern crate bson;
35
extern crate byteorder;

tests/modules/ser.rs

+77-2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
use bson::{from_bson, to_bson, Bson};
1+
use bson::{from_bson, to_bson, Bson, EncoderError, EncoderResult};
22
use bson::oid::ObjectId;
33
use std::collections::BTreeMap;
4+
use std::{u8, u16, u32, u64};
45

56
#[test]
67
fn floating_point() {
@@ -53,11 +54,85 @@ fn int32() {
5354
assert_eq!(deser, obj);
5455
}
5556

57+
#[test]
58+
#[cfg_attr(feature = "u2i", ignore)]
59+
fn uint8() {
60+
let obj_min: EncoderResult<Bson> = to_bson(&u8::MIN);
61+
assert_matches!(obj_min, Err(EncoderError::UnsupportedUnsignedType));
62+
}
63+
64+
#[test]
65+
#[cfg(feature = "u2i")]
66+
fn uint8_u2i() {
67+
let obj: Bson = to_bson(&u8::MIN).unwrap();
68+
let deser: u8 = from_bson(obj).unwrap();
69+
assert_eq!(deser, u8::MIN);
70+
71+
let obj_max: Bson = to_bson(&u8::MAX).unwrap();
72+
let deser_max: u8 = from_bson(obj_max).unwrap();
73+
assert_eq!(deser_max, u8::MAX);
74+
}
75+
76+
#[test]
77+
#[cfg_attr(feature = "u2i", ignore)]
78+
fn uint16() {
79+
let obj_min: EncoderResult<Bson> = to_bson(&u16::MIN);
80+
assert_matches!(obj_min, Err(EncoderError::UnsupportedUnsignedType));
81+
}
82+
83+
#[test]
84+
#[cfg(feature = "u2i")]
85+
fn uint16_u2i() {
86+
let obj: Bson = to_bson(&u16::MIN).unwrap();
87+
let deser: u16 = from_bson(obj).unwrap();
88+
assert_eq!(deser, u16::MIN);
89+
90+
let obj_max: Bson = to_bson(&u16::MAX).unwrap();
91+
let deser_max: u16 = from_bson(obj_max).unwrap();
92+
assert_eq!(deser_max, u16::MAX);
93+
}
94+
95+
#[test]
96+
#[cfg_attr(feature = "u2i", ignore)]
97+
fn uint32() {
98+
let obj_min: EncoderResult<Bson> = to_bson(&u32::MIN);
99+
assert_matches!(obj_min, Err(EncoderError::UnsupportedUnsignedType));
100+
}
101+
102+
#[test]
103+
#[cfg(feature = "u2i")]
104+
fn uint32_u2i() {
105+
let obj_min: Bson = to_bson(&u32::MIN).unwrap();
106+
let deser_min: u32 = from_bson(obj_min).unwrap();
107+
assert_eq!(deser_min, u32::MIN);
108+
109+
let obj_max: Bson = to_bson(&u32::MAX).unwrap();
110+
let deser_max: u32 = from_bson(obj_max).unwrap();
111+
assert_eq!(deser_max, u32::MAX);
112+
}
113+
114+
#[test]
115+
#[cfg_attr(feature = "u2i", ignore)]
116+
fn uint64() {
117+
let obj_min: EncoderResult<Bson> = to_bson(&u64::MIN);
118+
assert_matches!(obj_min, Err(EncoderError::UnsupportedUnsignedType));
119+
}
120+
121+
#[test]
122+
#[cfg(feature = "u2i")]
123+
fn uint64_u2i() {
124+
let obj_min: Bson = to_bson(&u64::MIN).unwrap();
125+
let deser_min: u64 = from_bson(obj_min).unwrap();
126+
assert_eq!(deser_min, u64::MIN);
127+
128+
let obj_max: EncoderResult<Bson> = to_bson(&u64::MAX);
129+
assert_matches!(obj_max, Err(EncoderError::UnsignedTypesValueExceedsRange(u64::MAX)));
130+
}
131+
56132
#[test]
57133
fn int64() {
58134
let obj = Bson::I64(101);
59135
let i: i64 = from_bson(obj.clone()).unwrap();
60-
61136
assert_eq!(i, 101);
62137

63138
let deser: Bson = to_bson(&i).unwrap();

0 commit comments

Comments
 (0)