aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml1
-rw-r--r--src/database.rs73
-rw-r--r--src/directory.rs35
-rw-r--r--src/error.rs12
-rw-r--r--src/ffi.rs6
-rw-r--r--src/filenames.rs43
-rw-r--r--src/lib.rs27
-rw-r--r--src/message.rs110
-rw-r--r--src/messages.rs140
-rw-r--r--src/query.rs79
-rw-r--r--src/tags.rs33
-rw-r--r--src/thread.rs110
-rw-r--r--src/threads.rs98
-rw-r--r--src/utils.rs32
-rw-r--r--tests/main.rs11
15 files changed, 374 insertions, 436 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 1dc00d0..d04896d 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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,
}
}
diff --git a/src/ffi.rs b/src/ffi.rs
index 1434ee0..3874ae5 100644
--- a/src/ffi.rs
+++ b/src/ffi.rs
@@ -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)
};
diff --git a/src/lib.rs b/src/lib.rs
index 005f142..ef8cc33 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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());
}