diff options
Diffstat (limited to 'src/messages.rs')
| -rw-r--r-- | src/messages.rs | 140 |
1 files changed, 76 insertions, 64 deletions
diff --git a/src/messages.rs b/src/messages.rs index 88c52ec..dc0f59e 100644 --- a/src/messages.rs +++ b/src/messages.rs @@ -1,63 +1,51 @@ use std::ops::Drop; -use supercow::{Phantomcow, Supercow}; - -use crate::ffi; -use crate::utils::{StreamingIterator, StreamingIteratorExt}; -use crate::Message; -use crate::MessageOwner; -use crate::Tags; -use crate::TagsOwner; - -pub trait MessagesOwner {} +use ffi; +use utils::ScopedPhantomcow; +use MessageOwner; +use Message; +use Tags; +use TagsOwner; #[derive(Debug)] -pub struct MessagesPtr { - pub ptr: *mut ffi::notmuch_messages_t, +pub struct Messages<'o, O> +where + O: MessageOwner + 'o, +{ + pub(crate) ptr: *mut ffi::notmuch_messages_t, + marker: ScopedPhantomcow<'o, O>, } -impl Drop for MessagesPtr { +impl<'o, O> Drop for Messages<'o, O> +where + O: MessageOwner + 'o, +{ fn drop(self: &mut Self) { - let valid = unsafe { ffi::notmuch_messages_valid(self.ptr) }; - - if valid == 0 { - return; - } - unsafe { ffi::notmuch_messages_destroy(self.ptr) }; } } -#[derive(Debug)] -pub struct Messages<'o, O> -where - O: MessagesOwner, -{ - pub(crate) handle: MessagesPtr, - marker: Phantomcow<'o, O>, -} - impl<'o, O> Messages<'o, O> where - O: MessagesOwner + 'o, + O: MessageOwner + 'o, { pub(crate) fn from_ptr<P>(ptr: *mut ffi::notmuch_messages_t, owner: P) -> Messages<'o, O> where - P: Into<Phantomcow<'o, O>>, + P: Into<ScopedPhantomcow<'o, O>>, { Messages { - handle: MessagesPtr { ptr }, + ptr, marker: owner.into(), } } } -impl<'o, O> MessageOwner for Messages<'o, O> where O: MessagesOwner + 'o {} -impl<'o, O> TagsOwner for Messages<'o, O> where O: MessagesOwner + 'o {} +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: MessagesOwner + 'o, + O: MessageOwner + 'o, { /** * Return a list of tags from all messages. @@ -74,53 +62,77 @@ where */ pub fn collect_tags<'m>(self: &'o Self) -> Tags<'m, Self> { Tags::from_ptr( - unsafe { ffi::notmuch_messages_collect_tags(self.handle.ptr) }, + unsafe { ffi::notmuch_messages_collect_tags(self.ptr) }, self, ) } } -impl<'s, 'o: 's, O> StreamingIterator<'s, Message<'s, Self>> for Messages<'o, O> +impl<'o, O> Iterator for Messages<'o, O> where - O: MessagesOwner + 'o, + O: MessageOwner + 'o, { - fn next(&'s mut self) -> Option<Message<'s, Self>> { - <Self as StreamingIteratorExt<'s, Message<'s, Self>>>::next(Supercow::borrowed(self)) + 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: MessagesOwner + 'o, + O: MessageOwner + 'o, { } -impl<'o, O> MessagesExt<'o, O> for Messages<'o, O> where O: MessagesOwner + 'o {} - -impl<'s, 'o: 's, O> StreamingIteratorExt<'s, Message<'s, Self>> for Messages<'o, O> -where - O: MessagesOwner + 'o, -{ - fn next<S>(messages: S) -> Option<Message<'s, Self>> - where - S: Into<Supercow<'s, Messages<'o, O>>>, - { - let messagesref = messages.into(); - let valid = unsafe { ffi::notmuch_messages_valid(messagesref.handle.ptr) }; +impl<'o, O> MessagesExt<'o, O> for Messages<'o, O> where O: MessageOwner + 'o {} - if valid == 0 { - return None; - } - let cmsg = unsafe { - let msg = ffi::notmuch_messages_get(messagesref.handle.ptr); - ffi::notmuch_messages_move_to_next(messagesref.handle.ptr); - msg - }; +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 {} - Some(Message::from_ptr(cmsg, Supercow::phantom(messagesref))) +#[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); + } + } } } - -unsafe impl<'o, O> Send for Messages<'o, O> where O: MessagesOwner + 'o {} -unsafe impl<'o, O> Sync for Messages<'o, O> where O: MessagesOwner + 'o {} |
