1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
//! Typed, generic wrapper around MongoDB `Cursor`s.

use std::fmt;
use std::iter::Iterator;
use std::marker::PhantomData;
use serde::Deserialize;
use mongodb;
use bsn::*;
use error::{ Result, ResultExt };

/// A typed wrapper around the MongoDB `Cursor` type.
pub struct Cursor<T> where T: for<'a> Deserialize<'a> {
    /// The underlying MongoDB cursor.
    inner: mongodb::cursor::Cursor,
    /// Just here so that the type parameter is used.
    _marker: PhantomData<T>,
}

impl<T> Cursor<T> where T: for<'a> Deserialize<'a> {
    /// Reads the remaining documents available in the current batch.
    pub fn next_batch(&mut self) -> Result<Vec<T>> {
        self.inner
            .drain_current_batch()
            .chain("couldn't retrieve next batch")
            .and_then(deserialize_documents)
    }

    /// Retrieves the next at most `n` documents.
    #[cfg_attr(feature = "cargo-clippy", allow(cast_possible_wrap, cast_possible_truncation))]
    pub fn next_n(&mut self, n: usize) -> Result<Vec<T>> {
        self.inner
            .next_n(n)
            .chain("couldn't retrieve documents")
            .and_then(deserialize_documents)
    }

    /// Checks whether there are any more documents for the cursor to yield.
    pub fn has_next(&mut self) -> Result<bool> {
        self.inner.has_next().chain("cursor error")
    }
}

#[doc(hidden)]
impl<T> From<mongodb::cursor::Cursor> for Cursor<T> where T: for<'a> Deserialize<'a> {
    fn from(cursor: mongodb::cursor::Cursor) -> Self {
        Cursor {
            inner: cursor,
            _marker: PhantomData,
        }
    }
}

impl<T> Iterator for Cursor<T> where T: for<'a> Deserialize<'a> {
    type Item = Result<T>;

    fn next(&mut self) -> Option<Self::Item> {
        self.inner
            .next()
            .map(|r| r.chain("can't step Cursor").and_then(deserialize_document))
    }
}

impl<T> fmt::Debug for Cursor<T> where T: for<'a> Deserialize<'a> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        f.debug_struct("Cursor").finish()
    }
}