aboutsummaryrefslogtreecommitdiffstats
path: root/notmuch/src/messages.rs
diff options
context:
space:
mode:
Diffstat (limited to 'notmuch/src/messages.rs')
-rw-r--r--notmuch/src/messages.rs136
1 files changed, 136 insertions, 0 deletions
diff --git a/notmuch/src/messages.rs b/notmuch/src/messages.rs
new file mode 100644
index 0000000..cfba547
--- /dev/null
+++ b/notmuch/src/messages.rs
@@ -0,0 +1,136 @@
+use ffi;
+use utils::ScopedPhantomcow;
+use MessageOwner;
+use Message;
+use Tags;
+use TagsOwner;
+
+#[derive(Debug)]
+pub struct Messages<'o, O>
+where
+ O: MessageOwner + 'o,
+{
+ pub(crate) ptr: *mut ffi::notmuch_messages_t,
+ marker: ScopedPhantomcow<'o, O>,
+}
+
+// impl<'o, O> Drop for Messages<'o, O>
+// where
+// O: MessageOwner + 'o,
+// {
+// fn drop(self: &mut Self) {
+// unsafe { ffi::notmuch_messages_destroy(self.ptr) };
+// }
+// }
+
+impl<'o, O> Messages<'o, O>
+where
+ O: MessageOwner + 'o,
+{
+ pub(crate) fn from_ptr<P>(ptr: *mut ffi::notmuch_messages_t, owner: P) -> Messages<'o, O>
+ where
+ P: Into<ScopedPhantomcow<'o, O>>,
+ {
+ Messages {
+ ptr,
+ marker: owner.into(),
+ }
+ }
+}
+
+impl<'o, O> MessageOwner for Messages<'o, O> where O: MessageOwner + 'o {}
+impl<'o, O> TagsOwner for Messages<'o, O> where O: MessageOwner + 'o {}
+
+impl<'o, O> Messages<'o, O>
+where
+ O: MessageOwner + 'o,
+{
+ /**
+ * Return a list of tags from all messages.
+ *
+ * The resulting list is guaranteed not to contain duplicated tags.
+ *
+ * WARNING: You can no longer iterate over messages after calling this
+ * function, because the iterator will point at the end of the list.
+ * We do not have a function to reset the iterator yet and the only
+ * way how you can iterate over the list again is to recreate the
+ * message list.
+ *
+ * The function returns NULL on error.
+ */
+ pub fn collect_tags<'m>(self: &'o Self) -> Tags<'m, Self> {
+ Tags::from_ptr(
+ unsafe { ffi::notmuch_messages_collect_tags(self.ptr) },
+ self,
+ )
+ }
+}
+
+impl<'o, O> Iterator for Messages<'o, O>
+where
+ O: MessageOwner + 'o,
+{
+ type Item = Message<'o, O>;
+
+ fn next(&mut self) -> Option<Self::Item> {
+ let valid = unsafe { ffi::notmuch_messages_valid(self.ptr) };
+
+ if valid == 0 {
+ return None;
+ }
+
+ let cthrd = unsafe {
+ let thrd = ffi::notmuch_messages_get(self.ptr);
+ ffi::notmuch_messages_move_to_next(self.ptr);
+ thrd
+ };
+
+ Some(Message::from_ptr(cthrd, ScopedPhantomcow::<'o, O>::share(&mut self.marker)))
+ }
+}
+
+
+
+pub trait MessagesExt<'o, O>
+where
+ O: MessageOwner + 'o,
+{
+}
+
+impl<'o, O> MessagesExt<'o, O> for Messages<'o, O> where O: MessageOwner + 'o {}
+
+
+unsafe impl<'o, O> Send for Messages<'o, O> where O: MessageOwner + 'o {}
+unsafe impl<'o, O> Sync for Messages<'o, O> where O: MessageOwner + 'o {}
+
+#[cfg(test)]
+mod tests {
+ // This will not compile if ownership can't be subject to recursion
+ fn descend<'o, O: 'o + super::MessageOwner, T: Iterator<Item=super::Message<'o, O>>>(iter: T)
+ -> usize {
+ iter.map(|msg| descend(msg.replies()) ).count()
+ }
+
+ use query::Query;
+ use database;
+
+ #[test]
+ #[should_panic] // until test data is filled in
+ fn recurse() {
+ match database::Database::open(
+ &String::new(),
+ database::DatabaseMode::ReadOnly,
+ ) {
+ /* This will not happen without test data, but will force the compiler to compile
+ * the descend function.
+ */
+ Ok(db) => {
+ let q = Query::create(db, &String::new()).unwrap();
+ descend::<Query, super::Messages<Query>>(q.search_messages().unwrap());
+ }
+ Err(err) => {
+ panic!("Got error while trying to open db: {:?}", err);
+ }
+ }
+ }
+}