From 76c4823e11c4f6fbec35b60087ef2c5aad0d36a1 Mon Sep 17 00:00:00 2001 From: "J. Cliff Dyer" Date: Mon, 16 Sep 2019 08:19:56 -0400 Subject: [PATCH] Add more Bson From<> implementations for better ergonomics. --- src/bson.rs | 60 ++++++++++++++++++++++++++++++++----------- tests/modules/bson.rs | 42 ++++++++++++++++++++++++++++-- 2 files changed, 85 insertions(+), 17 deletions(-) diff --git a/src/bson.rs b/src/bson.rs index 69b195bb..cfa5aad3 100644 --- a/src/bson.rs +++ b/src/bson.rs @@ -177,7 +177,7 @@ impl From for Bson { } } -impl<'a> From<&'a str> for Bson { +impl From<&str> for Bson { fn from(s: &str) -> Bson { Bson::String(s.to_owned()) } @@ -189,18 +189,6 @@ impl From for Bson { } } -impl<'a> From<&'a String> for Bson { - fn from(a: &'a String) -> Bson { - Bson::String(a.to_owned()) - } -} - -impl From for Bson { - fn from(a: Array) -> Bson { - Bson::Array(a) - } -} - impl From for Bson { fn from(a: Document) -> Bson { Bson::Document(a) @@ -231,6 +219,49 @@ impl From<(BinarySubtype, Vec)> for Bson { } } +impl From<&T> for Bson +where + T: Clone + Into +{ + fn from(t: &T) -> Bson { + t.clone().into() + } +} + +impl From> for Bson +where + T: Into +{ + fn from(v: Vec) -> Bson { + Bson::Array(v.into_iter().map(|val| val.into()).collect()) + } +} + +impl From<&[T]> for Bson +where + T: Clone + Into +{ + fn from(s: &[T]) -> Bson { + Bson::Array(s.into_iter().cloned().map(|val| val.into()).collect()) + } +} + +impl> ::std::iter::FromIterator for Bson { + /// # Examples + /// + /// ``` + /// use std::iter::FromIterator; + /// use bson::Bson; + /// + /// let x: Bson = Bson::from_iter(vec!["lorem", "ipsum", "dolor"]); + /// // or + /// let x: Bson = vec!["lorem", "ipsum", "dolor"].into_iter().collect(); + /// ``` + fn from_iter>(iter: I) -> Self { + Bson::Array(iter.into_iter().map(Into::into).collect()) + } +} + impl From for Bson { fn from(a: i32) -> Bson { Bson::I32(a) @@ -719,8 +750,7 @@ impl Bson { /// Just a helper for convenience /// /// ```rust,ignore -/// #[macro_use] -/// extern crate serde_derive; +/// use serde::{Serialize, Deserialize}; /// extern crate bson; /// use bson::TimeStamp; /// diff --git a/tests/modules/bson.rs b/tests/modules/bson.rs index a4c1b483..48125c99 100644 --- a/tests/modules/bson.rs +++ b/tests/modules/bson.rs @@ -1,11 +1,12 @@ extern crate serde_json; -use self::serde_json::Value; -use bson::{Bson, Document}; +use self::serde_json::{Value, json}; +use bson::{Bson, Document, oid::ObjectId, spec::BinarySubtype}; #[test] fn to_json() { let mut doc = Document::new(); + doc.insert("_id", Bson::ObjectId(ObjectId::with_bytes(*b"abcdefghijkl"))); doc.insert("first", Bson::I32(1)); doc.insert("second", Bson::String("foo".to_owned())); doc.insert("alphanumeric", Bson::String("bar".to_owned())); @@ -14,6 +15,12 @@ fn to_json() { assert!(data.is_object()); let obj = data.as_object().unwrap(); + let id = obj.get("_id").unwrap(); + assert!(id.is_object()); + let id_val = id.get("$oid").unwrap(); + assert!(id_val.is_string()); + assert_eq!(id_val, "6162636465666768696a6b6c"); + let first = obj.get("first").unwrap(); assert!(first.is_number()); assert_eq!(first.as_i64().unwrap(), 1); @@ -39,3 +46,34 @@ fn document_default() { assert_eq!(doc1.keys().count(), 0); assert_eq!(doc1, Document::new()); } + +#[test] +fn from_impls() { + assert_eq!(Bson::from(1.5f32), Bson::FloatingPoint(1.5)); + assert_eq!(Bson::from(2.25f64), Bson::FloatingPoint(2.25)); + assert_eq!(Bson::from("data"), Bson::String(String::from("data"))); + assert_eq!(Bson::from(String::from("data")), Bson::String(String::from("data"))); + assert_eq!(Bson::from(doc!{}), Bson::Document(Document::new())); + assert_eq!(Bson::from(false), Bson::Boolean(false)); + assert_eq!(Bson::from((String::from("\\s+$"), String::from("i"))), Bson::RegExp(String::from("\\s+$"), String::from("i"))); + assert_eq!(Bson::from((String::from("alert(\"hi\");"), doc!{})), Bson::JavaScriptCodeWithScope(String::from("alert(\"hi\");"), doc!{})); + // + assert_eq!(Bson::from((BinarySubtype::Generic, vec![1, 2, 3])), Bson::Binary(BinarySubtype::Generic, vec![1, 2, 3])); + assert_eq!(Bson::from(-48i32), Bson::I32(-48)); + assert_eq!(Bson::from(-96i64), Bson::I64(-96)); + assert_eq!(Bson::from(152u32), Bson::I32(152)); + assert_eq!(Bson::from(4096u64), Bson::I64(4096)); + + let oid = ObjectId::new().unwrap(); + assert_eq!(Bson::from(b"abcdefghijkl"), Bson::ObjectId(ObjectId::with_bytes(*b"abcdefghijkl"))); + assert_eq!(Bson::from(oid.clone()), Bson::ObjectId(oid.clone())); + assert_eq!(Bson::from(vec![1, 2, 3]), Bson::Array(vec![Bson::I32(1), Bson::I32(2), Bson::I32(3)])); + assert_eq!(Bson::from(json!({"_id": {"$oid": oid.to_hex()}, "name": ["bson-rs"]})), Bson::Document(doc!{"_id": &oid, "name": ["bson-rs"]})); + + // References + assert_eq!(Bson::from(&24i32), Bson::I32(24)); + assert_eq!(Bson::from(&String::from("data")), Bson::String(String::from("data"))); + assert_eq!(Bson::from(&oid), Bson::ObjectId(oid)); + assert_eq!(Bson::from(&doc!{"a": "b"}), Bson::Document(doc!{"a": "b"})); + +}