Skip to content

Commit 9444b87

Browse files
restructure, maintain oid structure
1 parent bed3232 commit 9444b87

File tree

5 files changed

+142
-86
lines changed

5 files changed

+142
-86
lines changed

src/error.rs

Lines changed: 11 additions & 70 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,14 @@
11
mod datetime;
2+
mod oid;
23
mod uuid;
4+
mod value_access;
35

46
use thiserror::Error;
57

6-
use crate::spec::ElementType;
7-
88
pub use datetime::DateTimeErrorKind;
9+
pub use oid::ObjectIdErrorKind;
910
pub use uuid::UuidErrorKind;
11+
pub use value_access::ValueAccessErrorKind;
1012

1113
pub type Result<T> = std::result::Result<T, Error>;
1214

@@ -63,6 +65,13 @@ pub enum ErrorKind {
6365
message: String,
6466
},
6567

68+
/// An error related to the [`ObjectId`](crate::oid::ObjectId) type occurred.
69+
#[error("An ObjectId-related error occurred: {kind}")]
70+
ObjectId {
71+
/// The kind of error that occurred.
72+
kind: ObjectIdErrorKind,
73+
},
74+
6675
/// Invalid UTF-8 bytes were encountered.
6776
#[error("Invalid UTF-8")]
6877
Utf8Encoding,
@@ -93,31 +102,6 @@ impl From<ErrorKind> for Error {
93102
}
94103
}
95104

