Skip to content

Commit 320c783

Browse files
authored
RUST-738 Implement Clone on error types (#252)
This commit also updates a few of the error cases to include more information and more accurate names, and it also removes some redundant cases.
1 parent 00d4e2f commit 320c783

File tree

8 files changed

+62
-57
lines changed

8 files changed

+62
-57
lines changed

src/de/error.rs

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
use std::{error, fmt, fmt::Display, io, string};
1+
use std::{error, fmt, fmt::Display, io, string, sync::Arc};
22

33
use serde::de::{self, Unexpected};
44

55
use crate::Bson;
66

77
/// Possible errors that can arise during decoding.
8-
#[derive(Debug)]
8+
#[derive(Clone, Debug)]
99
#[non_exhaustive]
1010
pub enum Error {
1111
/// A [`std::io::Error`](https://doc.rust-lang.org/std/io/struct.Error.html) encountered while deserializing.
12-
IoError(io::Error),
12+
IoError(Arc<io::Error>),
1313

1414
/// A [`std::string::FromUtf8Error`](https://doc.rust-lang.org/std/string/struct.FromUtf8Error.html) encountered
1515
/// while decoding a UTF-8 String from the input data.
@@ -31,11 +31,14 @@ pub enum Error {
3131
/// The end of the BSON input was reached too soon.
3232
EndOfStream,
3333

34-
/// An invalid timestamp was encountered while decoding.
35-
InvalidTimestamp(i64),
34+
/// An invalid datetime was encountered while decoding.
35+
InvalidDateTime {
36+
/// The key at which an unexpected/unsupported datetime was encountered.
37+
key: String,
3638

37-
/// An ambiguous timestamp was encountered while decoding.
38-
AmbiguousTimestamp(i64),
39+
/// The value of the invalid datetime.
40+
datetime: i64,
41+
},
3942

4043
/// A general error encountered during deserialization.
4144
/// See: https://docs.serde.rs/serde/de/trait.Error.html
@@ -47,7 +50,7 @@ pub enum Error {
4750

4851
impl From<io::Error> for Error {
4952
fn from(err: io::Error) -> Error {
50-
Error::IoError(err)
53+
Error::IoError(Arc::new(err))
5154
}
5255
}
5356

@@ -73,16 +76,17 @@ impl fmt::Display for Error {
7376
Error::SyntaxError { ref message } => message.fmt(fmt),
7477
Error::EndOfStream => fmt.write_str("end of stream"),
7578
Error::DeserializationError { ref message } => message.fmt(fmt),
76-
Error::InvalidTimestamp(ref i) => write!(fmt, "no such local time {}", i),
77-
Error::AmbiguousTimestamp(ref i) => write!(fmt, "ambiguous local time {}", i),
79+
Error::InvalidDateTime { ref key, datetime } => {
80+
write!(fmt, "invalid datetime for key \"{}\": {}", key, datetime)
81+
}
7882
}
7983
}
8084
}
8185

8286
impl error::Error for Error {
83-
fn cause(&self) -> Option<&dyn error::Error> {
87+
fn source(&self) -> Option<&(dyn error::Error + 'static)> {
8488
match *self {
85-
Error::IoError(ref inner) => Some(inner),
89+
Error::IoError(ref inner) => Some(inner.as_ref()),
8690
Error::FromUtf8Error(ref inner) => Some(inner),
8791
_ => None,
8892
}

src/de/mod.rs

Lines changed: 7 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -326,19 +326,14 @@ pub(crate) fn deserialize_bson_kvp<R: Read + ?Sized>(
326326
// The int64 is UTC milliseconds since the Unix epoch.
327327
let time = read_i64(reader)?;
328328

329-
let mut sec = time / 1000;
330-
let tmp_msec = time % 1000;
331-
let msec = if tmp_msec < 0 {
332-
sec -= 1;
333-
1000 + tmp_msec
334-
} else {
335-
tmp_msec
336-
};
337-
338-
match Utc.timestamp_opt(sec, (msec as u32) * 1_000_000) {
339-
LocalResult::None => return Err(Error::InvalidTimestamp(time)),
340-
LocalResult::Ambiguous(..) => return Err(Error::AmbiguousTimestamp(time)),
329+
match Utc.timestamp_millis_opt(time) {
341330
LocalResult::Single(t) => Bson::DateTime(t),
331+
_ => {
332+
return Err(Error::InvalidDateTime {
333+
key,
334+
datetime: time,
335+
})
336+
}
342337
}
343338
}
344339
Some(ElementType::Symbol) => read_string(reader, utf8_lossy).map(Bson::Symbol)?,

src/document.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ use crate::{
2626

2727
/// Error to indicate that either a value was empty or it contained an unexpected
2828
/// type, for use with the direct getters.
29-
#[derive(PartialEq)]
29+
#[derive(PartialEq, Clone)]
3030
#[non_exhaustive]
3131
pub enum ValueAccessError {
3232
/// Cannot find the expected field with the specified key

src/extjson/de.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ use serde::de::{Error as _, Unexpected};
2727

2828
use crate::{extjson::models, oid, Bson, Document};
2929

30-
#[derive(Debug)]
30+
#[derive(Clone, Debug)]
3131
#[non_exhaustive]
3232
/// Error cases that can occur during deserialization from [extended JSON](https://docs.mongodb.com/manual/reference/mongodb-extended-json/).
3333
pub enum Error {

src/oid.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ lazy_static! {
3131
}
3232

3333
/// Errors that can occur during OID construction and generation.
34-
#[derive(Debug)]
34+
#[derive(Clone, Debug)]
3535
#[non_exhaustive]
3636
pub enum Error {
3737
/// An invalid argument was passed in.

src/ser/error.rs

Lines changed: 18 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
use std::{error, fmt, fmt::Display, io};
1+
use std::{error, fmt, fmt::Display, io, sync::Arc};
22

33
use serde::ser;
44

55
use crate::bson::Bson;
66

77
/// Possible errors that can arise during encoding.
8-
#[derive(Debug)]
8+
#[derive(Clone, Debug)]
99
#[non_exhaustive]
1010
pub enum Error {
1111
/// A [`std::io::Error`](https://doc.rust-lang.org/std/io/struct.Error.html) encountered while serializing.
12-
IoError(io::Error),
12+
IoError(Arc<io::Error>),
1313

1414
/// A key could not be serialized to a BSON string.
1515
InvalidMapKeyType {
@@ -28,18 +28,18 @@ pub enum Error {
2828
/// Returned when serialization of an unsigned integer was attempted. BSON only supports
2929
/// 32-bit and 64-bit signed integers.
3030
///
31-
/// To allow serialization of unsigned integers as signed integers, enable the "u2i" feature
32-
/// flag.
33-
UnsupportedUnsignedType,
31+
/// To serialize unsigned integers to BSON, use an appropriate helper from
32+
/// [`crate::serde_helpers`] or enable the "u2i" feature flag.
33+
UnsupportedUnsignedInteger(u64),
3434

3535
#[cfg(feature = "u2i")]
3636
/// An unsigned integer type could not fit into a signed integer type.
37-
UnsignedTypesValueExceedsRange(u64),
37+
UnsignedIntegerExceededRange(u64),
3838
}
3939

4040
impl From<io::Error> for Error {
4141
fn from(err: io::Error) -> Error {
42-
Error::IoError(err)
42+
Error::IoError(Arc::new(err))
4343
}
4444
}
4545

@@ -50,11 +50,17 @@ impl fmt::Display for Error {
5050
Error::InvalidMapKeyType { ref key } => write!(fmt, "Invalid map key type: {}", key),
5151
Error::SerializationError { ref message } => message.fmt(fmt),
5252
#[cfg(not(feature = "u2i"))]
53-
Error::UnsupportedUnsignedType => fmt.write_str("BSON does not support unsigned type"),
53+
Error::UnsupportedUnsignedInteger(value) => write!(
54+
fmt,
55+
"BSON does not support unsigned integers, cannot serialize value: {}. To \
56+
serialize unsigned integers to BSON, use an appropriate serde helper or enable \
57+
the u2i feature.",
58+
value
59+
),
5460
#[cfg(feature = "u2i")]
55-
Error::UnsignedTypesValueExceedsRange(value) => write!(
61+
Error::UnsignedIntegerExceededRange(value) => write!(
5662
fmt,
57-
"BSON does not support unsigned types.
63+
"BSON does not support unsigned integers.
5864
An attempt to serialize the value: {} in a signed type failed due to the value's \
5965
size.",
6066
value
@@ -66,7 +72,7 @@ impl fmt::Display for Error {
6672
impl error::Error for Error {
6773
fn cause(&self) -> Option<&dyn error::Error> {
6874
match *self {
69-
Error::IoError(ref inner) => Some(inner),
75+
Error::IoError(ref inner) => Some(inner.as_ref()),
7076
_ => None,
7177
}
7278
}

src/ser/serde.rs

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -117,14 +117,14 @@ impl ser::Serializer for Serializer {
117117
}
118118

119119
#[inline]
120-
fn serialize_u8(self, _value: u8) -> crate::ser::Result<Bson> {
120+
fn serialize_u8(self, value: u8) -> crate::ser::Result<Bson> {
121121
#[cfg(feature = "u2i")]
122122
{
123-
Ok(Bson::Int32(_value as i32))
123+
Ok(Bson::Int32(value as i32))
124124
}
125125

126126
#[cfg(not(feature = "u2i"))]
127-
Err(Error::UnsupportedUnsignedType)
127+
Err(Error::UnsupportedUnsignedInteger(value as u64))
128128
}
129129

130130
#[inline]
@@ -133,14 +133,14 @@ impl ser::Serializer for Serializer {
133133
}
134134

135135
#[inline]
136-
fn serialize_u16(self, _value: u16) -> crate::ser::Result<Bson> {
136+
fn serialize_u16(self, value: u16) -> crate::ser::Result<Bson> {
137137
#[cfg(feature = "u2i")]
138138
{
139-
Ok(Bson::Int32(_value as i32))
139+
Ok(Bson::Int32(value as i32))
140140
}
141141

142142
#[cfg(not(feature = "u2i"))]
143-
Err(Error::UnsupportedUnsignedType)
143+
Err(Error::UnsupportedUnsignedInteger(value as u64))
144144
}
145145

146146
#[inline]
@@ -149,14 +149,14 @@ impl ser::Serializer for Serializer {
149149
}
150150

151151
#[inline]
152-
fn serialize_u32(self, _value: u32) -> crate::ser::Result<Bson> {
152+
fn serialize_u32(self, value: u32) -> crate::ser::Result<Bson> {
153153
#[cfg(feature = "u2i")]
154154
{
155-
Ok(Bson::Int64(_value as i64))
155+
Ok(Bson::Int64(value as i64))
156156
}
157157

158158
#[cfg(not(feature = "u2i"))]
159-
Err(Error::UnsupportedUnsignedType)
159+
Err(Error::UnsupportedUnsignedInteger(value as u64))
160160
}
161161

162162
#[inline]
@@ -165,19 +165,19 @@ impl ser::Serializer for Serializer {
165165
}
166166

167167
#[inline]
168-
fn serialize_u64(self, _value: u64) -> crate::ser::Result<Bson> {
168+
fn serialize_u64(self, value: u64) -> crate::ser::Result<Bson> {
169169
#[cfg(feature = "u2i")]
170170
{
171171
use std::convert::TryFrom;
172172

173-
match i64::try_from(_value) {
173+
match i64::try_from(value) {
174174
Ok(ivalue) => Ok(Bson::Int64(ivalue)),
175-
Err(_) => Err(Error::UnsignedTypesValueExceedsRange(_value)),
175+
Err(_) => Err(Error::UnsignedIntegerExceededRange(value)),
176176
}
177177
}
178178

179179
#[cfg(not(feature = "u2i"))]
180-
Err(Error::UnsupportedUnsignedType)
180+
Err(Error::UnsupportedUnsignedInteger(value))
181181
}
182182

183183
#[inline]

src/tests/modules/ser.rs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -86,7 +86,7 @@ fn dec128() {
8686
fn uint8() {
8787
let _guard = LOCK.run_concurrently();
8888
let obj_min: ser::Result<Bson> = to_bson(&u8::MIN);
89-
assert_matches!(obj_min, Err(ser::Error::UnsupportedUnsignedType));
89+
assert_matches!(obj_min, Err(ser::Error::UnsupportedUnsignedInteger(_)));
9090
}
9191

9292
#[test]
@@ -107,7 +107,7 @@ fn uint8_u2i() {
107107
fn uint16() {
108108
let _guard = LOCK.run_concurrently();
109109
let obj_min: ser::Result<Bson> = to_bson(&u16::MIN);
110-
assert_matches!(obj_min, Err(ser::Error::UnsupportedUnsignedType));
110+
assert_matches!(obj_min, Err(ser::Error::UnsupportedUnsignedInteger(_)));
111111
}
112112

113113
#[test]
@@ -128,7 +128,7 @@ fn uint16_u2i() {
128128
fn uint32() {
129129
let _guard = LOCK.run_concurrently();
130130
let obj_min: ser::Result<Bson> = to_bson(&u32::MIN);
131-
assert_matches!(obj_min, Err(ser::Error::UnsupportedUnsignedType));
131+
assert_matches!(obj_min, Err(ser::Error::UnsupportedUnsignedInteger(_)));
132132
}
133133

134134
#[test]
@@ -149,7 +149,7 @@ fn uint32_u2i() {
149149
fn uint64() {
150150
let _guard = LOCK.run_concurrently();
151151
let obj_min: ser::Result<Bson> = to_bson(&u64::MIN);
152-
assert_matches!(obj_min, Err(ser::Error::UnsupportedUnsignedType));
152+
assert_matches!(obj_min, Err(ser::Error::UnsupportedUnsignedInteger(_)));
153153
}
154154

155155
#[test]
@@ -163,7 +163,7 @@ fn uint64_u2i() {
163163
let obj_max: ser::Result<Bson> = to_bson(&u64::MAX);
164164
assert_matches!(
165165
obj_max,
166-
Err(ser::Error::UnsignedTypesValueExceedsRange(u64::MAX))
166+
Err(ser::Error::UnsignedIntegerExceededRange(u64::MAX))
167167
);
168168
}
169169

0 commit comments

Comments
 (0)