diff options
| -rw-r--r-- | Cargo.toml | 1 | ||||
| -rw-r--r-- | src/database.rs | 73 | ||||
| -rw-r--r-- | src/directory.rs | 35 | ||||
| -rw-r--r-- | src/error.rs | 12 | ||||
| -rw-r--r-- | src/ffi.rs | 6 | ||||
| -rw-r--r-- | src/filenames.rs | 43 | ||||
| -rw-r--r-- | src/lib.rs | 27 | ||||
| -rw-r--r-- | src/message.rs | 110 | ||||
| -rw-r--r-- | src/messages.rs | 140 | ||||
| -rw-r--r-- | src/query.rs | 79 | ||||
| -rw-r--r-- | src/tags.rs | 33 | ||||
| -rw-r--r-- | src/thread.rs | 110 | ||||
| -rw-r--r-- | src/threads.rs | 98 | ||||
| -rw-r--r-- | src/utils.rs | 32 | ||||
| -rw-r--r-- | tests/main.rs | 11 |
15 files changed, 374 insertions, 436 deletions
@@ -7,7 +7,6 @@ repository = "https://github.com/vhdirk/notmuch-rs" description = "Rust interface and bindings for notmuch" license = "GPL-3.0+" readme = "README.md" -edition = "2018" [badges] travis-ci = { repository = "vhdirk/notmuch-rs" } diff --git a/src/database.rs b/src/database.rs index fe9a39b..027a43f 100644 --- a/src/database.rs +++ b/src/database.rs @@ -7,18 +7,19 @@ use supercow::Supercow; use libc; -use crate::error::{Error, Result}; -use crate::ffi; -use crate::ffi::Status; -use crate::query::QueryPtr; -use crate::utils::ToStr; -use crate::Directory; -use crate::Query; -use crate::Tags; -use crate::TagsOwner; +use error::{Error, Result}; +use ffi; +use ffi::Status; +use utils::ToStr; +use Directory; +use Query; +use Tags; +use TagsOwner; +use utils::ScopedSupercow; + // Re-exported under database module for pretty namespacin'. -pub use crate::ffi::DatabaseMode; +pub use ffi::DatabaseMode; #[derive(Copy, Clone, Debug)] pub struct Version(libc::c_uint); @@ -29,32 +30,18 @@ pub struct Revision { pub uuid: String, } + #[derive(Debug)] -pub(crate) struct DatabasePtr { - pub ptr: *mut ffi::notmuch_database_t, +pub struct Database { + pub(crate) ptr: *mut ffi::notmuch_database_t, } -impl Drop for DatabasePtr { +impl Drop for Database { fn drop(&mut self) { unsafe { ffi::notmuch_database_destroy(self.ptr) }; } } -impl DatabasePtr { - pub(crate) fn create_query(&self, query_string: &str) -> Result<QueryPtr> { - let query_str = CString::new(query_string).unwrap(); - - let query = unsafe { ffi::notmuch_query_create(self.ptr, query_str.as_ptr()) }; - - Ok(QueryPtr { ptr: query }) - } -} - -#[derive(Debug)] -pub struct Database { - pub(crate) handle: DatabasePtr, -} - impl TagsOwner for Database {} impl Database { @@ -68,7 +55,7 @@ impl Database { unsafe { ffi::notmuch_database_create(path_str.as_ptr(), &mut db) }.as_result()?; Ok(Database { - handle: DatabasePtr { ptr: db }, + ptr: db, }) } @@ -83,12 +70,12 @@ impl Database { .as_result()?; Ok(Database { - handle: DatabasePtr { ptr: db }, + ptr: db, }) } pub fn close(&mut self) -> Result<()> { - unsafe { ffi::notmuch_database_close(self.handle.ptr) }.as_result()?; + unsafe { ffi::notmuch_database_close(self.ptr) }.as_result()?; Ok(()) } @@ -145,14 +132,14 @@ impl Database { pub fn path(&self) -> &Path { Path::new( - unsafe { ffi::notmuch_database_get_path(self.handle.ptr) } + unsafe { ffi::notmuch_database_get_path(self.ptr) } .to_str() .unwrap(), ) } pub fn version(&self) -> Version { - Version(unsafe { ffi::notmuch_database_get_version(self.handle.ptr) }) + Version(unsafe { ffi::notmuch_database_get_version(self.ptr) }) } #[cfg(feature = "v0_21")] @@ -160,7 +147,7 @@ impl Database { let uuid_p: *const libc::c_char = ptr::null(); let revision = unsafe { ffi::notmuch_database_get_revision( - self.handle.ptr, + self.ptr, (&uuid_p) as *const _ as *mut *const libc::c_char, ) }; @@ -174,7 +161,7 @@ impl Database { } pub fn needs_upgrade(&self) -> bool { - unsafe { ffi::notmuch_database_needs_upgrade(self.handle.ptr) == 1 } + unsafe { ffi::notmuch_database_needs_upgrade(self.ptr) == 1 } } pub fn upgrade<F>(&mut self) -> Result<()> @@ -207,7 +194,7 @@ impl Database { unsafe { ffi::notmuch_database_upgrade( - self.handle.ptr, + self.ptr, if status.is_some() { Some(wrapper::<F>) } else { @@ -251,25 +238,25 @@ pub trait DatabaseExt { let dbref = database.into(); let query_str = CString::new(query_string).unwrap(); - let query = unsafe { ffi::notmuch_query_create(dbref.handle.ptr, query_str.as_ptr()) }; + let query = unsafe { ffi::notmuch_query_create(dbref.ptr, query_str.as_ptr()) }; Ok(Query::from_ptr(query, Supercow::phantom(dbref))) } fn all_tags<'d, D>(database: D) -> Result<Tags<'d, Database>> where - D: Into<Supercow<'d, Database>>, + D: Into<ScopedSupercow<'d, Database>>, { let dbref = database.into(); - let tags = unsafe { ffi::notmuch_database_get_all_tags(dbref.handle.ptr) }; + let tags = unsafe { ffi::notmuch_database_get_all_tags(dbref.ptr) }; - Ok(Tags::from_ptr(tags, Supercow::phantom(dbref))) + Ok(Tags::from_ptr(tags, ScopedSupercow::phantom(dbref))) } fn directory<'d, D, P>(database: D, path: &P) -> Result<Option<Directory<'d>>> where - D: Into<Supercow<'d, Database>>, + D: Into<ScopedSupercow<'d, Database>>, P: AsRef<Path>, { let dbref = database.into(); @@ -278,7 +265,7 @@ pub trait DatabaseExt { let mut dir = ptr::null_mut(); unsafe { - ffi::notmuch_database_get_directory(dbref.handle.ptr, path_str.as_ptr(), &mut dir) + ffi::notmuch_database_get_directory(dbref.ptr, path_str.as_ptr(), &mut dir) }.as_result()?; if dir.is_null() { @@ -298,7 +285,7 @@ pub trait DatabaseExt { Some(path_str) => { let msg_path = CString::new(path_str).unwrap(); - unsafe { ffi::notmuch_database_remove_message(dbref.handle.ptr, msg_path.as_ptr()) } + unsafe { ffi::notmuch_database_remove_message(dbref.ptr, msg_path.as_ptr()) } .as_result() } None => Err(Error::NotmuchError(Status::FileError)), diff --git a/src/directory.rs b/src/directory.rs index be2ea5c..8f09ed7 100644 --- a/src/directory.rs +++ b/src/directory.rs @@ -1,42 +1,39 @@ use std::ops::Drop; -use supercow::{Phantomcow, Supercow}; +use supercow::Supercow; + +use ffi; +use Database; +use Filenames; +use FilenamesOwner; +use utils::{ScopedSupercow, ScopedPhantomcow}; -use crate::ffi; -use crate::Database; -use crate::Filenames; -use crate::FilenamesOwner; #[derive(Debug)] -pub(crate) struct DirectoryPtr { - pub ptr: *mut ffi::notmuch_directory_t, +pub struct Directory<'d> { + ptr: *mut ffi::notmuch_directory_t, + marker: ScopedPhantomcow<'d, Database>, } -impl Drop for DirectoryPtr { +impl<'d> Drop for Directory<'d> { fn drop(&mut self) { unsafe { ffi::notmuch_directory_destroy(self.ptr) }; } } -#[derive(Debug)] -pub struct Directory<'d> { - handle: DirectoryPtr, - marker: Phantomcow<'d, Database>, -} - impl<'d> FilenamesOwner for Directory<'d> {} impl<'d> Directory<'d> { pub fn from_ptr<O>(ptr: *mut ffi::notmuch_directory_t, owner: O) -> Directory<'d> where - O: Into<Phantomcow<'d, Database>>, + O: Into<ScopedPhantomcow<'d, Database>>, { Directory { - handle: DirectoryPtr { ptr }, + ptr, marker: owner.into(), } } - pub fn child_directories(&self) -> Filenames<'_, Self> { + pub fn child_directories(&self) -> Filenames<Self> { <Self as DirectoryExt>::child_directories(self) } } @@ -44,11 +41,11 @@ impl<'d> Directory<'d> { pub trait DirectoryExt<'d> { fn child_directories<'s, S>(directory: S) -> Filenames<'s, Directory<'d>> where - S: Into<Supercow<'s, Directory<'d>>>, + S: Into<ScopedSupercow<'s, Directory<'d>>>, { let dir = directory.into(); Filenames::from_ptr( - unsafe { ffi::notmuch_directory_get_child_directories(dir.handle.ptr) }, + unsafe { ffi::notmuch_directory_get_child_directories(dir.ptr) }, Supercow::phantom(dir), ) } diff --git a/src/error.rs b/src/error.rs index 3eba2ba..824cc39 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,7 +1,7 @@ use std; use std::{error, fmt, io, result}; -use crate::ffi; +use ffi; pub type Result<T> = result::Result<T, Error>; @@ -13,7 +13,7 @@ pub enum Error { } impl fmt::Display for Error { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", error::Error::description(self)) } } @@ -27,10 +27,10 @@ impl std::error::Error for Error { } } - fn cause(&self) -> Option<&dyn error::Error> { - match self { - Error::IoError(e) => Some(e), - Error::NotmuchError(e) => Some(e), + fn cause(&self) -> Option<&error::Error> { + match *self { + Error::IoError(ref e) => Some(e), + Error::NotmuchError(ref e) => Some(e), Error::UnspecifiedError => None, } } @@ -4,10 +4,10 @@ use libc::{c_char, c_double, c_int, c_uint, c_ulong, c_void, time_t}; -use crate::error::{Error, Result}; +use error::{Error, Result}; use std::{error, fmt, str}; -use crate::utils::ToStr; +use utils::ToStr; notmuch_enum! { #[repr(C)] @@ -60,7 +60,7 @@ impl ToStr for Status { } impl fmt::Display for Status { - fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { write!(f, "{}", self.to_str().unwrap()) } } diff --git a/src/filenames.rs b/src/filenames.rs index ad4c3e9..a4440d3 100644 --- a/src/filenames.rs +++ b/src/filenames.rs @@ -3,34 +3,27 @@ use std::iter::Iterator; use std::ops::Drop; use std::path::PathBuf; -use supercow::Phantomcow; - -use crate::ffi; +use ffi; +use utils::ScopedPhantomcow; pub trait FilenamesOwner {} #[derive(Debug)] -pub(crate) struct FilenamesPtr { - pub ptr: *mut ffi::notmuch_filenames_t, -} - -impl Drop for FilenamesPtr { - fn drop(self: &mut Self) { - let valid = unsafe { ffi::notmuch_filenames_valid(self.ptr) }; - - if valid != 0 { - unsafe { ffi::notmuch_filenames_destroy(self.ptr) }; - } - } +pub struct Filenames<'o, O> +where + O: FilenamesOwner + 'o, +{ + pub(crate) ptr: *mut ffi::notmuch_filenames_t, + pub(crate) marker: ScopedPhantomcow<'o, O>, } -#[derive(Debug)] -pub struct Filenames<'o, O> +impl<'o, O> Drop for Filenames<'o, O> where - O: FilenamesOwner, + O: FilenamesOwner + 'o, { - pub(crate) handle: FilenamesPtr, - pub(crate) marker: Phantomcow<'o, O>, + fn drop(self: &mut Self) { + unsafe { ffi::notmuch_filenames_destroy(self.ptr) }; + } } impl<'o, O> Filenames<'o, O> @@ -39,10 +32,10 @@ where { pub fn from_ptr<P>(ptr: *mut ffi::notmuch_filenames_t, owner: P) -> Filenames<'o, O> where - P: Into<Phantomcow<'o, O>>, + P: Into<ScopedPhantomcow<'o, O>>, { Filenames { - handle: FilenamesPtr { ptr }, + ptr, marker: owner.into(), } } @@ -55,15 +48,15 @@ where type Item = PathBuf; fn next(self: &mut Self) -> Option<Self::Item> { - let valid = unsafe { ffi::notmuch_filenames_valid(self.handle.ptr) }; + let valid = unsafe { ffi::notmuch_filenames_valid(self.ptr) }; if valid == 0 { return None; } let ctag = unsafe { - let t = ffi::notmuch_filenames_get(self.handle.ptr); - ffi::notmuch_filenames_move_to_next(self.handle.ptr); + let t = ffi::notmuch_filenames_get(self.ptr); + ffi::notmuch_filenames_move_to_next(self.ptr); CStr::from_ptr(t) }; @@ -4,8 +4,8 @@ #[macro_use] mod macros; -use libc; - +extern crate libc; +extern crate supercow; mod ffi; mod utils; @@ -21,16 +21,15 @@ mod tags; mod thread; mod threads; -pub use crate::database::{Database, DatabaseExt}; -pub use crate::directory::{Directory, DirectoryExt}; -pub use crate::error::Error; -pub use crate::filenames::{Filenames, FilenamesOwner}; -pub use crate::message::{Message, MessageExt, MessageOwner}; -pub use crate::messages::{Messages, MessagesExt, MessagesOwner}; -pub use crate::query::{Query, QueryExt}; -pub use crate::tags::{Tags, TagsExt, TagsOwner}; -pub use crate::thread::{Thread, ThreadExt, ThreadOwner}; -pub use crate::threads::{Threads, ThreadsExt, ThreadsOwner}; +pub use database::{Database, DatabaseExt}; +pub use directory::{Directory, DirectoryExt}; +pub use error::Error; +pub use filenames::{Filenames, FilenamesOwner}; +pub use message::{Message, MessageExt, MessageOwner}; +pub use messages::{Messages, MessagesExt}; +pub use query::{Query, QueryExt}; +pub use tags::{Tags, TagsExt, TagsOwner}; +pub use thread::{Thread, ThreadExt}; +pub use threads::{Threads, ThreadsExt}; -pub use crate::ffi::{DatabaseMode, Sort}; -pub use crate::utils::{StreamingIterator, StreamingIteratorExt}; +pub use ffi::{DatabaseMode, Sort};
\ No newline at end of file diff --git a/src/message.rs b/src/message.rs index b4bb581..226d3b8 100644 --- a/src/message.rs +++ b/src/message.rs @@ -1,43 +1,29 @@ use std::ffi::CString; -use std::ops::Drop; use std::path::PathBuf; -use supercow::{Phantomcow, Supercow}; +use std::cell::RefCell; +use supercow::{Supercow}; -use crate::error::{Error, Result}; -use crate::ffi; -use crate::utils::ToStr; -use crate::Filenames; -use crate::FilenamesOwner; -use crate::Messages; -use crate::MessagesOwner; -use crate::Tags; -use crate::TagsOwner; +use error::{Error, Result}; +use ffi; +use utils::{ToStr, ScopedPhantomcow, ScopedSupercow}; +use Filenames; +use FilenamesOwner; +use Messages; +use Tags; +use TagsOwner; -pub trait MessageOwner {} - -#[derive(Debug)] -pub(crate) struct MessagePtr { - pub ptr: *mut ffi::notmuch_message_t, -} - -// TODO: The iterator doesn't actually own these, so dropping these will -// generate a segfault when a new iterator is constructed. -// impl Drop for MessagePtr { -// fn drop(&mut self) { -// unsafe { ffi::notmuch_message_destroy(self.ptr) }; -// } -// } +pub trait MessageOwner: Send + Sync {} #[derive(Debug)] pub struct Message<'o, O> where - O: MessageOwner, + O: MessageOwner + 'o, { - pub(crate) handle: MessagePtr, - marker: Phantomcow<'o, O>, + pub(crate) ptr: *mut ffi::notmuch_message_t, + marker: RefCell<ScopedPhantomcow<'o, O>>, } -impl<'o, O> MessagesOwner for Message<'o, O> where O: MessageOwner + 'o {} +impl<'o, O> MessageOwner for Message<'o, O> where O: MessageOwner + 'o {} impl<'o, O> FilenamesOwner for Message<'o, O> where O: MessageOwner + 'o {} impl<'o, O> TagsOwner for Message<'o, O> where O: MessageOwner + 'o {} @@ -45,54 +31,58 @@ impl<'o, O> Message<'o, O> where O: MessageOwner + 'o, { - pub fn from_ptr<P>(ptr: *mut ffi::notmuch_message_t, owner: P) -> Message<'o, O> + pub(crate) fn from_ptr<P>(ptr: *mut ffi::notmuch_message_t, owner: P) -> Message<'o, O> where - P: Into<Phantomcow<'o, O>>, + P: Into<ScopedPhantomcow<'o, O>>, { Message { - handle: MessagePtr { ptr }, - marker: owner.into(), + ptr, + marker: RefCell::new(owner.into()), } } pub fn id(self: &Self) -> String { - let mid = unsafe { ffi::notmuch_message_get_message_id(self.handle.ptr) }; + let mid = unsafe { ffi::notmuch_message_get_message_id(self.ptr) }; mid.to_str().unwrap().to_string() } pub fn thread_id(self: &Self) -> String { - let tid = unsafe { ffi::notmuch_message_get_thread_id(self.handle.ptr) }; + let tid = unsafe { ffi::notmuch_message_get_thread_id(self.ptr) }; tid.to_str().unwrap().to_string() } - pub fn replies(self: &Self) -> Messages<'_, Self> { - <Self as MessageExt<'o, O>>::replies(self) + pub fn replies(self: &Self) -> Messages<'o, O> { + Messages::<'o, O>::from_ptr( + unsafe { ffi::notmuch_message_get_replies(self.ptr) }, + // will never panic since the borrow is released immediately + ScopedPhantomcow::<'o, O>::share(&mut *(self.marker.borrow_mut())) + ) } #[cfg(feature = "v0_26")] pub fn count_files(self: &Self) -> i32 { - unsafe { ffi::notmuch_message_count_files(self.handle.ptr) } + unsafe { ffi::notmuch_message_count_files(self.ptr) } } - pub fn filenames(self: &Self) -> Filenames<'_, Self> { + pub fn filenames(self: &Self) -> Filenames<Self> { <Self as MessageExt<'o, O>>::filenames(self) } pub fn filename(self: &Self) -> PathBuf { PathBuf::from( - unsafe { ffi::notmuch_message_get_filename(self.handle.ptr) } + unsafe { ffi::notmuch_message_get_filename(self.ptr) } .to_str() .unwrap(), ) } pub fn date(&self) -> i64 { - unsafe { ffi::notmuch_message_get_date(self.handle.ptr) as i64 } + unsafe { ffi::notmuch_message_get_date(self.ptr) as i64 } } pub fn header(&self, name: &str) -> Result<Option<&str>> { let name = CString::new(name).unwrap(); - let ret = unsafe { ffi::notmuch_message_get_header(self.handle.ptr, name.as_ptr()) }; + let ret = unsafe { ffi::notmuch_message_get_header(self.ptr, name.as_ptr()) }; if ret.is_null() { Err(Error::UnspecifiedError) } else { @@ -103,22 +93,22 @@ where } } - pub fn tags(&self) -> Tags<'_, Self> { + pub fn tags(&self) -> Tags<Self> { <Self as MessageExt<'o, O>>::tags(self) } pub fn add_tag(self: &Self, tag: &str) -> Result<()> { let tag = CString::new(tag).unwrap(); - unsafe { ffi::notmuch_message_add_tag(self.handle.ptr, tag.as_ptr()) }.as_result() + unsafe { ffi::notmuch_message_add_tag(self.ptr, tag.as_ptr()) }.as_result() } pub fn remove_tag(self: &Self, tag: &str) -> Result<()> { let tag = CString::new(tag).unwrap(); - unsafe { ffi::notmuch_message_remove_tag(self.handle.ptr, tag.as_ptr()) }.as_result() + unsafe { ffi::notmuch_message_remove_tag(self.ptr, tag.as_ptr()) }.as_result() } pub fn remove_all_tags(self: &Self) -> Result<()> { - unsafe { ffi::notmuch_message_remove_all_tags(self.handle.ptr) }.as_result() + unsafe { ffi::notmuch_message_remove_all_tags(self.ptr) }.as_result() } } @@ -128,33 +118,33 @@ where { fn tags<'s, S>(message: S) -> Tags<'s, Message<'o, O>> where - S: Into<Supercow<'s, Message<'o, O>>>, + S: Into<ScopedSupercow<'s, Message<'o, O>>>, { let messageref = message.into(); Tags::from_ptr( - unsafe { ffi::notmuch_message_get_tags(messageref.handle.ptr) }, + unsafe { ffi::notmuch_message_get_tags(messageref.ptr) }, Supercow::phantom(messageref), ) } - fn replies<'s, S>(message: S) -> Messages<'s, Message<'o, O>> - where - S: Into<Supercow<'s, Message<'o, O>>>, - { - let messageref = message.into(); - Messages::from_ptr( - unsafe { ffi::notmuch_message_get_replies(messageref.handle.ptr) }, - Supercow::phantom(messageref), - ) - } + // fn replies<'s, S>(message: S) -> Messages<'s, Message<'o, O>> + // where + // S: Into<ScopedSupercow<'s, Message<'o, O>>>, + // { + // let messageref = message.into(); + // Messages::from_ptr( + // unsafe { ffi::notmuch_message_get_replies(messageref.ptr) }, + // Supercow::phantom(messageref), + // ) + // } fn filenames<'s, S>(message: S) -> Filenames<'s, Message<'o, O>> where - S: Into<Supercow<'s, Message<'o, O>>>, + S: Into<ScopedSupercow<'s, Message<'o, O>>>, { let messageref = message.into(); Filenames::from_ptr( - unsafe { ffi::notmuch_message_get_filenames(messageref.handle.ptr) }, + unsafe { ffi::notmuch_message_get_filenames(messageref.ptr) }, Supercow::phantom(messageref), ) } 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 {} diff --git a/src/query.rs b/src/query.rs index 3dba264..127a9ab 100644 --- a/src/query.rs +++ b/src/query.rs @@ -3,34 +3,29 @@ use std::ptr; use supercow::{Phantomcow, Supercow}; -use crate::error::Result; -use crate::ffi; -use crate::ffi::Sort; -use crate::Database; -use crate::Messages; -use crate::MessagesOwner; -use crate::Threads; -use crate::ThreadsOwner; +use error::Result; +use ffi; +use ffi::Sort; +use Database; +use Messages; +use MessageOwner; +use Threads; +use DatabaseExt; +use utils::ScopedSupercow; #[derive(Debug)] -pub(crate) struct QueryPtr { - pub ptr: *mut ffi::notmuch_query_t, +pub struct Query<'d> { + pub(crate) ptr: *mut ffi::notmuch_query_t, + marker: Phantomcow<'d, Database>, } -impl Drop for QueryPtr { +impl<'d> Drop for Query<'d> { fn drop(&mut self) { unsafe { ffi::notmuch_query_destroy(self.ptr) }; } } -#[derive(Debug)] -pub struct Query<'d> { - pub(crate) handle: QueryPtr, - marker: Phantomcow<'d, Database>, -} - -impl<'d> ThreadsOwner for Query<'d> {} -impl<'d> MessagesOwner for Query<'d> {} +impl<'d> MessageOwner for Query<'d> {} impl<'d> Query<'d> { pub(crate) fn from_ptr<O>(ptr: *mut ffi::notmuch_query_t, owner: O) -> Query<'d> @@ -38,17 +33,7 @@ impl<'d> Query<'d> { O: Into<Phantomcow<'d, Database>>, { Query { - handle: QueryPtr { ptr }, - marker: owner.into(), - } - } - - pub(crate) fn from_handle<O>(handle: QueryPtr, owner: O) -> Query<'d> - where - O: Into<Phantomcow<'d, Database>>, - { - Query { - handle, + ptr, marker: owner.into(), } } @@ -57,73 +42,69 @@ impl<'d> Query<'d> { where D: Into<Supercow<'d, Database>>, { - let dbref = db.into(); - dbref - .handle - .create_query(query_string) - .map(move |handle| Query::from_handle(handle, Supercow::phantom(dbref))) + <Database as DatabaseExt>::create_query(db, query_string) } /// Specify the sorting desired for this query. pub fn set_sort(self: &Self, sort: Sort) { - unsafe { ffi::notmuch_query_set_sort(self.handle.ptr, sort.into()) } + unsafe { ffi::notmuch_query_set_sort(self.ptr, sort.into()) } } /// Return the sort specified for this query. See /// `set_sort`. pub fn sort(self: &Self) -> Sort { - unsafe { ffi::notmuch_query_get_sort(self.handle.ptr) }.into() + unsafe { ffi::notmuch_query_get_sort(self.ptr) }.into() } /// Filter messages according to the query and return pub fn search_messages<'q>(self: &'d Self) -> Result<Messages<'q, Self>> { - <Query<'_> as QueryExt>::search_messages(self) + <Query as QueryExt>::search_messages(self) } pub fn count_messages(self: &Self) -> Result<u32> { let mut cnt = 0; - unsafe { ffi::notmuch_query_count_messages(self.handle.ptr, &mut cnt) }.as_result()?; + unsafe { ffi::notmuch_query_count_messages(self.ptr, &mut cnt) }.as_result()?; Ok(cnt) } - pub fn search_threads<'q>(self: &'d Self) -> Result<Threads<'q, Self>> { - <Query<'_> as QueryExt>::search_threads(self) + pub fn search_threads<'q>(self: &'d Self) -> Result<Threads<'d, 'q>> { + <Query<'d> as QueryExt>::search_threads(self) } pub fn count_threads(self: &Self) -> Result<u32> { let mut cnt = 0; - unsafe { ffi::notmuch_query_count_threads(self.handle.ptr, &mut cnt) }.as_result()?; + unsafe { ffi::notmuch_query_count_threads(self.ptr, &mut cnt) }.as_result()?; Ok(cnt) } } pub trait QueryExt<'d> { - fn search_threads<'q, Q>(query: Q) -> Result<Threads<'q, Query<'d>>> + fn search_threads<'q, Q>(query: Q) -> Result<Threads<'d, 'q>> where - Q: Into<Supercow<'q, Query<'d>>>, + Q: Into<ScopedSupercow<'q, Query<'d>>>, { let queryref = query.into(); let mut thrds = ptr::null_mut(); - unsafe { ffi::notmuch_query_search_threads(queryref.handle.ptr, &mut thrds) } + unsafe { ffi::notmuch_query_search_threads(queryref.ptr, &mut thrds) } .as_result()?; - Ok(Threads::from_ptr(thrds, Supercow::phantom(queryref))) + Ok(Threads::from_ptr(thrds, ScopedSupercow::phantom(queryref))) } fn search_messages<'q, Q>(query: Q) -> Result<Messages<'q, Query<'d>>> where - Q: Into<Supercow<'q, Query<'d>>>, + Q: Into<ScopedSupercow<'q, Query<'d>>>, { let queryref = query.into(); let mut msgs = ptr::null_mut(); - unsafe { ffi::notmuch_query_search_messages(queryref.handle.ptr, &mut msgs) } + unsafe { ffi::notmuch_query_search_messages(queryref.ptr, &mut msgs) } .as_result()?; - Ok(Messages::from_ptr(msgs, Supercow::phantom(queryref))) + Ok(Messages::from_ptr(msgs, ScopedSupercow::phantom(queryref))) } } diff --git a/src/tags.rs b/src/tags.rs index f400f63..ad8e421 100644 --- a/src/tags.rs +++ b/src/tags.rs @@ -2,39 +2,38 @@ use std::ffi::CStr; use std::iter::Iterator; use std::ops::Drop; -use supercow::Phantomcow; - -use crate::ffi; +use ffi; +use utils::ScopedPhantomcow; pub trait TagsOwner {} #[derive(Debug)] -pub(crate) struct TagsPtr { - pub ptr: *mut ffi::notmuch_tags_t, +pub struct Tags<'o, O> where + O: TagsOwner + 'o, +{ + ptr: *mut ffi::notmuch_tags_t, + marker: ScopedPhantomcow<'o, O>, } -impl Drop for TagsPtr { +impl<'o, O> Drop for Tags<'o, O> +where + O: TagsOwner + 'o, +{ fn drop(&mut self) { unsafe { ffi::notmuch_tags_destroy(self.ptr) }; } } -#[derive(Debug)] -pub struct Tags<'o, Owner: TagsOwner> { - handle: TagsPtr, - marker: Phantomcow<'o, Owner>, -} - impl<'o, O> Tags<'o, O> where O: TagsOwner + 'o, { pub fn from_ptr<P>(ptr: *mut ffi::notmuch_tags_t, owner: P) -> Tags<'o, O> where - P: Into<Phantomcow<'o, O>>, + P: Into<ScopedPhantomcow<'o, O>>, { Tags { - handle: TagsPtr { ptr }, + ptr, marker: owner.into(), } } @@ -47,15 +46,15 @@ where type Item = String; fn next(&mut self) -> Option<Self::Item> { - let valid = unsafe { ffi::notmuch_tags_valid(self.handle.ptr) }; + let valid = unsafe { ffi::notmuch_tags_valid(self.ptr) }; if valid == 0 { return None; } let ctag = unsafe { - let t = ffi::notmuch_tags_get(self.handle.ptr); - ffi::notmuch_tags_move_to_next(self.handle.ptr); + let t = ffi::notmuch_tags_get(self.ptr); + ffi::notmuch_tags_move_to_next(self.ptr); CStr::from_ptr(t) }; diff --git a/src/thread.rs b/src/thread.rs index 3b58a3e..9634a57 100644 --- a/src/thread.rs +++ b/src/thread.rs @@ -1,90 +1,84 @@ use std::ops::Drop; -use supercow::{Phantomcow, Supercow}; -use crate::ffi; -use crate::utils::ToStr; -use crate::Messages; -use crate::MessagesOwner; -use crate::Tags; -use crate::TagsOwner; - -pub trait ThreadOwner {} +use ffi; +use utils::{ToStr, ScopedSupercow, ScopedPhantomcow}; +use Messages; +use MessageOwner; +use Tags; +use TagsOwner; +use Query; #[derive(Debug)] -pub(crate) struct ThreadPtr { - pub ptr: *mut ffi::notmuch_thread_t, +pub struct Thread<'d, 'q> +where + 'd: 'q +{ + pub(crate) ptr: *mut ffi::notmuch_thread_t, + pub(crate) marker: ScopedPhantomcow<'q, Query<'d>>, } -// TODO: The iterator doesn't actually own these, so dropping these will -// generate a segfault when a new iterator is constructed. -// impl Drop for ThreadPtr { -// fn drop(&mut self) { -// unsafe { ffi::notmuch_thread_destroy(self.ptr) }; -// } -// } - -#[derive(Debug)] -pub struct Thread<'o, O> +impl<'d, 'q> Drop for Thread<'d, 'q> where - O: ThreadOwner, + 'd: 'q { - pub(crate) handle: ThreadPtr, - marker: Phantomcow<'o, O>, + fn drop(&mut self) { + unsafe { ffi::notmuch_thread_destroy(self.ptr) }; + } } -impl<'o, O> MessagesOwner for Thread<'o, O> where O: ThreadOwner + 'o {} -impl<'o, O> TagsOwner for Thread<'o, O> where O: ThreadOwner + 'o {} +impl<'d, 'q> MessageOwner for Thread<'d, 'q> where 'd: 'q {} +impl<'d, 'q> TagsOwner for Thread<'d, 'q> where 'd: 'q {} -impl<'o, O> Thread<'o, O> +impl<'d, 'q> Thread<'d, 'q> where - O: ThreadOwner + 'o, + 'd: 'q { - pub fn from_ptr<P>(ptr: *mut ffi::notmuch_thread_t, owner: P) -> Thread<'o, O> + pub fn from_ptr<P>(ptr: *mut ffi::notmuch_thread_t, owner: P) -> Thread<'d, 'q> where - P: Into<Phantomcow<'o, O>>, + P: Into<ScopedPhantomcow<'q, Query<'d>>>, { Thread { - handle: ThreadPtr { ptr }, + ptr, marker: owner.into(), } } pub fn id(self: &Self) -> String { - let tid = unsafe { ffi::notmuch_thread_get_thread_id(self.handle.ptr) }; + let tid = unsafe { ffi::notmuch_thread_get_thread_id(self.ptr) }; tid.to_str().unwrap().to_string() } pub fn total_messages(self: &Self) -> i32 { - unsafe { ffi::notmuch_thread_get_total_messages(self.handle.ptr) } + unsafe { ffi::notmuch_thread_get_total_messages(self.ptr) } } #[cfg(feature = "0.26")] pub fn total_files(self: &Self) -> i32 { - unsafe { ffi::notmuch_thread_get_total_files(self.handle.ptr) } + unsafe { ffi::notmuch_thread_get_total_files(self.ptr) } } pub fn toplevel_messages(self: &Self) -> Messages<'_, Self> { - <Self as ThreadExt<'o, O>>::toplevel_messages(self) + <Self as ThreadExt<'d, 'q>>::toplevel_messages(self) } /// Get a `Messages` iterator for all messages in 'thread' in /// oldest-first order. pub fn messages(self: &Self) -> Messages<'_, Self> { - <Self as ThreadExt<'o, O>>::messages(self) + <Self as ThreadExt<'d, 'q>>::messages(self) } pub fn tags(&self) -> Tags<'_, Self> { - <Self as ThreadExt<'o, O>>::tags(self) + <Self as ThreadExt<'d, 'q>>::tags(self) } pub fn subject(self: &Self) -> String { - let sub = unsafe { ffi::notmuch_thread_get_subject(self.handle.ptr) }; + let sub = unsafe { ffi::notmuch_thread_get_subject(self.ptr) }; sub.to_str().unwrap().to_string() } pub fn authors(self: &Self) -> Vec<String> { - let athrs = unsafe { ffi::notmuch_thread_get_authors(self.handle.ptr) }; + let athrs = unsafe { ffi::notmuch_thread_get_authors(self.ptr) }; athrs .to_str() @@ -96,56 +90,56 @@ where /// Get the date of the oldest message in 'thread' as a time_t value. pub fn oldest_date(self: &Self) -> i64 { - unsafe { ffi::notmuch_thread_get_oldest_date(self.handle.ptr) as i64 } + unsafe { ffi::notmuch_thread_get_oldest_date(self.ptr) as i64 } } /// Get the date of the newest message in 'thread' as a time_t value. pub fn newest_date(self: &Self) -> i64 { - unsafe { ffi::notmuch_thread_get_newest_date(self.handle.ptr) as i64 } + unsafe { ffi::notmuch_thread_get_newest_date(self.ptr) as i64 } } } -pub trait ThreadExt<'o, O> +pub trait ThreadExt<'d, 'q> where - O: ThreadOwner + 'o, + 'd: 'q { - fn tags<'s, S>(thread: S) -> Tags<'s, Thread<'o, O>> + fn tags<'s, S>(thread: S) -> Tags<'s, Thread<'d, 'q>> where - S: Into<Supercow<'s, Thread<'o, O>>>, + S: Into<ScopedSupercow<'s, Thread<'d, 'q>>>, { let threadref = thread.into(); Tags::from_ptr( - unsafe { ffi::notmuch_thread_get_tags(threadref.handle.ptr) }, - Supercow::phantom(threadref), + unsafe { ffi::notmuch_thread_get_tags(threadref.ptr) }, + ScopedSupercow::phantom(threadref), ) } - fn toplevel_messages<'s, S>(thread: S) -> Messages<'s, Thread<'o, O>> + fn toplevel_messages<'s, S>(thread: S) -> Messages<'s, Thread<'d, 'q>> where - S: Into<Supercow<'s, Thread<'o, O>>>, + S: Into<ScopedSupercow<'s, Thread<'d, 'q>>>, { let threadref = thread.into(); Messages::from_ptr( - unsafe { ffi::notmuch_thread_get_toplevel_messages(threadref.handle.ptr) }, - Supercow::phantom(threadref), + unsafe { ffi::notmuch_thread_get_toplevel_messages(threadref.ptr) }, + ScopedSupercow::phantom(threadref), ) } /// Get a `Messages` iterator for all messages in 'thread' in /// oldest-first order. - fn messages<'s, S>(thread: S) -> Messages<'s, Thread<'o, O>> + fn messages<'s, S>(thread: S) -> Messages<'s, Thread<'d, 'q>> where - S: Into<Supercow<'s, Thread<'o, O>>>, + S: Into<ScopedSupercow<'s, Thread<'d, 'q>>>, { let threadref = thread.into(); Messages::from_ptr( - unsafe { ffi::notmuch_thread_get_messages(threadref.handle.ptr) }, - Supercow::phantom(threadref), + unsafe { ffi::notmuch_thread_get_messages(threadref.ptr) }, + ScopedSupercow::phantom(threadref), ) } } -impl<'o, O> ThreadExt<'o, O> for Thread<'o, O> where O: ThreadOwner + 'o {} +impl<'d, 'q> ThreadExt<'d, 'q> for Thread<'d, 'q> where 'd: 'q {} -unsafe impl<'o, O> Send for Thread<'o, O> where O: ThreadOwner + 'o {} -unsafe impl<'o, O> Sync for Thread<'o, O> where O: ThreadOwner + 'o {} +unsafe impl<'d, 'q> Send for Thread<'d, 'q> where 'd: 'q {} +unsafe impl<'d, 'q> Sync for Thread<'d, 'q> where 'd: 'q {} diff --git a/src/threads.rs b/src/threads.rs index 2bd3d24..0359e20 100644 --- a/src/threads.rs +++ b/src/threads.rs @@ -1,92 +1,76 @@ use std::ops::Drop; -use supercow::{Phantomcow, Supercow}; -use crate::utils::{StreamingIterator, StreamingIteratorExt}; +use ffi; +use Thread; +use Query; +use utils::ScopedPhantomcow; -use crate::ffi; -use crate::thread::ThreadOwner; -use crate::Thread; - -pub trait ThreadsOwner {} #[derive(Debug)] -pub(crate) struct ThreadsPtr { - pub ptr: *mut ffi::notmuch_threads_t, +pub struct Threads<'d, 'q> +where + 'd: 'q +{ + ptr: *mut ffi::notmuch_threads_t, + marker: ScopedPhantomcow<'q, Query<'d>>, } -impl Drop for ThreadsPtr { +impl<'d, 'q> Drop for Threads<'d, 'q> +where + 'd: 'q, +{ fn drop(&mut self) { unsafe { ffi::notmuch_threads_destroy(self.ptr) }; } } -#[derive(Debug)] -pub struct Threads<'o, O> +impl<'d, 'q> Threads<'d, 'q> where - O: ThreadsOwner, + 'd: 'q, { - handle: ThreadsPtr, - marker: Phantomcow<'o, O>, -} - -impl<'o, O> ThreadOwner for Threads<'o, O> where O: ThreadsOwner + 'o {} - -impl<'o, O> Threads<'o, O> -where - O: ThreadsOwner + 'o, -{ - pub fn from_ptr<P>(ptr: *mut ffi::notmuch_threads_t, owner: P) -> Threads<'o, O> + pub fn from_ptr<P>(ptr: *mut ffi::notmuch_threads_t, owner: P) -> Threads<'d, 'q> where - P: Into<Phantomcow<'o, O>>, + P: Into<ScopedPhantomcow<'q, Query<'d>>>, { Threads { - handle: ThreadsPtr { ptr }, + ptr, marker: owner.into(), } } } -impl<'s, 'o: 's, O> StreamingIterator<'s, Thread<'s, Self>> for Threads<'o, O> +impl<'d, 'q> Iterator for Threads<'d, 'q> where - O: ThreadsOwner + 'o, + 'd: 'q, { - fn next(&'s mut self) -> Option<Thread<'s, Self>> { - <Self as StreamingIteratorExt<'s, Thread<'s, Self>>>::next(Supercow::borrowed(self)) - } -} + type Item = Thread<'d, 'q>; -pub trait ThreadsExt<'o, O> -where - O: ThreadsOwner + 'o, -{ -} - -impl<'o, O> ThreadsExt<'o, O> for Threads<'o, O> where O: ThreadsOwner + 'o {} - -impl<'s, 'o: 's, O> StreamingIteratorExt<'s, Thread<'s, Self>> for Threads<'o, O> -where - O: ThreadsOwner + 'o, -{ - fn next<S>(threads: S) -> Option<Thread<'s, Self>> - where - S: Into<Supercow<'s, Threads<'o, O>>>, - { - let threadsref = threads.into(); - let valid = unsafe { ffi::notmuch_threads_valid(threadsref.handle.ptr) }; + fn next(&mut self) -> Option<Self::Item> { + let valid = unsafe { ffi::notmuch_threads_valid(self.ptr) }; if valid == 0 { return None; } - let cmsg = unsafe { - let msg = ffi::notmuch_threads_get(threadsref.handle.ptr); - ffi::notmuch_threads_move_to_next(threadsref.handle.ptr); - msg + let cthrd = unsafe { + let thrd = ffi::notmuch_threads_get(self.ptr); + ffi::notmuch_threads_move_to_next(self.ptr); + thrd }; - Some(Thread::from_ptr(cmsg, Supercow::phantom(threadsref))) + Some(Thread::from_ptr(cthrd, ScopedPhantomcow::<'q, Query<'d>>::share(&mut self.marker))) } } -unsafe impl<'o, O> Send for Threads<'o, O> where O: ThreadsOwner + 'o {} -unsafe impl<'o, O> Sync for Threads<'o, O> where O: ThreadsOwner + 'o {} + +pub trait ThreadsExt<'d, 'q> +where + 'd: 'q, +{ +} + +impl<'d, 'q> ThreadsExt<'d, 'q> for Threads<'d, 'q> where 'd: 'q {} + + +unsafe impl<'d, 'q> Send for Threads<'d, 'q> where 'd: 'q {} +unsafe impl<'d, 'q> Sync for Threads<'d, 'q> where 'd: 'q {} diff --git a/src/utils.rs b/src/utils.rs index be5f66c..5bfb5d0 100644 --- a/src/utils.rs +++ b/src/utils.rs @@ -1,7 +1,8 @@ use libc; use std::{ffi, str}; -use supercow::Supercow; +use supercow::{Supercow, DefaultFeatures/*, NonSyncFeatures*/}; +use supercow::ext::{BoxedStorage}; pub trait ToStr { fn to_str<'a>(&self) -> Result<&'a str, str::Utf8Error>; @@ -23,17 +24,20 @@ impl ToString for *const libc::c_char { } } -/// A streaming iterator, as found in https://github.com/emk/rust-streaming -pub trait StreamingIterator<'a, T> { - /// Return either the next item in the sequence, or `None` if all items - /// have been consumed. - fn next(&'a mut self) -> Option<T>; -} +// pub type ScopedNonSyncSupercow<'a, OWNED, BORROWED = OWNED> = +// Supercow<'a, OWNED, BORROWED, +// Box<NonSyncFeatures<'a> + 'a>, +// BoxedStorage>; + +pub type ScopedPhantomcow<'a, OWNED, BORROWED = OWNED, + SHARED = Box<DefaultFeatures<'a> + 'a>, + STORAGE = BoxedStorage> = + Supercow<'a, OWNED, BORROWED, SHARED, STORAGE, ()>; + +pub type ScopedSupercow<'a, OWNED, BORROWED = OWNED, SHARED = Box<DefaultFeatures<'a> + 'a>> = + Supercow<'a, OWNED, BORROWED, SHARED, BoxedStorage>; + + + + -pub trait StreamingIteratorExt<'a, T> { - /// Return either the next item in the sequence, or `None` if all items - /// have been consumed. - fn next<S: Into<Supercow<'a, Self>>>(s: S) -> Option<T> - where - Self: Sized + 'a; -} diff --git a/tests/main.rs b/tests/main.rs index def2e5f..9ad0a36 100644 --- a/tests/main.rs +++ b/tests/main.rs @@ -1,10 +1,9 @@ -use dirs; -use notmuch; +extern crate dirs; +extern crate notmuch; use std::sync::Arc; -use notmuch::StreamingIteratorExt; -use notmuch::{Query, QueryExt, Threads}; +use notmuch::{Query, QueryExt}; fn main() { let mut mail_path = dirs::home_dir().unwrap(); @@ -30,9 +29,9 @@ fn main() { // let mut threads = db.create_query(&"".to_string()).unwrap().search_threads().unwrap(); - let threads = Arc::new(<Query as QueryExt>::search_threads(query).unwrap()); + let mut threads = Arc::new(<Query as QueryExt>::search_threads(query).unwrap()); - while let Some(thread) = <Threads<_> as StreamingIteratorExt<_>>::next(threads.clone()) + for thread in Arc::get_mut(&mut threads).unwrap() { println!("thread {:?} {:?}", thread.subject(), thread.authors()); } |