96-
/// The types of errors that can occur when attempting to access a value in a document.
97-
#[derive(Clone, Debug, Error)]
98-
#[non_exhaustive]
99-
pub enum ValueAccessErrorKind {
100-
/// No value for the specified key was present in the document.
101-
#[error("The key was not present in the document")]
102-
NotPresent,
103-
104-
/// The type of the value in the document did not match the requested type.
105-
#[error("Expected type {expected:?}, got type {actual:?}")]
106-
#[non_exhaustive]
107-
UnexpectedType {
108-
/// The actual type of the value.
109-
actual: ElementType,
110-
111-
/// The expected type of the value.
112-
expected: ElementType,
113-
},
114-
115-
/// An error occurred when attempting to parse the document's BSON bytes.
116-
#[error("{message}")]
117-
#[non_exhaustive]
118-
InvalidBson { message: String },
119-
}
120-
121105
impl Error {
122106
pub(crate) fn with_key(mut self, key: impl Into<String>) -> Self {
123107
self.key = Some(key.into());
@@ -129,27 +113,6 @@ impl Error {
129113
self
130114
}
131115

132-
pub(crate) fn value_access_not_present() -> Self {
133-
ErrorKind::ValueAccess {
134-
kind: ValueAccessErrorKind::NotPresent,
135-
}
136-
.into()
137-
}
138-
139-
pub(crate) fn value_access_unexpected_type(actual: ElementType, expected: ElementType) -> Self {
140-
ErrorKind::ValueAccess {
141-
kind: ValueAccessErrorKind::UnexpectedType { actual, expected },
142-
}
143-
.into()
144-
}
145-
146-
pub(crate) fn value_access_invalid_bson(message: String) -> Self {
147-
ErrorKind::ValueAccess {
148-
kind: ValueAccessErrorKind::InvalidBson { message },
149-
}
150-
.into()
151-
}
152-
153116
pub(crate) fn malformed_bytes(message: impl ToString) -> Self {
154117
ErrorKind::MalformedBytes {
155118
message: message.to_string(),
@@ -163,26 +126,4 @@ impl Error {
163126
}
164127
.into()
165128
}
166-
167-
#[cfg(test)]
168-
pub(crate) fn is_value_access_not_present(&self) -> bool {
169-
matches!(
170-
self.kind,
171-
ErrorKind::ValueAccess {
172-
kind: ValueAccessErrorKind::NotPresent,
173-
..
174-
}
175-
)
176-
}
177-
178-
#[cfg(test)]
179-
pub(crate) fn is_value_access_unexpected_type(&self) -> bool {
180-
matches!(
181-
self.kind,
182-
ErrorKind::ValueAccess {
183-
kind: ValueAccessErrorKind::UnexpectedType { .. },
184-
..
185-
}
186-
)
187-
}
188129
}

src/error/datetime.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ use thiserror::Error as ThisError;
22

33
use crate::error::{Error, ErrorKind};
44

5+
/// The kinds of errors that can occur when working with the [`DateTime`](crate::DateTime) type.
56
#[derive(Clone, Debug, ThisError)]
67
pub enum DateTimeErrorKind {
78
/// The `DateTime` could not be formatted.

src/error/oid.rs

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
use hex::FromHexError;
2+
use thiserror::Error as ThisError;
3+
4+
use crate::error::{Error, ErrorKind};
5+
6+
/// The kinds of errors that can occur when working with the [`ObjectId`](crate::oid::ObjectId)
7+
/// type.
8+
#[derive(Clone, Debug, ThisError)]
9+
pub enum ObjectIdErrorKind {
10+
/// An invalid character was found in the provided hex string. Valid characters are: `0...9`,
11+
/// `a...f`, or `A...F`.
12+
#[error("invalid character '{c}' encountered at index {index}")]
13+
#[non_exhaustive]
14+
InvalidHexStringCharacter {
15+
/// The invalid character.
16+
c: char,
17+
18+
/// The index at which the invalid character was encountered.
19+
index: usize,
20+
},
21+
22+
/// An `ObjectId` with an invalid length was encountered.
23+
#[error("invalid hex string length {length}")]
24+
#[non_exhaustive]
25+
InvalidHexStringLength {
26+
/// The length of the invalid hex string.
27+
length: usize,
28+
},
29+
}
30+
31+
impl Error {
32+
// This method is not a From implementation so that it is not part of the public API.
33+
pub(crate) fn from_hex_error(error: FromHexError, length: usize) -> Self {
34+
let kind = match error {
35+
FromHexError::InvalidHexCharacter { c, index } => {
36+
ObjectIdErrorKind::InvalidHexStringCharacter { c, index }
37+
}
38+
FromHexError::InvalidStringLength | FromHexError::OddLength => {
39+
ObjectIdErrorKind::InvalidHexStringLength { length }
40+
}
41+
};
42+
ErrorKind::ObjectId { kind }.into()
43+
}
44+
45+
pub(crate) fn oid_invalid_length(length: usize) -> Self {
46+
ErrorKind::ObjectId {
47+
kind: ObjectIdErrorKind::InvalidHexStringLength { length },
48+
}
49+
.into()
50+
}
51+
}

src/error/value_access.rs

Lines changed: 76 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,76 @@
1+
use thiserror::Error as ThisError;
2+
3+
use crate::{
4+
error::{Error, ErrorKind},
5+
spec::ElementType,
6+
};
7+
8+
/// The types of errors that can occur when attempting to access a value in a document.
9+
#[derive(Clone, Debug, ThisError)]
10+
#[non_exhaustive]
11+
pub enum ValueAccessErrorKind {
12+
/// No value for the specified key was present in the document.
13+
#[error("the key was not present in the document")]
14+
NotPresent,
15+
16+
/// The type of the value in the document did not match the requested type.
17+
#[error("expected type {expected:?}, got type {actual:?}")]
18+
#[non_exhaustive]
19+
UnexpectedType {
20+
/// The actual type of the value.
21+
actual: ElementType,
22+
23+
/// The expected type of the value.
24+
expected: ElementType,
25+
},
26+
27+
/// An error occurred when attempting to parse the document's BSON bytes.
28+
#[error("{message}")]
29+
#[non_exhaustive]
30+
InvalidBson { message: String },
31+
}
32+
33+
impl Error {
34+
pub(crate) fn value_access_not_present() -> Self {
35+
ErrorKind::ValueAccess {
36+
kind: ValueAccessErrorKind::NotPresent,
37+
}
38+
.into()
39+
}
40+
41+
pub(crate) fn value_access_unexpected_type(actual: ElementType, expected: ElementType) -> Self {
42+
ErrorKind::ValueAccess {
43+
kind: ValueAccessErrorKind::UnexpectedType { actual, expected },
44+
}
45+
.into()
46+
}
47+
48+
pub(crate) fn value_access_invalid_bson(message: String) -> Self {
49+
ErrorKind::ValueAccess {
50+
kind: ValueAccessErrorKind::InvalidBson { message },
51+
}
52+
.into()
53+
}
54+
55+
#[cfg(test)]
56+
pub(crate) fn is_value_access_not_present(&self) -> bool {
57+
matches!(
58+
self.kind,
59+
ErrorKind::ValueAccess {
60+
kind: ValueAccessErrorKind::NotPresent,
61+
..
62+
}
63+
)
64+
}
65+
66+
#[cfg(test)]
67+
pub(crate) fn is_value_access_unexpected_type(&self) -> bool {
68+
matches!(
69+
self.kind,
70+
ErrorKind::ValueAccess {
71+
kind: ValueAccessErrorKind::UnexpectedType { .. },
72+
..
73+
}
74+
)
75+
}
76+
}

src/oid.rs

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,6 @@ use std::{
99
sync::atomic::{AtomicUsize, Ordering},
1010
};
1111

12-
use hex::{self, FromHexError};
1312
use once_cell::sync::Lazy;
1413
use rand::{random, rng, Rng};
1514

@@ -154,22 +153,10 @@ impl ObjectId {
154153
pub fn parse_str(s: impl AsRef<str>) -> Result<ObjectId> {
155154
let s = s.as_ref();
156155

157-
let bytes: Vec<u8> = hex::decode(s.as_bytes()).map_err(|e| {
158-
let message = match e {
159-
FromHexError::InvalidHexCharacter { c, index } => {
160-
format!("invalid hex character {c} encountered at index {index}")
161-
}
162-
FromHexError::InvalidStringLength | FromHexError::OddLength => {
163-
format!("invalid hex string length {}", s.len())
164-
}
165-
};
166-
Error::invalid_value(message)
167-
})?;
156+
let bytes: Vec<u8> =
157+
hex::decode(s.as_bytes()).map_err(|e| Error::from_hex_error(e, s.len()))?;
168158
if bytes.len() != 12 {
169-
Err(Error::invalid_value(format!(
170-
"invalid object ID byte vector length {}",
171-
bytes.len()
172-
)))
159+
Err(Error::oid_invalid_length(bytes.len()))
173160
} else {
174161
let mut byte_array: [u8; 12] = [0; 12];
175162
byte_array[..].copy_from_slice(&bytes[..]);

0 commit comments

Comments
 (0)