Skip to content

Commit f5beba3

Browse files
committed
Merge pull request #16 from thijsc/get_field_helpers
Helpers to directly get inner values
2 parents edc47de + d17cb2f commit f5beba3

File tree

5 files changed

+179
-5
lines changed

5 files changed

+179
-5
lines changed

src/bson.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ use spec::{ElementType, BinarySubtype};
3232
use oid;
3333

3434
/// Possible BSON value types.
35-
#[derive(Debug, Clone)]
35+
#[derive(Debug,Clone,PartialEq)]
3636
pub enum Bson {
3737
FloatingPoint(f64),
3838
String(String),

src/lib.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ extern crate time;
5353
pub use self::bson::{Bson, Document, Array};
5454
pub use self::encoder::{encode_document, EncoderResult, EncoderError};
5555
pub use self::decoder::{decode_document, DecoderResult, DecoderError};
56+
pub use self::ordered::{ValueAccessError, ValueAccessResult};
5657

5758
pub mod macros;
5859
pub mod oid;

src/oid.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ impl error::Error for Error {
7676
}
7777

7878
fn cause(&self) -> Option<&error::Error> {
79-
match self {
79+
match self {
8080
&Error::ArgumentError(_) => None,
8181
&Error::FromHexError(ref inner) => Some(inner),
8282
&Error::IoError(ref inner) => Some(inner),

src/ordered.rs

Lines changed: 113 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,24 @@
1-
use bson::Bson;
1+
use chrono::{DateTime, UTC};
2+
use bson::{Array,Bson,Document};
3+
use super::oid::ObjectId;
24
use std::collections::BTreeMap;
35
use std::fmt::{Display, Error, Formatter};
46
use std::iter::{FromIterator, Map};
57
use std::vec::IntoIter;
68
use std::slice;
79

10+
/// Error to indicate that either a value was empty or it contained an unexpected
11+
/// type, for use with the direct getters.
12+
#[derive(Debug,PartialEq)]
13+
pub enum ValueAccessError {
14+
NotPresent,
15+
UnexpectedType
16+
}
17+
18+
pub type ValueAccessResult<T> = Result<T, ValueAccessError>;
19+
820
/// A BSON document represented as an associative BTree Map with insertion ordering.
9-
#[derive(Debug, Clone)]
21+
#[derive(Debug,Clone,PartialEq)]
1022
pub struct OrderedDocument {
1123
pub keys: Vec<String>,
1224
document: BTreeMap<String, Bson>,
@@ -147,11 +159,109 @@ impl OrderedDocument {
147159
self.document.get(key)
148160
}
149161

150-
/// Gets a mutable reference to the value in the entry.
162+
/// Gets a mutable reference to the Bson corresponding to the key
151163
pub fn get_mut(&mut self, key: &str) -> Option<&mut Bson> {
152164
self.document.get_mut(key)
153165
}
154166

167+
/// Get a floating point value for this key if it exists and has
168+
/// the correct type.
169+
pub fn get_f64(&self, key: &str) -> ValueAccessResult<f64> {
170+
match self.get(key) {
171+
Some(&Bson::FloatingPoint(v)) => Ok(v),
172+
Some(_) => Err(ValueAccessError::UnexpectedType),
173+
None => Err(ValueAccessError::NotPresent)
174+
}
175+
}
176+
177+
/// Get a string slice this key if it exists and has the correct type.
178+
pub fn get_str(&self, key: &str) -> ValueAccessResult<&str> {
179+
match self.get(key) {
180+
Some(&Bson::String(ref v)) => Ok(v),
181+
Some(_) => Err(ValueAccessError::UnexpectedType),
182+
None => Err(ValueAccessError::NotPresent)
183+
}
184+
}
185+
186+
/// Get a reference to an array for this key if it exists and has
187+
/// the correct type.
188+
pub fn get_array(&self, key: &str) -> ValueAccessResult<&Array> {
189+
match self.get(key) {
190+
Some(&Bson::Array(ref v)) => Ok(v),
191+
Some(_) => Err(ValueAccessError::UnexpectedType),
192+
None => Err(ValueAccessError::NotPresent)
193+
}
194+
}
195+
196+
/// Get a reference to a document for this key if it exists and has
197+
/// the correct type.
198+
pub fn get_document(&self, key: &str) -> ValueAccessResult<&Document> {
199+
match self.get(key) {
200+
Some(&Bson::Document(ref v)) => Ok(v),
201+
Some(_) => Err(ValueAccessError::UnexpectedType),
202+
None => Err(ValueAccessError::NotPresent)
203+
}
204+
}
205+
206+
/// Get a bool value for this key if it exists and has the correct type.
207+
pub fn get_bool(&self, key: &str) -> ValueAccessResult<bool> {
208+
match self.get(key) {
209+
Some(&Bson::Boolean(v)) => Ok(v),
210+
Some(_) => Err(ValueAccessError::UnexpectedType),
211+
None => Err(ValueAccessError::NotPresent)
212+
}
213+
}
214+
215+
/// Returns wether this key has a null value
216+
pub fn is_null(&self, key: &str) -> bool {
217+
self.get(key) == Some(&Bson::Null)
218+
}
219+
220+
/// Get an i32 value for this key if it exists and has the correct type.
221+
pub fn get_i32(&self, key: &str) -> ValueAccessResult<i32> {
222+
match self.get(key) {
223+
Some(&Bson::I32(v)) => Ok(v),
224+
Some(_) => Err(ValueAccessError::UnexpectedType),
225+
None => Err(ValueAccessError::NotPresent)
226+
}
227+
}
228+
229+
/// Get an i64 value for this key if it exists and has the correct type.
230+
pub fn get_i64(&self, key: &str) -> ValueAccessResult<i64> {
231+
match self.get(key) {
232+
Some(&Bson::I64(v)) => Ok(v),
233+
Some(_) => Err(ValueAccessError::UnexpectedType),
234+
None => Err(ValueAccessError::NotPresent)
235+
}
236+
}
237+
238+
/// Get a time stamp value for this key if it exists and has the correct type.
239+
pub fn get_time_stamp(&self, key: &str) -> ValueAccessResult<i64> {
240+
match self.get(key) {
241+
Some(&Bson::TimeStamp(v)) => Ok(v),
242+
Some(_) => Err(ValueAccessError::UnexpectedType),
243+
None => Err(ValueAccessError::NotPresent)
244+
}
245+
}
246+
247+
/// Get an object id value for this key if it exists and has the correct type.
248+
pub fn get_object_id(&self, key: &str) -> ValueAccessResult<&ObjectId> {
249+
match self.get(key) {
250+
Some(&Bson::ObjectId(ref v)) => Ok(v),
251+
Some(_) => Err(ValueAccessError::UnexpectedType),
252+
None => Err(ValueAccessError::NotPresent)
253+
}
254+
}
255+
256+
/// Get a UTC datetime value for this key if it exists and has the correct type.
257+
pub fn get_utc_datetime(&self, key: &str) -> ValueAccessResult<&DateTime<UTC>> {
258+
match self.get(key) {
259+
Some(&Bson::UtcDatetime(ref v)) => Ok(v),
260+
Some(_) => Err(ValueAccessError::UnexpectedType),
261+
None => Err(ValueAccessError::NotPresent)
262+
}
263+
}
264+
155265
/// Returns true if the map contains a value for the specified key.
156266
pub fn contains_key(&self, key: &str) -> bool {
157267
self.document.contains_key(key)

tests/modules/ordered.rs

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
11
use bson::{Bson, Document};
2+
use bson::ValueAccessError;
3+
use bson::oid::ObjectId;
4+
use chrono::UTC;
25

36
#[test]
47
fn ordered_insert() {
@@ -34,6 +37,66 @@ fn ordered_insert_shorthand() {
3437
assert_eq!(expected_keys, keys);
3538
}
3639

40+
#[test]
41+
fn test_getters() {
42+
let datetime = UTC::now();
43+
let cloned_dt = datetime.clone();
44+
let mut doc = doc! {
45+
"floating_point" => 10.0,
46+
"string" => "a value",
47+
"array" => [10, 20, 30],
48+
"doc" => { "key" => 1 },
49+
"bool" => true,
50+
"i32" => 1i32,
51+
"i64" => 1i64,
52+
"datetime" => cloned_dt
53+
};
54+
55+
assert_eq!(None, doc.get("nonsense"));
56+
assert_eq!(Err(ValueAccessError::NotPresent), doc.get_str("nonsense"));
57+
assert_eq!(Err(ValueAccessError::UnexpectedType), doc.get_str("floating_point"));
58+
59+
assert_eq!(Some(&Bson::FloatingPoint(10.0)), doc.get("floating_point"));
60+
assert_eq!(Ok(10.0), doc.get_f64("floating_point"));
61+
62+
assert_eq!(Some(&Bson::String("a value".to_string())), doc.get("string"));
63+
assert_eq!(Ok("a value"), doc.get_str("string"));
64+
65+
let array = vec![Bson::I32(10), Bson::I32(20), Bson::I32(30)];
66+
assert_eq!(Some(&Bson::Array(array.clone())), doc.get("array"));
67+
assert_eq!(Ok(&array), doc.get_array("array"));
68+
69+
let embedded = doc! { "key" => 1 };
70+
assert_eq!(Some(&Bson::Document(embedded.clone())), doc.get("doc"));
71+
assert_eq!(Ok(&embedded), doc.get_document("doc"));
72+
73+
assert_eq!(Some(&Bson::Boolean(true)), doc.get("bool"));
74+
assert_eq!(Ok(true), doc.get_bool("bool"));
75+
76+
doc.insert("null".to_string(), Bson::Null);
77+
assert_eq!(Some(&Bson::Null), doc.get("null"));
78+
assert_eq!(true, doc.is_null("null"));
79+
assert_eq!(false, doc.is_null("array"));
80+
81+
assert_eq!(Some(&Bson::I32(1)), doc.get("i32"));
82+
assert_eq!(Ok(1i32), doc.get_i32("i32"));
83+
84+
assert_eq!(Some(&Bson::I64(1)), doc.get("i64"));
85+
assert_eq!(Ok(1i64), doc.get_i64("i64"));
86+
87+
doc.insert("timestamp".to_string(), Bson::TimeStamp(100));
88+
assert_eq!(Some(&Bson::TimeStamp(100)), doc.get("timestamp"));
89+
assert_eq!(Ok(100i64), doc.get_time_stamp("timestamp"));
90+
91+
let object_id = ObjectId::new().unwrap();
92+
doc.insert("_id".to_string(), Bson::ObjectId(object_id.clone()));
93+
assert_eq!(Some(&Bson::ObjectId(object_id.clone())), doc.get("_id"));
94+
assert_eq!(Ok(&object_id), doc.get_object_id("_id"));
95+
96+
assert_eq!(Some(&Bson::UtcDatetime(datetime.clone())), doc.get("datetime"));
97+
assert_eq!(Ok(&datetime), doc.get_utc_datetime("datetime"));
98+
}
99+
37100
#[test]
38101
fn remove() {
39102
let mut doc = Document::new();

0 commit comments

Comments
 (0)