Bump bson to 0.11 and use lossy utf-8 decoding for responses

Mongo can return invalid UTF-8 in bson responses:

https://jira.mongodb.org/browse/SERVER-24007

We use lossy UTF-8 decoding when parsing now.
pull/38/merge
Thijs Cadier 7 years ago
parent 8e8a02f454
commit d0b93b6bb0

@ -21,7 +21,7 @@ name = "tests"
[dependencies] [dependencies]
libc = "^0.2" libc = "^0.2"
log = "^0.3" log = "^0.3"
bson = "^0.10" bson = "^0.11"
[dependencies.mongoc-sys] [dependencies.mongoc-sys]
path = "mongoc-sys" path = "mongoc-sys"

@ -42,6 +42,7 @@ impl Bsonc {
Ok(Bsonc{ inner: inner }) Ok(Bsonc{ inner: inner })
} }
/// Decode a bson from the C side to a document
pub fn as_document(&self) -> Result<bson::Document> { pub fn as_document(&self) -> Result<bson::Document> {
assert!(!self.inner.is_null()); assert!(!self.inner.is_null());
@ -63,6 +64,28 @@ impl Bsonc {
Ok(document) 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<bson::Document> {
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 { pub fn as_json(&self) -> String {
assert!(!self.inner.is_null()); assert!(!self.inner.is_null());
let json_ptr = unsafe { bindings::bson_as_json(self.inner, ptr::null_mut()) }; 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 bsonc = super::Bsonc::from_document(&document).unwrap();
let decoded = bsonc.as_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(), "<22><>");
} }
#[test] #[test]

@ -305,7 +305,7 @@ impl<'a> Client<'a> {
}; };
if success == 1 { if success == 1 {
match reply.as_document() { match reply.as_document_utf8_lossy() {
Ok(document) => return Ok(document), Ok(document) => return Ok(document),
Err(error) => return Err(error.into()) Err(error) => return Err(error.into())
} }

@ -342,7 +342,7 @@ impl<'a> Collection<'a> {
}; };
if success == 1 { if success == 1 {
match reply.as_document() { match reply.as_document_utf8_lossy() {
Ok(document) => return Ok(document), Ok(document) => return Ok(document),
Err(error) => return Err(error.into()) Err(error) => return Err(error.into())
} }
@ -547,7 +547,7 @@ impl<'a> Collection<'a> {
}; };
if success == 1 { if success == 1 {
match reply.as_document() { match reply.as_document_utf8_lossy() {
Ok(document) => return Ok(document), Ok(document) => return Ok(document),
Err(error) => return Err(error.into()) 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, Ok(document) => document,
Err(error) => return Err(BulkOperationError{error: error.into(), reply: doc!{}}) Err(error) => return Err(BulkOperationError{error: error.into(), reply: doc!{}})
}; };

@ -116,7 +116,7 @@ impl<'a> Database<'a> {
}; };
if success == 1 { if success == 1 {
match reply.as_document() { match reply.as_document_utf8_lossy() {
Ok(document) => return Ok(document), Ok(document) => return Ok(document),
Err(error) => return Err(error.into()) Err(error) => return Err(error.into())
} }

@ -9,7 +9,9 @@ fn test_execute_error() {
let uri = Uri::new("mongodb://localhost:27017/").unwrap(); let uri = Uri::new("mongodb://localhost:27017/").unwrap();
let pool = ClientPool::new(uri, None); let pool = ClientPool::new(uri, None);
let client = pool.pop(); 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 bulk_operation = collection.create_bulk_operation(None);
let result = bulk_operation.execute(); let result = bulk_operation.execute();
@ -24,11 +26,13 @@ fn test_basics() {
let uri = Uri::new("mongodb://localhost:27017/").unwrap(); let uri = Uri::new("mongodb://localhost:27017/").unwrap();
let pool = ClientPool::new(uri, None); let pool = ClientPool::new(uri, None);
let client = pool.pop(); 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 bulk_operation = collection.create_bulk_operation(None);
let document = doc! {"key_1" => "Value 1"}; 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()); assert!(bulk_operation.execute().is_ok());
let first_document = collection.find(&doc!{}, None).unwrap().next().unwrap().unwrap(); 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 uri = Uri::new("mongodb://localhost:27017/").unwrap();
let pool = ClientPool::new(uri, None); let pool = ClientPool::new(uri, None);
let client = pool.pop(); 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 bulk_operation = collection.create_bulk_operation(None);
let document = doc! {"key_1" => "kācaṃ śaknomyattum; nopahinasti mām."}; 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()); assert!(bulk_operation.execute().is_ok());
let first_document = collection.find(&doc!{}, None).unwrap().next().unwrap().unwrap(); 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] #[test]
fn test_insert_remove_replace_update_extended() { fn test_insert_remove_replace_update_extended() {
if env::var("SKIP_EXTENDED_BULK_OPERATION_TESTS") == Ok("true".to_string()) { if env::var("SKIP_EXTENDED_BULK_OPERATION_TESTS") == Ok("true".to_string()) {

Loading…
Cancel
Save