Skip to content

Commit 148e37d

Browse files
feat: convert collection to use serde
With BSON & MongoDB 2.0 which is clearly geared at using serde for conversion using the interim document type for Collection no longer makes sense. For that reason Collection has been changed to require serde, this should not be too big an issue as customer derives can be used to obtain the old behaviour. This change also allows for Cursor to return concrete types addressing #2.
1 parent 9098776 commit 148e37d

File tree

23 files changed

+165
-220
lines changed

23 files changed

+165
-220
lines changed

mongod-derive/Cargo.toml

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mongod-derive"
3-
version = "0.2.2"
3+
version = "0.3.0"
44
authors = ["Alex Kornitzer <[email protected]>"]
55
edition = "2018"
66
description = "An abstraction layer on mongodb"
@@ -17,7 +17,8 @@ quote = "1.0"
1717
syn = "1.0"
1818

1919
[dev-dependencies]
20-
mongod = { version = "0.2.2", path = "../mongod" }
20+
mongod = { version = "0.3.0", path = "../mongod" }
21+
serde = "1.0"
2122

2223
[lib]
2324
proc-macro = true

mongod-derive/src/lib.rs

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@
2020
//! ```
2121
//! # mod wrap {
2222
//! # use mongod_derive::Mongo;
23-
//! # #[derive(mongod_derive::Bson)]
24-
//! #[derive(Mongo)]
23+
//! use serde::{Deserialize, Serialize};
24+
//! #[derive(Mongo, Deserialize, Serialize)]
2525
//! #[mongo(collection = "users", field, filter, update)]
2626
//! pub struct User {
2727
//! name: String,
@@ -143,8 +143,9 @@ pub fn derive_bson(input: TokenStream) -> TokenStream {
143143
/// ```
144144
/// # mod wrap {
145145
/// # use mongod_derive::Mongo;
146-
/// # #[derive(mongod_derive::Bson)]
147-
/// #[derive(Mongo)]
146+
/// use serde::{Deserialize, Serialize};
147+
///
148+
/// #[derive(Mongo, Deserialize, Serialize)]
148149
/// #[mongo(collection = "users")]
149150
/// pub struct User {
150151
/// name: String,
@@ -228,8 +229,9 @@ pub fn derive_bson(input: TokenStream) -> TokenStream {
228229
/// ```
229230
/// # mod wrap {
230231
/// # use mongod_derive::Mongo;
231-
/// # #[derive(mongod_derive::Bson)]
232-
/// #[derive(Mongo)]
232+
/// use serde::{Deserialize, Serialize};
233+
///
234+
/// #[derive(Mongo, Deserialize, Serialize)]
233235
/// #[mongo(collection = "users")]
234236
/// pub struct User {
235237
/// name: String,
@@ -246,8 +248,9 @@ pub fn derive_bson(input: TokenStream) -> TokenStream {
246248
/// ```
247249
/// # mod wrap {
248250
/// # use mongod_derive::Mongo;
249-
/// # #[derive(mongod_derive::Bson)]
250-
/// #[derive(Mongo)]
251+
/// use serde::{Deserialize, Serialize};
252+
///
253+
/// #[derive(Mongo, Deserialize, Serialize)]
251254
/// #[mongo(collection = "users")]
252255
/// pub struct User {
253256
/// name: String,

mongod-derive/src/mongo.rs

Lines changed: 0 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -58,40 +58,10 @@ fn impl_struct(
5858
attrs: &attr::Container,
5959
) -> proc_macro2::TokenStream {
6060
let collection = if let Some(col) = &attrs.collection {
61-
let from = if attrs.bson == attr::BsonMode::Serde {
62-
quote! {
63-
_mongo::bson::from_document(document).map_err(_mongo::Error::invalid_document)
64-
}
65-
} else {
66-
quote! {
67-
Self::try_from(_mongo::bson::Bson::Document(document)).map_err(_mongo::Error::invalid_document)
68-
}
69-
};
70-
let into = if attrs.bson == attr::BsonMode::Serde {
71-
quote! {
72-
let b = _mongo::bson::to_bson(&self).map_err(_mongo::Error::invalid_document)?;
73-
}
74-
} else {
75-
quote! {
76-
let b = _mongo::bson::Bson::try_from(self).map_err(_mongo::Error::invalid_document)?;
77-
}
78-
};
7961
quote! {
8062
#[automatically_derived]
8163
impl _mongo::Collection for #name {
8264
const COLLECTION: &'static str = #col;
83-
84-
fn from_document(document: _mongo::bson::Document) -> Result<Self, _mongo::Error> {
85-
#from
86-
}
87-
88-
fn into_document(self) -> Result<_mongo::bson::Document, _mongo::Error> {
89-
#into
90-
match b {
91-
_mongo::bson::Bson::Document(doc) => Ok(doc),
92-
_ => Err(_mongo::Error::invalid_document("not a bson document")),
93-
}
94-
}
9565
}
9666
}
9767
} else {

mongod/Cargo.toml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
[package]
22
name = "mongod"
3-
version = "0.2.2"
3+
version = "0.3.0"
44
authors = [
55
"Alex Kornitzer <[email protected]>",
66
]
@@ -21,14 +21,14 @@ chrono = { version = "0.4", optional = true, features = ["serde"] }
2121
futures = "0.3"
2222
log = "0.4"
2323
mongodb = "2.0.0-beta.3"
24-
mongod-derive = { version = "=0.2.2", optional = true, path = "../mongod-derive" }
24+
mongod-derive = { version = "=0.3.0", optional = true, path = "../mongod-derive" }
2525
serde = { version = "1.0", features = ["derive"] }
2626
tokio = { version = "1.0", default-features = false }
2727
url = "2.2"
2828

2929

3030
[dev-dependencies]
31-
mongod-derive = { version = "0.2.2", path = "../mongod-derive" }
31+
mongod-derive = { version = "0.3", path = "../mongod-derive" }
3232

3333

3434
[features]

mongod/src/async/client.rs

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -533,7 +533,7 @@ impl Client {
533533
/// # Errors
534534
///
535535
/// This method fails if the mongodb encountered an error.
536-
pub async fn find<C, F, T>(&self, filter: Option<F>) -> crate::Result<mongodb::Cursor<Document>>
536+
pub async fn find<C, F>(&self, filter: Option<F>) -> crate::Result<mongodb::Cursor<C>>
537537
where
538538
C: AsFilter<F> + Collection,
539539
F: Filter,
@@ -563,8 +563,7 @@ impl Client {
563563
let mut cursor = find.filter(filter)?.query(&self).await?;
564564
if let Some(res) = cursor.next().await {
565565
let doc = res.map_err(crate::error::mongodb)?;
566-
let document: C = C::from_document(doc).map_err(crate::error::bson)?;
567-
return Ok(Some(document));
566+
return Ok(Some(doc));
568567
}
569568
Ok(None)
570569
}

mongod/src/blocking/client.rs

Lines changed: 5 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use mongodb::options::{
1010
};
1111
use mongodb::results::{DeleteResult, InsertManyResult, UpdateResult};
1212

13-
use super::cursor::Cursor;
13+
use super::cursor::{Cursor, CursorInt};
1414
use crate::collection::Collection;
1515
use crate::filter::{AsFilter, Filter};
1616
use crate::query;
@@ -167,7 +167,7 @@ pub(crate) enum Request {
167167
}
168168
pub(crate) enum Response {
169169
Delete(DeleteResult),
170-
Find(Cursor),
170+
Find(CursorInt),
171171
Insert(InsertManyResult),
172172
Replace(UpdateResult),
173173
Update(UpdateResult),
@@ -255,7 +255,7 @@ impl Client {
255255
/// # Errors
256256
///
257257
/// This method fails if the mongodb encountered an error.
258-
pub fn find<C, F>(&self, filter: Option<F>) -> crate::Result<Cursor>
258+
pub fn find<C, F>(&self, filter: Option<F>) -> crate::Result<Cursor<C>>
259259
where
260260
C: AsFilter<F> + Collection,
261261
F: Filter,
@@ -284,8 +284,7 @@ impl Client {
284284
let find: query::Find<C> = query::Find::new();
285285
let mut cursor = find.filter(filter)?.blocking(&self)?;
286286
if let Some(res) = cursor.next() {
287-
let doc = res.map_err(crate::error::mongodb)?;
288-
let document: C = C::from_document(doc).map_err(crate::error::bson)?;
287+
let document = res.map_err(crate::error::mongodb)?;
289288
return Ok(Some(document));
290289
}
291290
Ok(None)
@@ -489,7 +488,7 @@ impl ClientInner {
489488
.map_err(crate::error::mongodb),
490489
Request::Find(collection, filter, options) => {
491490
match database.collection(collection).find(filter, options).await {
492-
Ok(c) => Ok(Response::Find(Cursor::new(c))),
491+
Ok(c) => Ok(Response::Find(CursorInt::new(c))),
493492
Err(e) => Err(crate::error::mongodb(e)),
494493
}
495494
}

mongod/src/blocking/cursor.rs

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,8 @@
1+
use std::marker::{PhantomData, Unpin};
2+
13
use bson::Document;
24
use futures::stream::StreamExt;
5+
use serde::de::DeserializeOwned;
36

47
#[derive(Debug)]
58
enum Request {
@@ -9,16 +12,11 @@ enum Response {
912
Next(Option<crate::Result<Document>>),
1013
}
1114

12-
/// A blocking version of the [`mongodb::Cursor`](https://docs.rs/mongodb/1.1.1/mongodb/struct.Cursor.html).
13-
///
14-
/// This wraps the async `Cursor` so that is can be called in a synchronous fashion, please see the
15-
/// asynchronous description for more information about the cursor.
16-
pub struct Cursor {
15+
pub(crate) struct CursorInt {
1716
tx: tokio::sync::mpsc::UnboundedSender<(Request, std::sync::mpsc::Sender<Response>)>,
1817
}
1918

20-
impl Cursor {
21-
/// Constructs a synchronous `Cursor` from an asynchronous one.
19+
impl CursorInt {
2220
pub fn new(cursor: mongodb::Cursor<Document>) -> Self {
2321
let (tx, mut rx) =
2422
tokio::sync::mpsc::unbounded_channel::<(Request, std::sync::mpsc::Sender<Response>)>();
@@ -39,10 +37,36 @@ impl Cursor {
3937
tokio::spawn(f);
4038
Self { tx }
4139
}
40+
41+
pub fn to_cursor<T>(self) -> Cursor<T>
42+
where
43+
T: DeserializeOwned + Unpin + Send + Sync,
44+
{
45+
Cursor {
46+
document_type: PhantomData,
47+
tx: self.tx,
48+
}
49+
}
50+
}
51+
52+
/// A blocking version of the [`mongodb::Cursor`](https://docs.rs/mongodb/1.1.1/mongodb/struct.Cursor.html).
53+
///
54+
/// This wraps the async `Cursor` so that is can be called in a synchronous fashion, please see the
55+
/// asynchronous description for more information about the cursor.
56+
pub struct Cursor<T>
57+
where
58+
T: DeserializeOwned + Unpin + Send + Sync,
59+
{
60+
document_type: PhantomData<T>,
61+
62+
tx: tokio::sync::mpsc::UnboundedSender<(Request, std::sync::mpsc::Sender<Response>)>,
4263
}
4364

44-
impl Iterator for Cursor {
45-
type Item = crate::Result<Document>;
65+
impl<T> Iterator for Cursor<T>
66+
where
67+
T: DeserializeOwned + Unpin + Send + Sync,
68+
{
69+
type Item = crate::Result<T>;
4670
fn next(&mut self) -> Option<Self::Item> {
4771
let (tx, rx) = std::sync::mpsc::channel();
4872
self.tx
@@ -52,6 +76,11 @@ impl Iterator for Cursor {
5276
.recv()
5377
.expect("could not get response from mongo runtime");
5478
let Response::Next(c) = res;
55-
c
79+
let resp = match c {
80+
Some(Ok(b)) => Some(bson::from_document::<T>(b).map_err(crate::error::mongodb)),
81+
Some(Err(e)) => Some(Err(crate::error::mongodb(e))),
82+
None => None,
83+
};
84+
resp
5685
}
5786
}

mongod/src/blocking/mod.rs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,9 @@
1313
//! example to fetch users from a collection.
1414
//!
1515
//! ```no_run
16-
//! # use mongod_derive::{Bson, Mongo};
17-
//! # #[derive(Debug, Bson, Mongo)]
16+
//! # use mongod_derive::Mongo;
17+
//! # use serde::{Deserialize, Serialize};
18+
//! # #[derive(Debug, Mongo, Deserialize, Serialize)]
1819
//! # #[mongo(collection="users", field, filter, update)]
1920
//! # pub struct User {
2021
//! # name: String,
@@ -27,8 +28,7 @@
2728
//!
2829
//! let mut cursor = client.find::<User, _>(None).unwrap();
2930
//! while let Some(res) = cursor.next() {
30-
//! if let Ok(doc) = res {
31-
//! let user: User = User::from_document(doc).unwrap();
31+
//! if let Ok(user) = res {
3232
//! println!("{:?}", user);
3333
//! }
3434
//! }

0 commit comments

Comments
 (0)