diff --git a/Cargo.toml b/Cargo.toml index 67fa75e..1a0fa27 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -21,7 +21,7 @@ name = "tests" [dependencies] libc = "^0.2" log = "^0.3" -bson = "^0.10" +bson = "^0.11" [dependencies.mongoc-sys] path = "mongoc-sys" diff --git a/src/bsonc.rs b/src/bsonc.rs index c033141..45bf2d6 100644 --- a/src/bsonc.rs +++ b/src/bsonc.rs @@ -42,6 +42,7 @@ impl Bsonc { Ok(Bsonc{ inner: inner }) } + /// Decode a bson from the C side to a document pub fn as_document(&self) -> Result { assert!(!self.inner.is_null()); @@ -63,6 +64,28 @@ impl Bsonc { Ok(document) } + /// Decode a bson from the C side to a document with lossy UTF-8 decoding + pub fn as_document_utf8_lossy(&self) -> Result { + assert!(!self.inner.is_null()); + + // This pointer should not be modified or freed + // See: http://mongoc.org/libbson/current/bson_get_data.html + let data_ptr = unsafe { bindings::bson_get_data(self.inner) }; + assert!(!data_ptr.is_null()); + + let data_len = unsafe { + let bson = *self.inner; + bson.len + } as usize; + + let mut slice = unsafe { + slice::from_raw_parts(data_ptr, data_len) + }; + + let document = try!(bson::decode_document_utf8_lossy(&mut slice)); + Ok(document) + } + pub fn as_json(&self) -> String { assert!(!self.inner.is_null()); let json_ptr = unsafe { bindings::bson_as_json(self.inner, ptr::null_mut()) }; @@ -106,7 +129,18 @@ mod tests { let bsonc = super::Bsonc::from_document(&document).unwrap(); let decoded = bsonc.as_document().unwrap(); - assert!(decoded.contains_key("key")); + assert_eq!(decoded.get_str("key").unwrap(), "value"); + } + + #[test] + fn test_bsonc_from_and_as_document_invalid_utf8() { + let bytes = b"\x80\xae".to_vec(); + let value = unsafe { String::from_utf8_unchecked(bytes) }; + let document = doc! { "key" => value }; + let bsonc = super::Bsonc::from_document(&document).unwrap(); + + let decoded = bsonc.as_document_utf8_lossy().unwrap(); + assert_eq!(decoded.get_str("key").unwrap(), "��"); } #[test] diff --git a/src/client.rs b/src/client.rs index 3d65629..2fe78aa 100644 --- a/src/client.rs +++ b/src/client.rs @@ -305,7 +305,7 @@ impl<'a> Client<'a> { }; if success == 1 { - match reply.as_document() { + match reply.as_document_utf8_lossy() { Ok(document) => return Ok(document), Err(error) => return Err(error.into()) } diff --git a/src/collection.rs b/src/collection.rs index 72a50df..729551f 100644 --- a/src/collection.rs +++ b/src/collection.rs @@ -342,7 +342,7 @@ impl<'a> Collection<'a> { }; if success == 1 { - match reply.as_document() { + match reply.as_document_utf8_lossy() { Ok(document) => return Ok(document), Err(error) => return Err(error.into()) } @@ -547,7 +547,7 @@ impl<'a> Collection<'a> { }; if success == 1 { - match reply.as_document() { + match reply.as_document_utf8_lossy() { Ok(document) => return Ok(document), Err(error) => return Err(error.into()) } @@ -884,7 +884,7 @@ impl<'a>BulkOperation<'a> { ) }; - let document = match reply.as_document() { + let document = match reply.as_document_utf8_lossy() { Ok(document) => document, Err(error) => return Err(BulkOperationError{error: error.into(), reply: doc!{}}) }; diff --git a/src/database.rs b/src/database.rs index bf97f31..6cb05af 100644 --- a/src/database.rs +++ b/src/database.rs @@ -116,7 +116,7 @@ impl<'a> Database<'a> { }; if success == 1 { - match reply.as_document() { + match reply.as_document_utf8_lossy() { Ok(document) => return Ok(document), Err(error) => return Err(error.into()) } diff --git a/tests/bulk_operation.rs b/tests/bulk_operation.rs index a31b456..7a8c115 100644 --- a/tests/bulk_operation.rs +++ b/tests/bulk_operation.rs @@ -9,7 +9,9 @@ fn test_execute_error() { let uri = Uri::new("mongodb://localhost:27017/").unwrap(); let pool = ClientPool::new(uri, None); let client = pool.pop(); - let collection = client.get_collection("rust_driver_test", "bulk_operation_error"); + let mut collection = client.get_collection("rust_driver_test", "bulk_operation_error"); + collection.drop().unwrap_or(()); + let bulk_operation = collection.create_bulk_operation(None); let result = bulk_operation.execute(); @@ -24,11 +26,13 @@ fn test_basics() { let uri = Uri::new("mongodb://localhost:27017/").unwrap(); let pool = ClientPool::new(uri, None); let client = pool.pop(); - let collection = client.get_collection("rust_driver_test", "bulk_operation_basics"); + let mut collection = client.get_collection("rust_driver_test", "bulk_operation_basics"); + collection.drop().unwrap_or(()); + let bulk_operation = collection.create_bulk_operation(None); let document = doc! {"key_1" => "Value 1"}; - bulk_operation.insert(&document).unwrap(); + bulk_operation.insert(&document).expect("Could not insert"); assert!(bulk_operation.execute().is_ok()); let first_document = collection.find(&doc!{}, None).unwrap().next().unwrap().unwrap(); @@ -43,11 +47,13 @@ fn test_utf8() { let uri = Uri::new("mongodb://localhost:27017/").unwrap(); let pool = ClientPool::new(uri, None); let client = pool.pop(); - let collection = client.get_collection("rust_driver_test", "bulk_operation_utf8"); + let mut collection = client.get_collection("rust_driver_test", "bulk_operation_utf8"); + collection.drop().unwrap_or(()); + let bulk_operation = collection.create_bulk_operation(None); let document = doc! {"key_1" => "kācaṃ śaknomyattum; nopahinasti mām."}; - bulk_operation.insert(&document).unwrap(); + bulk_operation.insert(&document).expect("Could not insert"); assert!(bulk_operation.execute().is_ok()); let first_document = collection.find(&doc!{}, None).unwrap().next().unwrap().unwrap(); @@ -57,27 +63,6 @@ fn test_utf8() { ); } -#[test] -fn test_utf8_invalid() { - let uri = Uri::new("mongodb://localhost:27017/").unwrap(); - let pool = ClientPool::new(uri, None); - let client = pool.pop(); - let collection = client.get_collection("rust_driver_test", "bulk_operation_utf8_invalid"); - let bulk_operation = collection.create_bulk_operation(None); - - let bytes = b"\x80\xae".to_vec(); - let value = unsafe { String::from_utf8_unchecked(bytes) }; - let document = doc! {"key_1" => value}; - bulk_operation.insert(&document).unwrap(); - assert!(bulk_operation.execute().is_ok()); - - let first_document = collection.find(&doc!{}, None).unwrap().next().unwrap().unwrap(); - assert_eq!( - first_document.get("key_1").unwrap(), - &bson::Bson::String("𤭢".to_string()) - ); -} - #[test] fn test_insert_remove_replace_update_extended() { if env::var("SKIP_EXTENDED_BULK_OPERATION_TESTS") == Ok("true".to_string()) {