use super::*;
use crate::{
notmuch::ffi::{
notmuch_thread_destroy, notmuch_thread_get_messages, notmuch_thread_get_newest_date,
notmuch_thread_get_thread_id, notmuch_thread_get_total_messages, notmuch_thread_t,
notmuch_threads_get, notmuch_threads_move_to_next, notmuch_threads_t,
notmuch_threads_valid,
},
thread::ThreadHash,
};
pub struct Thread<'query> {
pub lib: Arc<NotmuchLibrary>,
pub inner: NonNull<notmuch_thread_t>,
pub _ph: std::marker::PhantomData<*const Query<'query>>,
}
impl<'q> Thread<'q> {
#[inline]
pub fn id(&self) -> ThreadHash {
let thread_id = unsafe {
call!(self.lib, notmuch_thread_get_thread_id)(self.inner.as_ptr())
};
let c_str = unsafe { CStr::from_ptr(thread_id) };
ThreadHash::from(c_str.to_bytes())
}
#[inline]
pub fn date(&self) -> crate::UnixTimestamp {
(unsafe {
call!(self.lib, notmuch_thread_get_newest_date)(self.inner.as_ptr())
}) as u64
}
#[inline]
pub fn len(&self) -> usize {
(unsafe {
call!(self.lib, notmuch_thread_get_total_messages)(self.inner.as_ptr())
}) as usize
}
#[inline]
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn iter(&'q self) -> MessageIterator<'q> {
let messages = NonNull::new(unsafe {
call!(self.lib, notmuch_thread_get_messages)(self.inner.as_ptr())
});
MessageIterator {
lib: self.lib.clone(),
messages,
is_from_thread: true,
_ph: std::marker::PhantomData,
}
}
}
impl<'q> IntoIterator for &'q Thread<'q> {
type IntoIter = MessageIterator<'q>;
type Item = Message<'q>;
fn into_iter(self) -> Self::IntoIter {
self.iter()
}
}
impl Drop for Thread<'_> {
fn drop(&mut self) {
unsafe {
call!(self.lib, notmuch_thread_destroy)(self.inner.as_ptr())
}
}
}
pub struct ThreadsIterator<'query> {
pub lib: Arc<NotmuchLibrary>,
pub inner: Option<NonNull<notmuch_threads_t>>,
pub _ph: std::marker::PhantomData<*const Query<'query>>,
}
impl<'q> Iterator for ThreadsIterator<'q> {
type Item = Thread<'q>;
fn next(&mut self) -> Option<Self::Item> {
let inner = self.inner?;
if unsafe { call!(self.lib, notmuch_threads_valid)(inner.as_ptr()) } == 1 {
let Some(thread_inner) = NonNull::new(unsafe {
call!(self.lib, notmuch_threads_get)(inner.as_ptr())
}) else {
self.inner = None;
return None;
};
unsafe {
call!(self.lib, notmuch_threads_move_to_next)(inner.as_ptr());
}
Some(Thread {
lib: self.lib.clone(),
inner: thread_inner,
_ph: std::marker::PhantomData,
})
} else {
self.inner = None;
None
}
}
}