use bson::{Bson, Document};
use json::options::FromJson;
use mongodb::coll::options::{AggregateOptions, CountOptions,
FindOneAndDeleteOptions, FindOneAndUpdateOptions, FindOptions};
use rustc_serialize::json::Object;
pub enum Arguments {
Aggregate {
pipeline: Vec<Document>,
options: AggregateOptions,
out: bool,
},
Count {
filter: Option<Document>,
options: CountOptions,
},
Delete {
filter: Document,
many: bool,
},
Distinct {
field_name: String,
filter: Option<Document>,
},
Find {
filter: Option<Document>,
options: FindOptions,
},
FindOneAndDelete {
filter: Document,
options: FindOneAndDeleteOptions,
},
FindOneAndReplace {
filter: Document,
replacement: Document,
options: FindOneAndUpdateOptions,
},
FindOneAndUpdate {
filter: Document,
update: Document,
options: FindOneAndUpdateOptions,
},
InsertOne {
document: Document,
},
InsertMany {
documents: Vec<Document>,
},
ReplaceOne {
filter: Document,
replacement: Document,
upsert: bool,
},
Update {
filter: Document,
update: Document,
upsert: bool,
many: bool,
}
}
impl Arguments {
pub fn aggregate_from_json(object: &Object) -> Result<Arguments, String> {
let options = AggregateOptions::from_json(object);
let f = |x| Some(Bson::from_json(x));
let array = val_or_err!(object.get("pipeline").and_then(f),
Some(Bson::Array(arr)) => arr,
"`aggregate` requires pipeline array");
let mut docs = vec![];
let mut out = false;
for bson in array {
let doc = match bson {
Bson::Document(doc) => {
out = out || doc.contains_key("$out");
doc
},
_ => return Err("aggregate pipeline can only contain documents".to_owned())
};
docs.push(doc);
}
Ok(Arguments::Aggregate { pipeline: docs, options: options, out: out })
}
pub fn count_from_json(object: &Object) -> Arguments {
let options = CountOptions::from_json(object);
let f = |x| Some(Bson::from_json(x));
let filter = match object.get("filter").and_then(f) {
Some(Bson::Document(doc)) => Some(doc),
_ => None
};
Arguments::Count { filter: filter, options: options }
}
pub fn delete_from_json(object: &Object,
many: bool) -> Result<Arguments, String> {
let f = |x| Some(Bson::from_json(x));
let document = val_or_err!(object.get("filter").and_then(f),
Some(Bson::Document(doc)) => doc,
"`delete` requires document");
Ok(Arguments::Delete { filter: document, many: many })
}
pub fn distinct_from_json(object: &Object) -> Result<Arguments, String> {
let f = |x| Some(Bson::from_json(x));
let field_name = val_or_err!(object.get("fieldName").and_then(f),
Some(Bson::String(ref s)) => s.to_owned(),
"`distinct` requires field name");
let f = |x| Some(Bson::from_json(x));
let filter = match object.get("filter").and_then(f) {
Some(Bson::Document(doc)) => Some(doc),
_ => None
};
Ok(Arguments::Distinct { field_name: field_name, filter: filter })
}
pub fn find_from_json(object: &Object) -> Arguments {
let options = FindOptions::from_json(object);
let f = |x| Some(Bson::from_json(x));
let filter = match object.get("filter").and_then(f) {
Some(Bson::Document(doc)) => Some(doc),
_ => None
};
Arguments::Find { filter: filter, options: options }
}
pub fn find_one_and_delete_from_json(object: &Object) -> Result<Arguments, String> {
let options = FindOneAndDeleteOptions::from_json(object);
let f = |x| Some(Bson::from_json(x));
let filter = val_or_err!(object.get("filter").and_then(f),
Some(Bson::Document(doc)) => doc,
"`find_one_and_delete` requires filter document");
Ok(Arguments::FindOneAndDelete { filter: filter, options: options })
}
pub fn find_one_and_replace_from_json(object: &Object) -> Result<Arguments, String> {
let options = FindOneAndUpdateOptions::from_json(object);
let f = |x| Some(Bson::from_json(x));
let filter = val_or_err!(object.get("filter").and_then(f),
Some(Bson::Document(doc)) => doc,
"`find_one_and_update` requires filter document");
let f = |x| Some(Bson::from_json(x));
let replacement = val_or_err!(object.get("replacement").and_then(f),
Some(Bson::Document(doc)) => doc,
"`find_one_and_replace` requires replacement document");
Ok(Arguments::FindOneAndReplace { filter: filter,
replacement: replacement,
options: options })
}
pub fn find_one_and_update_from_json(object: &Object) -> Result<Arguments, String> {
let options = FindOneAndUpdateOptions::from_json(object);
let f = |x| Some(Bson::from_json(x));
let filter = val_or_err!(object.get("filter").and_then(f),
Some(Bson::Document(doc)) => doc,
"`find_one_and_update` requires filter document");
let f = |x| Some(Bson::from_json(x));
let update = val_or_err!(object.get("update").and_then(f),
Some(Bson::Document(doc)) => doc,
"`find_one_and_update` requires update document");
Ok(Arguments::FindOneAndUpdate { filter: filter, update: update,
options: options })
}
pub fn insert_many_from_json(object: &Object) -> Result<Arguments, String> {
let f = |x| Some(Bson::from_json(x));
let bsons = val_or_err!(object.get("documents").and_then(f),
Some(Bson::Array(arr)) => arr,
"`insert_many` requires documents");
let mut docs = vec![];
for bson in bsons.into_iter() {
match bson {
Bson::Document(doc) => docs.push(doc),
_ => return Err("`insert_many` can only insert documents".to_owned())
};
}
Ok(Arguments::InsertMany { documents: docs })
}
pub fn insert_one_from_json(object: &Object) -> Result<Arguments, String> {
let f = |x| Some(Bson::from_json(x));
let document = val_or_err!(object.get("document").and_then(f),
Some(Bson::Document(doc)) => doc,
"`delete_one` requires document");
Ok(Arguments::InsertOne { document: document })
}
pub fn replace_one_from_json(object: &Object) -> Result<Arguments, String> {
let f = |x| Some(Bson::from_json(x));
let filter = val_or_err!(object.get("filter").and_then(f),
Some(Bson::Document(doc)) => doc,
"`update` requires filter document");
let f = |x| Some(Bson::from_json(x));
let replacement = val_or_err!(object.get("replacement").and_then(f),
Some(Bson::Document(doc)) => doc,
"`update` requires update document");
let f = |x| Some(Bson::from_json(x));
let upsert = var_match!(object.get("upsert").and_then(f),
Some(Bson::Boolean(b)) => b);
Ok(Arguments::ReplaceOne { filter: filter, replacement: replacement,
upsert: upsert })
}
pub fn update_from_json(object: &Object, many: bool) -> Result<Arguments, String> {
let f = |x| Some(Bson::from_json(x));
let filter = val_or_err!(object.get("filter").and_then(f),
Some(Bson::Document(doc)) => doc,
"`update` requires filter document");
let f = |x| Some(Bson::from_json(x));
let update = val_or_err!(object.get("update").and_then(f),
Some(Bson::Document(doc)) => doc,
"`update` requires update document");
let f = |x| Some(Bson::from_json(x));
let upsert = var_match!(object.get("upsert").and_then(f),
Some(Bson::Boolean(b)) => b);
Ok(Arguments::Update { filter: filter, update: update, upsert: upsert,
many: many })
}
}