use bson::{self, Bson};
use cursor;
use common::{ReadPreference, WriteConcern};
use Error::ArgumentError;
use Result;
#[derive(Clone, PartialEq, Eq)]
pub enum CursorType {
NonTailable,
Tailable,
TailableAwait,
}
#[derive(Clone, PartialEq, Eq)]
pub enum ReturnDocument {
Before,
After,
}
#[derive(Debug, Clone)]
pub enum WriteModel {
InsertOne { document: bson::Document },
DeleteOne { filter: bson::Document },
DeleteMany { filter: bson::Document },
ReplaceOne {
filter: bson::Document,
replacement: bson::Document,
upsert: bool,
},
UpdateOne {
filter: bson::Document,
update: bson::Document,
upsert: bool,
},
UpdateMany {
filter: bson::Document,
update: bson::Document,
upsert: bool,
},
}
#[derive(Clone, Default)]
pub struct AggregateOptions {
pub allow_disk_use: bool,
pub use_cursor: bool,
pub batch_size: i32,
pub max_time_ms: Option<i64>,
pub read_preference: Option<ReadPreference>,
}
#[derive(Clone, Default)]
pub struct CountOptions {
pub skip: u64,
pub limit: i64,
pub hint: Option<String>,
pub hint_doc: Option<bson::Document>,
pub max_time_ms: Option<i64>,
pub read_preference: Option<ReadPreference>,
}
#[derive(Clone, Default)]
pub struct DistinctOptions {
pub max_time_ms: Option<i64>,
pub read_preference: Option<ReadPreference>,
}
#[derive(Clone)]
pub struct FindOptions {
pub allow_partial_results: bool,
pub no_cursor_timeout: bool,
pub op_log_replay: bool,
pub skip: u32,
pub limit: i32,
pub cursor_type: CursorType,
pub batch_size: i32,
pub comment: Option<String>,
pub max_time_ms: Option<i64>,
pub modifiers: Option<bson::Document>,
pub projection: Option<bson::Document>,
pub sort: Option<bson::Document>,
pub read_preference: Option<ReadPreference>,
}
#[derive(Clone, Default)]
pub struct FindOneAndDeleteOptions {
pub max_time_ms: Option<i64>,
pub projection: Option<bson::Document>,
pub sort: Option<bson::Document>,
pub write_concern: Option<WriteConcern>,
}
#[derive(Clone)]
pub struct FindOneAndUpdateOptions {
pub return_document: ReturnDocument,
pub max_time_ms: Option<i64>,
pub projection: Option<bson::Document>,
pub sort: Option<bson::Document>,
pub upsert: bool,
pub write_concern: Option<WriteConcern>,
}
#[derive(Clone, Default)]
pub struct IndexOptions {
pub background: Option<bool>,
pub expire_after_seconds: Option<i32>,
pub name: Option<String>,
pub sparse: Option<bool>,
pub storage_engine: Option<String>,
pub unique: Option<bool>,
pub version: Option<i32>,
pub default_language: Option<String>,
pub language_override: Option<String>,
pub text_version: Option<i32>,
pub weights: Option<bson::Document>,
pub sphere_version: Option<i32>,
pub bits: Option<i32>,
pub max: Option<f64>,
pub min: Option<f64>,
pub bucket_size: Option<i32>,
}
#[derive(Clone)]
pub struct IndexModel {
pub keys: bson::Document,
pub options: IndexOptions,
}
#[derive(Clone, Default)]
pub struct InsertManyOptions {
pub ordered: bool,
pub write_concern: Option<WriteConcern>,
}
#[derive(Clone, Default)]
pub struct UpdateOptions {
pub upsert: bool,
pub write_concern: Option<WriteConcern>,
}
pub type ReplaceOptions = UpdateOptions;
impl AggregateOptions {
pub fn new() -> AggregateOptions {
AggregateOptions {
allow_disk_use: false,
use_cursor: true,
batch_size: cursor::DEFAULT_BATCH_SIZE,
max_time_ms: None,
read_preference: None,
}
}
}
impl CountOptions {
pub fn new() -> CountOptions {
CountOptions {
skip: 0,
limit: 0,
hint: None,
hint_doc: None,
max_time_ms: None,
read_preference: None,
}
}
}
impl DistinctOptions {
pub fn new() -> DistinctOptions {
DistinctOptions {
max_time_ms: None,
read_preference: None,
}
}
}
impl Default for FindOptions {
fn default() -> Self {
Self::new()
}
}
impl FindOptions {
pub fn new() -> FindOptions {
FindOptions {
allow_partial_results: false,
no_cursor_timeout: false,
op_log_replay: false,
skip: 0,
limit: 0,
cursor_type: CursorType::NonTailable,
batch_size: cursor::DEFAULT_BATCH_SIZE,
comment: None,
max_time_ms: None,
modifiers: None,
projection: None,
sort: None,
read_preference: None,
}
}
pub fn with_limit(&self, limit: i32) -> FindOptions {
let mut new_opts = self.clone();
new_opts.limit = limit;
new_opts
}
}
impl FindOneAndDeleteOptions {
pub fn new() -> FindOneAndDeleteOptions {
FindOneAndDeleteOptions {
max_time_ms: None,
projection: None,
sort: None,
write_concern: None,
}
}
}
impl Default for FindOneAndUpdateOptions {
fn default() -> Self {
Self::new()
}
}
impl FindOneAndUpdateOptions {
pub fn new() -> FindOneAndUpdateOptions {
FindOneAndUpdateOptions {
return_document: ReturnDocument::Before,
max_time_ms: None,
projection: None,
sort: None,
upsert: false,
write_concern: None,
}
}
}
impl IndexOptions {
pub fn new() -> IndexOptions {
IndexOptions {
background: None,
expire_after_seconds: None,
name: None,
sparse: None,
storage_engine: None,
unique: None,
version: None,
default_language: None,
language_override: None,
text_version: None,
weights: None,
sphere_version: None,
bits: None,
max: None,
min: None,
bucket_size: None,
}
}
}
impl IndexModel {
pub fn new(keys: bson::Document, options: Option<IndexOptions>) -> IndexModel {
IndexModel {
keys: keys,
options: options.unwrap_or_else(IndexOptions::new),
}
}
pub fn name(&self) -> Result<String> {
Ok(match self.options.name {
Some(ref name) => name.to_owned(),
None => try!(self.generate_index_name()),
})
}
pub fn generate_index_name(&self) -> Result<String> {
let mut name = String::new();
for (key, bson) in self.keys.iter() {
if !name.is_empty() {
name.push_str("_");
}
name.push_str(key);
name.push('_');
match *bson {
Bson::I32(ref i) => name.push_str(&format!("{}", i)),
_ => return Err(ArgumentError(String::from("Index model keys must map to i32."))),
}
}
Ok(name)
}
pub fn to_bson(&self) -> Result<bson::Document> {
let mut doc = bson::Document::new();
doc.insert("key", Bson::Document(self.keys.clone()));
if let Some(ref val) = self.options.background {
doc.insert("background", Bson::Boolean(*val));
}
if let Some(ref val) = self.options.expire_after_seconds {
doc.insert("expireAfterSeconds", Bson::I32(*val));
}
if let Some(ref val) = self.options.name {
doc.insert("name", Bson::String(val.to_owned()));
} else {
doc.insert("name", Bson::String(try!(self.generate_index_name())));
}
if let Some(ref val) = self.options.sparse {
doc.insert("sparse", Bson::Boolean(*val));
}
if let Some(ref val) = self.options.storage_engine {
doc.insert("storageEngine", Bson::String(val.to_owned()));
}
if let Some(ref val) = self.options.unique {
doc.insert("unique", Bson::Boolean(*val));
}
if let Some(ref val) = self.options.version {
doc.insert("v", Bson::I32(*val));
}
if let Some(ref val) = self.options.default_language {
doc.insert("default_language", Bson::String(val.to_owned()));
}
if let Some(ref val) = self.options.language_override {
doc.insert("language_override", Bson::String(val.to_owned()));
}
if let Some(ref val) = self.options.text_version {
doc.insert("textIndexVersion", Bson::I32(*val));
}
if let Some(ref val) = self.options.weights {
doc.insert("weights", Bson::Document(val.clone()));
}
if let Some(ref val) = self.options.sphere_version {
doc.insert("2dsphereIndexVersion", Bson::I32(*val));
}
if let Some(ref val) = self.options.bits {
doc.insert("bits", Bson::I32(*val));
}
if let Some(ref val) = self.options.max {
doc.insert("max", Bson::FloatingPoint(*val));
}
if let Some(ref val) = self.options.min {
doc.insert("min", Bson::FloatingPoint(*val));
}
if let Some(ref val) = self.options.bucket_size {
doc.insert("bucketSize", Bson::I32(*val));
}
Ok(doc)
}
}
impl InsertManyOptions {
pub fn new(ordered: bool, write_concern: Option<WriteConcern>) -> InsertManyOptions {
InsertManyOptions {
ordered: ordered,
write_concern: write_concern,
}
}
}
impl ReturnDocument {
pub fn to_bool(&self) -> bool {
match *self {
ReturnDocument::Before => false,
ReturnDocument::After => true,
}
}
}
impl UpdateOptions {
pub fn new(upsert: bool, write_concern: Option<WriteConcern>) -> UpdateOptions {
UpdateOptions {
upsert: upsert,
write_concern: write_concern,
}
}
}