Skip to content

Commit e6263f5

Browse files
committed
Insertion-ordered BSON documents
1 parent 622270b commit e6263f5

File tree

3 files changed

+208
-5
lines changed

3 files changed

+208
-5
lines changed

src/bson.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,11 @@
2121

2222
//! BSON definition
2323
24-
use std::collections::BTreeMap;
25-
2624
use chrono::{DateTime, UTC};
2725
use rustc_serialize::json;
2826
use rustc_serialize::hex::ToHex;
2927

28+
use ordered::OrderedDocument;
3029
use spec::{ElementType, BinarySubtype};
3130

3231
/// Possible BSON value types.
@@ -51,8 +50,8 @@ pub enum Bson {
5150

5251
/// Alias for `Vec<Bson>`.
5352
pub type Array = Vec<Bson>;
54-
/// Alias for `BTreeMap<String, Bson>`.
55-
pub type Document = BTreeMap<String, Bson>;
53+
/// Alias for `OrderedDocument`.
54+
pub type Document = OrderedDocument;
5655

5756
impl Bson {
5857
/// Get the `ElementType` of this value.

src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,4 @@ pub mod spec;
5454
mod bson;
5555
mod encoder;
5656
mod decoder;
57-
57+
mod ordered;

src/ordered.rs

Lines changed: 204 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,204 @@
1+
use bson::Bson;
2+
use std::collections::BTreeMap;
3+
use std::iter::FromIterator;
4+
5+
/// A BSON document represented as an associative BTree Map with insertion ordering.
6+
#[derive(Debug, Clone)]
7+
pub struct OrderedDocument {
8+
pub keys: Vec<String>,
9+
document: BTreeMap<String, Bson>,
10+
}
11+
12+
/// An iterator over OrderedDocument entries.
13+
pub struct OrderedDocumentIterator {
14+
ordered_document: OrderedDocument,
15+
index: usize,
16+
}
17+
18+
/// An owning iterator over OrderedDocument entries.
19+
pub struct OrderedDocumentIntoIterator<'a> {
20+
ordered_document: &'a OrderedDocument,
21+
index: usize,
22+
}
23+
24+
impl IntoIterator for OrderedDocument {
25+
type Item = (String, Bson);
26+
type IntoIter = OrderedDocumentIterator;
27+
28+
fn into_iter(self) -> Self::IntoIter {
29+
OrderedDocumentIterator { ordered_document: self, index: 0 }
30+
}
31+
}
32+
33+
impl<'a> IntoIterator for &'a OrderedDocument {
34+
type Item = (&'a String, &'a Bson);
35+
type IntoIter = OrderedDocumentIntoIterator<'a>;
36+
37+
fn into_iter(self) -> Self::IntoIter {
38+
OrderedDocumentIntoIterator { ordered_document: self, index: 0 }
39+
}
40+
}
41+
42+
impl FromIterator<(String, Bson)> for OrderedDocument {
43+
fn from_iter<T: IntoIterator<Item=(String, Bson)>>(iter: T) -> Self {
44+
let mut doc = OrderedDocument::new();
45+
for (k, v) in iter {
46+
doc.insert(k, v.to_owned());
47+
}
48+
doc
49+
}
50+
}
51+
52+
impl<'a> Iterator for OrderedDocumentIterator {
53+
type Item = (String, Bson);
54+
fn next(&mut self) -> Option<(String, Bson)> {
55+
if self.ordered_document.keys.len() <= self.index {
56+
return None;
57+
}
58+
59+
let ref key = self.ordered_document.keys[self.index];
60+
let val = self.ordered_document.get(&key[..]).unwrap();
61+
self.index += 1;
62+
Some((key.to_owned(), val.to_owned()))
63+
}
64+
}
65+
66+
impl<'a> Iterator for OrderedDocumentIntoIterator<'a> {
67+
type Item = (&'a String, &'a Bson);
68+
fn next(&mut self) -> Option<(&'a String, &'a Bson)> {
69+
if self.ordered_document.keys.len() <= self.index {
70+
return None;
71+
}
72+
73+
let ref key = self.ordered_document.keys[self.index];
74+
let val = self.ordered_document.get(&key[..]).unwrap();
75+
self.index += 1;
76+
Some((key, val))
77+
}
78+
}
79+
80+
impl OrderedDocument {
81+
/// Creates a new empty OrderedDocument.
82+
pub fn new() -> OrderedDocument {
83+
OrderedDocument {
84+
keys: Vec::new(),
85+
document: BTreeMap::new(),
86+
}
87+
}
88+
89+
/// Gets an iterator over the entries of the map.
90+
pub fn iter<'a>(&'a self) -> OrderedDocumentIntoIterator<'a> {
91+
self.into_iter()
92+
}
93+
94+
/// Clears the document, removing all values.
95+
pub fn clear(&mut self) {
96+
self.keys.clear();
97+
self.document.clear();
98+
}
99+
100+
/// Returns a reference to the Bson corresponding to the key.
101+
pub fn get(&self, key: &str) -> Option<&Bson> {
102+
self.document.get(key)
103+
}
104+
105+
/// Gets a mutable reference to the value in the entry.
106+
pub fn get_mut(&mut self, key: &str) -> Option<&mut Bson> {
107+
self.document.get_mut(key)
108+
}
109+
110+
/// Returns true if the map contains a value for the specified key.
111+
pub fn contains_key(&self, key: &str) -> bool {
112+
self.document.contains_key(key)
113+
}
114+
115+
/// Returns the position of the key in the ordered vector, if it exists.
116+
pub fn position(&self, key: &str) -> Option<usize> {
117+
self.keys.iter().position(|x| x == key)
118+
}
119+
120+
/// Gets a collection of all keys in the document.
121+
pub fn keys<'a>(&'a self) -> Vec<&String> {
122+
self.iter().map(|(k, _)| k).collect()
123+
}
124+
125+
/// Gets a collection of all values in the document.
126+
pub fn values<'a>(&'a self) -> Vec<&Bson> {
127+
self.iter().map(|(_, v)| v).collect()
128+
}
129+
130+
/// Returns the number of elements in the document.
131+
pub fn len(&self) -> usize {
132+
self.keys.len()
133+
}
134+
135+
/// Returns true if the document contains no elements
136+
pub fn is_empty(&self) -> bool {
137+
self.document.is_empty()
138+
}
139+
140+
/// Sets the value of the entry with the OccupiedEntry's key,
141+
/// and returns the entry's old value.
142+
pub fn insert(&mut self, key: String, val: Bson) -> Option<Bson> {
143+
let key_slice = &key[..];
144+
145+
if self.contains_key(key_slice) {
146+
let position = self.position(key_slice).unwrap();
147+
self.keys.remove(position);
148+
}
149+
150+
self.keys.push(key.to_owned());
151+
self.document.insert(key.to_owned(), val.to_owned())
152+
}
153+
154+
/// Takes the value of the entry out of the document, and returns it.
155+
pub fn remove(&mut self, key: &str) -> Option<Bson> {
156+
let position = self.position(key);
157+
if position.is_some() {
158+
self.keys.remove(position.unwrap());
159+
}
160+
self.document.remove(key)
161+
}
162+
}
163+
164+
#[cfg(test)]
165+
mod test {
166+
use super::OrderedDocument;
167+
use bson::Bson;
168+
169+
#[test]
170+
fn ordered_insert() {
171+
let mut doc = OrderedDocument::new();
172+
doc.insert("first".to_owned(), Bson::I32(1));
173+
doc.insert("second".to_owned(), Bson::String("foo".to_owned()));
174+
doc.insert("alphanumeric".to_owned(), Bson::String("bar".to_owned()));
175+
176+
let expected_keys = vec!(
177+
"first".to_owned(),
178+
"second".to_owned(),
179+
"alphanumeric".to_owned(),
180+
);
181+
182+
let keys: Vec<_> = doc.iter().map(|(key, _)| key.to_owned()).collect();
183+
assert_eq!(expected_keys, keys);
184+
}
185+
186+
#[test]
187+
fn remove() {
188+
let mut doc = OrderedDocument::new();
189+
doc.insert("first".to_owned(), Bson::I32(1));
190+
doc.insert("second".to_owned(), Bson::String("foo".to_owned()));
191+
doc.insert("alphanumeric".to_owned(), Bson::String("bar".to_owned()));
192+
193+
assert!(doc.remove("second").is_some());
194+
assert!(doc.remove("none").is_none());
195+
196+
let expected_keys = vec!(
197+
"first",
198+
"alphanumeric",
199+
);
200+
201+
let keys: Vec<_> = doc.iter().map(|(key, _)| key.to_owned()).collect();
202+
assert_eq!(expected_keys, keys);
203+
}
204+
}

0 commit comments

Comments
 (0)