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
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
use crate::{
document::{C4DocumentOwner, Document},
error::{c4error_init, Error, Result},
ffi::{
c4db_enumerateAllDocs, c4enum_free, c4enum_getDocument, c4enum_next, C4DocEnumerator,
C4EnumeratorOptions,
},
Database,
};
use bitflags::bitflags;
use fallible_streaming_iterator::FallibleStreamingIterator;
use std::ptr::NonNull;
pub struct DocEnumerator<'a> {
_db: &'a Database,
reach_end: bool,
inner: NonNull<C4DocEnumerator>,
}
impl Drop for DocEnumerator<'_> {
fn drop(&mut self) {
unsafe { c4enum_free(self.inner.as_ptr()) };
}
}
impl<'a> DocEnumerator<'a> {
pub(crate) fn enumerate_all_docs(
db: &'a Database,
flags: DocEnumeratorFlags,
) -> Result<DocEnumerator<'a>> {
let mut c4err = c4error_init();
let opts = C4EnumeratorOptions { flags: flags.bits };
let enum_ptr = unsafe { c4db_enumerateAllDocs(db.inner.0.as_ptr(), &opts, &mut c4err) };
NonNull::new(enum_ptr)
.map(|inner| DocEnumerator {
_db: db,
inner,
reach_end: false,
})
.ok_or_else(|| c4err.into())
}
pub fn get_doc(&self) -> Result<Document> {
let mut c4err = c4error_init();
let doc_ptr = unsafe { c4enum_getDocument(self.inner.as_ptr(), &mut c4err) };
let c4doc: C4DocumentOwner =
NonNull::new(doc_ptr).map(C4DocumentOwner).ok_or_else(|| {
let err: Error = c4err.into();
err
})?;
let id: String = c4doc.id()?.into();
Ok(Document::new_internal(c4doc, id))
}
}
impl<'en> FallibleStreamingIterator for DocEnumerator<'en> {
type Error = crate::error::Error;
type Item = DocEnumerator<'en>;
fn advance(&mut self) -> Result<()> {
if self.reach_end {
return Ok(());
}
let mut c4err = c4error_init();
if unsafe { c4enum_next(self.inner.as_ptr(), &mut c4err) } {
Ok(())
} else if c4err.code == 0 {
self.reach_end = true;
Ok(())
} else {
Err(c4err.into())
}
}
fn get(&self) -> Option<&DocEnumerator<'en>> {
if !self.reach_end {
Some(self)
} else {
None
}
}
}
bitflags! {
pub struct DocEnumeratorFlags: u16 {
const DESCENDING = 0x01;
const INCLUDE_DELETED = 0x08;
const INCLUDE_NON_CONFLICTED = 0x10;
const INCLUDE_BODIES = 0x20;
}
}
impl Default for DocEnumeratorFlags {
fn default() -> Self {
DocEnumeratorFlags::INCLUDE_BODIES | DocEnumeratorFlags::INCLUDE_NON_CONFLICTED
}
}