use bson::Bson;
use std::collections::BTreeMap;
use std::fmt::{Display, Error, Formatter};
use std::iter::{FromIterator, Map};
use std::vec::IntoIter;
use std::slice;
#[derive(Debug, Clone)]
pub struct OrderedDocument {
pub keys: Vec<String>,
document: BTreeMap<String, Bson>,
}
impl Display for OrderedDocument {
fn fmt(&self, fmt: &mut Formatter) -> Result<(), Error> {
let mut string = "{ ".to_owned();
for (key, value) in self.iter() {
if !string.eq("{ ") {
string.push_str(", ");
}
string.push_str(&format!("{}: {}", key, value));
}
string.push_str(" }");
fmt.write_str(&string)
}
}
pub struct OrderedDocumentIntoIterator {
vec_iter: IntoIter<String>,
document: BTreeMap<String, Bson>,
}
pub struct OrderedDocumentIterator<'a> {
vec_iter: slice::Iter<'a, String>,
document: &'a BTreeMap<String, Bson>,
}
pub struct Keys<'a> {
inner: Map<OrderedDocumentIterator<'a>, fn((&'a String, &'a Bson)) -> &'a String>
}
pub struct Values<'a> {
inner: Map<OrderedDocumentIterator<'a>, fn((&'a String, &'a Bson)) -> &'a Bson>
}
impl<'a> Iterator for Keys<'a> {
type Item = &'a String;
fn next(&mut self) -> Option<(&'a String)> { self.inner.next() }
}
impl<'a> Iterator for Values<'a> {
type Item = &'a Bson;
fn next(&mut self) -> Option<(&'a Bson)> { self.inner.next() }
}
impl IntoIterator for OrderedDocument {
type Item = (String, Bson);
type IntoIter = OrderedDocumentIntoIterator;
fn into_iter(self) -> Self::IntoIter {
OrderedDocumentIntoIterator {
document: self.document,
vec_iter: self.keys.into_iter()
}
}
}
impl<'a> IntoIterator for &'a OrderedDocument {
type Item = (&'a String, &'a Bson);
type IntoIter = OrderedDocumentIterator<'a>;
fn into_iter(self) -> Self::IntoIter {
let ref keys = self.keys;
OrderedDocumentIterator {
vec_iter: keys.into_iter(),
document: &self.document,
}
}
}
impl FromIterator<(String, Bson)> for OrderedDocument {
fn from_iter<T: IntoIterator<Item=(String, Bson)>>(iter: T) -> Self {
let mut doc = OrderedDocument::new();
for (k, v) in iter {
doc.insert(k, v.to_owned());
}
doc
}
}
impl<'a> Iterator for OrderedDocumentIntoIterator {
type Item = (String, Bson);
fn next(&mut self) -> Option<(String, Bson)> {
match self.vec_iter.next() {
Some(key) => {
let val = self.document.remove(&key[..]).unwrap();
Some((key, val.to_owned()))
},
None => None,
}
}
}
impl<'a> Iterator for OrderedDocumentIterator<'a> {
type Item = (&'a String, &'a Bson);
fn next(&mut self) -> Option<(&'a String, &'a Bson)> {
match self.vec_iter.next() {
Some(key) => {
let val = self.document.get(&key[..]).unwrap();
Some((&key, val))
},
None => None,
}
}
}
impl OrderedDocument {
pub fn new() -> OrderedDocument {
OrderedDocument {
keys: Vec::new(),
document: BTreeMap::new(),
}
}
pub fn iter<'a>(&'a self) -> OrderedDocumentIterator<'a> {
self.into_iter()
}
pub fn clear(&mut self) {
self.keys.clear();
self.document.clear();
}
pub fn get(&self, key: &str) -> Option<&Bson> {
self.document.get(key)
}
pub fn get_mut(&mut self, key: &str) -> Option<&mut Bson> {
self.document.get_mut(key)
}
pub fn contains_key(&self, key: &str) -> bool {
self.document.contains_key(key)
}
pub fn position(&self, key: &str) -> Option<usize> {
self.keys.iter().position(|x| x == key)
}
pub fn keys<'a>(&'a self) -> Keys<'a> {
fn first<A, B>((a, _): (A, B)) -> A { a }
let first: fn((&'a String, &'a Bson)) -> &'a String = first;
Keys { inner: self.iter().map(first) }
}
pub fn values<'a>(&'a self) -> Values<'a> {
fn second<A, B>((_, b): (A, B)) -> B { b }
let second: fn((&'a String, &'a Bson)) -> &'a Bson = second;
Values { inner: self.iter().map(second) }
}
pub fn len(&self) -> usize {
self.keys.len()
}
pub fn is_empty(&self) -> bool {
self.document.is_empty()
}
pub fn insert(&mut self, key: String, val: Bson) -> Option<Bson> {
let key_slice = &key[..];
if self.contains_key(key_slice) {
let position = self.position(key_slice).unwrap();
self.keys.remove(position);
}
self.keys.push(key.to_owned());
self.document.insert(key.to_owned(), val.to_owned())
}
pub fn remove(&mut self, key: &str) -> Option<Bson> {
let position = self.position(key);
if position.is_some() {
self.keys.remove(position.unwrap());
}
self.document.remove(key)
}
}