diff --git a/mongoc-sys/src/lib.rs b/mongoc-sys/src/lib.rs index 8061994..cf4640c 100644 --- a/mongoc-sys/src/lib.rs +++ b/mongoc-sys/src/lib.rs @@ -131,6 +131,7 @@ pub mod bindings { pub fn mongoc_client_get_collection(client: *mut mongoc_client_t, db: *const ::libc::c_char, collection: *const ::libc::c_char) -> *mut mongoc_collection_t; pub fn mongoc_client_get_database(client: *mut mongoc_client_t, name: *const ::libc::c_char) -> *mut mongoc_database_t; pub fn mongoc_client_get_server_status(client: *mut mongoc_client_t, read_prefs: *mut mongoc_read_prefs_t, reply: *mut bson_t, error: *mut bson_error_t) -> u8; + pub fn mongoc_client_read_command_with_opts(client: *mut mongoc_client_t, db: *const ::libc::c_char, command: *const bson_t, read_prefs: *const mongoc_read_prefs_t, opts: *const bson_t, reply: *mut bson_t, error: *mut bson_error_t ) -> u8; } // Collection diff --git a/src/client.rs b/src/client.rs index 2fe78aa..433ef93 100644 --- a/src/client.rs +++ b/src/client.rs @@ -313,6 +313,48 @@ impl<'a> Client<'a> { Err(error.into()) } } + + pub fn read_command_with_opts>>(&self, + db: S, + command: &Document, + read_prefs: Option<&ReadPrefs>, + options: Option<&Document>) -> Result { + assert!(!self.inner.is_null()); + + let db_cstring = CString::new(db)?; + + // Bsonc to store the reply + let mut reply = Bsonc::new(); + // Empty error that might be filled + let mut error = BsoncError::empty(); + + let success = unsafe { + bindings::mongoc_client_read_command_with_opts( + self.inner, + db_cstring.as_ptr(), + Bsonc::from_document(command)?.inner(), + match read_prefs { + Some(ref prefs) => prefs.inner(), + None => ptr::null() + }, + match options { + Some(ref o) => Bsonc::from_document(o)?.inner(), + None => ptr::null() + }, + reply.mut_inner(), + error.mut_inner() + ) + }; + + if success == 1 { + match reply.as_document_utf8_lossy() { + Ok(document) => return Ok(document), + Err(error) => return Err(error.into()) + } + } else { + Err(error.into()) + } + } } impl<'a> Drop for Client<'a> { diff --git a/src/error.rs b/src/error.rs index bb28f41..ec78e0f 100644 --- a/src/error.rs +++ b/src/error.rs @@ -4,6 +4,7 @@ use std::borrow::Cow; use std::ffi::CStr; use bson::{DecoderError,EncoderError,ValueAccessError,Document}; +use std::ffi::NulError; use mongoc::bindings; @@ -18,7 +19,9 @@ pub enum MongoError { /// Error accessing a value on a Bson document. ValueAccessError(ValueAccessError), /// Invalid params error that can be reported by the underlying C driver. - InvalidParams(InvalidParamsError) + InvalidParams(InvalidParamsError), + // from CString::new(db) + Nul(NulError) } impl fmt::Display for MongoError { @@ -28,7 +31,8 @@ impl fmt::Display for MongoError { MongoError::Encoder(ref err) => write!(f, "{}", err), MongoError::Decoder(ref err) => write!(f, "{}", err), MongoError::ValueAccessError(ref err) => write!(f, "{}", err), - MongoError::InvalidParams(ref err) => write!(f, "{}", err) + MongoError::InvalidParams(ref err) => write!(f, "{}", err), + MongoError::Nul(ref err) => write!(f, "{}", err) } } } @@ -40,7 +44,8 @@ impl fmt::Debug for MongoError { MongoError::Decoder(ref err) => write!(f, "MongoError ({:?})", err), MongoError::Encoder(ref err) => write!(f, "MongoError ({:?})", err), MongoError::ValueAccessError(ref err) => write!(f, "MongoError ({:?})", err), - MongoError::InvalidParams(ref err) => write!(f, "MongoError ({:?})", err) + MongoError::InvalidParams(ref err) => write!(f, "MongoError ({:?})", err), + MongoError::Nul(ref err) => write!(f, "MongoError ({:?})", err) } } } @@ -52,7 +57,8 @@ impl error::Error for MongoError { MongoError::Decoder(ref err) => err.description(), MongoError::Encoder(ref err) => err.description(), MongoError::ValueAccessError(ref err) => err.description(), - MongoError::InvalidParams(ref err) => err.description() + MongoError::InvalidParams(ref err) => err.description(), + MongoError::Nul(ref err) => err.description() } } @@ -62,7 +68,8 @@ impl error::Error for MongoError { MongoError::Decoder(ref err) => Some(err), MongoError::Encoder(ref err) => Some(err), MongoError::ValueAccessError(ref err) => Some(err), - MongoError::InvalidParams(ref err) => Some(err) + MongoError::InvalidParams(ref err) => Some(err), + MongoError::Nul(ref err) => Some(err) } } } @@ -85,6 +92,12 @@ impl From for MongoError { } } +impl From for MongoError { + fn from(error: NulError) -> MongoError { + MongoError::Nul(error) + } +} + /// Error in the underlying C driver. pub struct BsoncError { inner: bindings::bson_error_t, diff --git a/tests/client.rs b/tests/client.rs index 8cd90bc..ff9d4ee 100644 --- a/tests/client.rs +++ b/tests/client.rs @@ -81,6 +81,29 @@ fn test_get_server_status() { assert!(status.contains_key("version")); } +#[test] +fn test_read_command_with_opts() { + let uri = Uri::new("mongodb://localhost:27017/").unwrap(); + let pool = ClientPool::new(uri, None); + let client = pool.pop(); + let db_name = "rust_driver_test"; + let coll_name = "test_read_command_with_opts"; + let collection = client.get_collection(db_name, coll_name); + + let document = doc! { + "key_1" => "Value 1", + "key_2" => "kācaṃ śaknomyattum; nopahinasti mām. \u{0}" + }; + collection.insert(&document, None).expect("Could not insert document"); + + let status = client.read_command_with_opts(db_name, + &doc!{"collStats": coll_name}, + None, None).unwrap(); + + assert!(status.contains_key("totalIndexSize")); + assert!(status.contains_key("storageSize")); +} + #[test] fn test_new_pool_with_ssl_options() { let uri = Uri::new("mongodb://localhost:27017/").unwrap();