Skip to content

Commit 3cbf444

Browse files
RUST-1406 Add type-specific errors to standard error type (#555)
1 parent 1669bc0 commit 3cbf444

File tree

19 files changed

+492
-456
lines changed

19 files changed

+492
-456
lines changed

src/binary.rs

Lines changed: 10 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,18 @@
11
#! Module containing functionality related to BSON binary values.
2-
32
mod vector;
43

5-
use crate::{base64, spec::BinarySubtype, RawBinaryRef};
64
use std::{
7-
error,
5+
convert::TryFrom,
86
fmt::{self, Display},
97
};
108

9+
use crate::{
10+
base64,
11+
error::{Error, Result},
12+
spec::BinarySubtype,
13+
RawBinaryRef,
14+
};
15+
1116
pub use vector::{PackedBitVector, Vector};
1217

1318
/// Represents a BSON binary value.
@@ -37,7 +42,7 @@ impl Binary {
3742
/// [`BinarySubtype::Generic`].
3843
///
3944
/// ```rust
40-
/// # use bson::{Binary, binary::Result};
45+
/// # use bson::{Binary, error::Result};
4146
/// # fn example() -> Result<()> {
4247
/// let input = base64::encode("hello");
4348
/// let binary = Binary::from_base64(input, None)?;
@@ -50,9 +55,7 @@ impl Binary {
5055
input: impl AsRef<str>,
5156
subtype: impl Into<Option<BinarySubtype>>,
5257
) -> Result<Self> {
53-
let bytes = base64::decode(input.as_ref()).map_err(|e| Error::DecodingError {
54-
message: e.to_string(),
55-
})?;
58+
let bytes = base64::decode(input.as_ref()).map_err(Error::binary)?;
5659
let subtype = match subtype.into() {
5760
Some(s) => s,
5861
None => BinarySubtype::Generic,
@@ -97,27 +100,3 @@ impl Binary {
97100
}
98101
}
99102
}
100-
101-
/// Possible errors that can arise during [`Binary`] construction.
102-
#[derive(Clone, Debug)]
103-
#[non_exhaustive]
104-
pub enum Error {
105-
/// While trying to decode from base64, an error was returned.
106-
DecodingError { message: String },
107-
108-
/// A [`Vector`]-related error occurred.
109-
Vector { message: String },
110-
}
111-
112-
impl error::Error for Error {}
113-
114-
impl std::fmt::Display for Error {
115-
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
116-
match self {
117-
Error::DecodingError { message } => fmt.write_str(message),
118-
Error::Vector { message } => fmt.write_str(message),
119-
}
120-
}
121-
}
122-
123-
pub type Result<T> = std::result::Result<T, Error>;

src/binary/vector.rs

Lines changed: 26 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ const PACKED_BIT: u8 = 0x10;
2323
///
2424
/// ```rust
2525
/// # use serde::{Serialize, Deserialize};
26-
/// # use bson::{binary::{Result, Vector}, spec::ElementType};
26+
/// # use bson::{binary::Vector, error::Result, spec::ElementType};
2727
/// #[derive(Serialize, Deserialize)]
2828
/// struct Data {
2929
/// vector: Vector,
@@ -64,7 +64,7 @@ impl PackedBitVector {
6464
/// single-bit elements in little-endian format. For example, the following vector:
6565
///
6666
/// ```rust
67-
/// # use bson::binary::{Result, PackedBitVector};
67+
/// # use bson::{binary::PackedBitVector, error::Result};
6868
/// # fn main() -> Result<()> {
6969
/// let packed_bits = vec![238, 224];
7070
/// let vector = PackedBitVector::new(packed_bits, 0)?;
@@ -91,17 +91,14 @@ impl PackedBitVector {
9191
pub fn new(vector: Vec<u8>, padding: impl Into<Option<u8>>) -> Result<Self> {
9292
let padding = padding.into().unwrap_or(0);
9393
if !(0..8).contains(&padding) {
94-
return Err(Error::Vector {
95-
message: format!("padding must be within 0-7 inclusive, got {}", padding),
96-
});
94+
return Err(Error::binary(format!(
95+
"vector padding must be within 0-7 inclusive, got {padding}"
96+
)));
9797
}
9898
if padding != 0 && vector.is_empty() {
99-
return Err(Error::Vector {
100-
message: format!(
101-
"cannot specify non-zero padding if the provided vector is empty, got {}",
102-
padding
103-
),
104-
});
99+
return Err(Error::binary(format!(
100+
"cannot specify non-zero padding if the provided vector is empty, got {padding}",
101+
)));
105102
}
106103
Ok(Self { vector, padding })
107104
}
@@ -115,24 +112,19 @@ impl Vector {
115112
let bytes = bytes.as_ref();
116113

117114
if bytes.len() < 2 {
118-
return Err(Error::Vector {
119-
message: format!(
120-
"the provided bytes must have a length of at least 2, got {}",
121-
bytes.len()
122-
),
123-
});
115+
return Err(Error::binary(format!(
116+
"the provided vector bytes must have a length of at least 2, got {}",
117+
bytes.len()
118+
)));
124119
}
125120

126121
let d_type = bytes[0];
127122
let padding = bytes[1];
128123
if d_type != PACKED_BIT && padding != 0 {
129-
return Err(Error::Vector {
130-
message: format!(
131-
"padding can only be specified for a packed bit vector (data type {}), got \
132-
type {}",
133-
PACKED_BIT, d_type
134-
),
135-
});
124+
return Err(Error::binary(format!(
125+
"padding can only be specified for a packed bit vector (data type {}), got type {}",
126+
PACKED_BIT, d_type
127+
)));
136128
}
137129
let number_bytes = &bytes[2..];
138130

@@ -149,11 +141,11 @@ impl Vector {
149141

150142
let mut vector = Vec::new();
151143
for chunk in number_bytes.chunks(F32_BYTES) {
152-
let bytes: [u8; F32_BYTES] = chunk.try_into().map_err(|_| Error::Vector {
153-
message: format!(
144+
let bytes: [u8; F32_BYTES] = chunk.try_into().map_err(|_| {
145+
Error::binary(format!(
154146
"f32 vector values must be {} bytes, got {:?}",
155147
F32_BYTES, chunk,
156-
),
148+
))
157149
})?;
158150
vector.push(f32::from_le_bytes(bytes));
159151
}
@@ -163,9 +155,9 @@ impl Vector {
163155
let packed_bit_vector = PackedBitVector::new(number_bytes.to_vec(), padding)?;
164156
Ok(Self::PackedBit(packed_bit_vector))
165157
}
166-
other => Err(Error::Vector {
167-
message: format!("unsupported vector data type: {}", other),
168-
}),
158+
other => Err(Error::binary(format!(
159+
"unsupported vector data type: {other}"
160+
))),
169161
}
170162
}
171163

@@ -228,9 +220,10 @@ impl TryFrom<&Binary> for Vector {
228220

229221
fn try_from(binary: &Binary) -> Result<Self> {
230222
if binary.subtype != BinarySubtype::Vector {
231-
return Err(Error::Vector {
232-
message: format!("expected vector binary subtype, got {:?}", binary.subtype),
233-
});
223+
return Err(Error::binary(format!(
224+
"expected vector binary subtype, got {:?}",
225+
binary.subtype
226+
)));
234227
}
235228
Self::from_bytes(&binary.bytes)
236229
}

src/datetime.rs

Lines changed: 7 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,24 @@
11
//! Module containing functionality related to BSON DateTimes.
22
//! For more information, see the documentation for the [`DateTime`] type.
3+
pub(crate) mod builder;
34

45
use std::{
56
convert::TryInto,
6-
error,
77
fmt::{self, Display},
8-
result,
98
time::{Duration, SystemTime},
109
};
1110

12-
pub(crate) mod builder;
13-
pub use crate::datetime::builder::DateTimeBuilder;
14-
use time::format_description::well_known::Rfc3339;
15-
1611
#[cfg(feature = "chrono-0_4")]
1712
use chrono::{LocalResult, TimeZone, Utc};
1813
#[cfg(all(
1914
feature = "serde_with-3",
2015
any(feature = "chrono-0_4", feature = "time-0_3")
2116
))]
2217
use serde::{Deserialize, Deserializer, Serialize};
18+
use time::format_description::well_known::Rfc3339;
19+
20+
pub use crate::datetime::builder::DateTimeBuilder;
21+
use crate::error::{Error, Result};
2322

2423
/// Struct representing a BSON datetime.
2524
/// Note: BSON datetimes have millisecond precision.
@@ -388,21 +387,13 @@ impl crate::DateTime {
388387

389388
/// Convert this [`DateTime`] to an RFC 3339 formatted string.
390389
pub fn try_to_rfc3339_string(self) -> Result<String> {
391-
self.to_time_0_3()
392-
.format(&Rfc3339)
393-
.map_err(|e| Error::CannotFormat {
394-
message: e.to_string(),
395-
})
390+
self.to_time_0_3().format(&Rfc3339).map_err(Error::datetime)
396391
}
397392

398393
/// Convert the given RFC 3339 formatted string to a [`DateTime`], truncating it to millisecond
399394
/// precision.
400395
pub fn parse_rfc3339_str(s: impl AsRef<str>) -> Result<Self> {
401-
let odt = time::OffsetDateTime::parse(s.as_ref(), &Rfc3339).map_err(|e| {
402-
Error::InvalidTimestamp {
403-
message: e.to_string(),
404-
}
405-
})?;
396+
let odt = time::OffsetDateTime::parse(s.as_ref(), &Rfc3339).map_err(Error::datetime)?;
406397
Ok(Self::from_time_0_3(odt))
407398
}
408399

@@ -543,30 +534,3 @@ impl serde_with::SerializeAs<time::OffsetDateTime> for crate::DateTime {
543534
dt.serialize(serializer)
544535
}
545536
}
546-
547-
/// Errors that can occur during [`DateTime`] construction and generation.
548-
#[derive(Clone, Debug)]
549-
#[non_exhaustive]
550-
pub enum Error {
551-
/// Error returned when an invalid datetime format is provided to a conversion method.
552-
#[non_exhaustive]
553-
InvalidTimestamp { message: String },
554-
/// Error returned when a [`DateTime`] cannot be represented in a particular format.
555-
#[non_exhaustive]
556-
CannotFormat { message: String },
557-
}
558-
559-
/// Alias for `Result<T, DateTime::Error>`
560-
pub type Result<T> = result::Result<T, Error>;
561-
562-
impl fmt::Display for Error {
563-
fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
564-
match self {
565-
Error::InvalidTimestamp { message } | Error::CannotFormat { message } => {
566-
write!(fmt, "{}", message)
567-
}
568-
}
569-
}
570-
}
571-
572-
impl error::Error for Error {}

src/datetime/builder.rs

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
1-
use super::*;
21
use std::convert::TryFrom;
2+
33
use time::Date;
44

5+
use crate::{
6+
datetime::DateTime,
7+
error::{Error, Result},
8+
};
9+
510
/// Builder for constructing a BSON [`DateTime`]
611
pub struct DateTimeBuilder<Y = NoYear, M = NoMonth, D = NoDay> {
712
pub(crate) year: Y,
@@ -169,19 +174,16 @@ impl DateTimeBuilder<Year, Month, Day> {
169174
///
170175
/// Note: You cannot call `build()` before setting at least the year, month and day.
171176
pub fn build(self) -> Result<DateTime> {
172-
let err = |e: time::error::ComponentRange| Error::InvalidTimestamp {
173-
message: e.to_string(),
174-
};
175-
let month = time::Month::try_from(self.month.0).map_err(err)?;
177+
let month = time::Month::try_from(self.month.0).map_err(Error::datetime)?;
176178
let dt = Date::from_calendar_date(self.year.0, month, self.day.0)
177-
.map_err(err)?
179+
.map_err(Error::datetime)?
178180
.with_hms_milli(
179181
self.hour.unwrap_or(0),
180182
self.minute.unwrap_or(0),
181183
self.second.unwrap_or(0),
182184
self.millisecond.unwrap_or(0),
183185
)
184-
.map_err(err)?;
186+
.map_err(Error::datetime)?;
185187
Ok(DateTime::from_time_private(dt.assume_utc()))
186188
}
187189
}

0 commit comments

Comments
 (0)