use super::{header::Header, tag::DBIndexTag};
use std::{os::raw::c_void, ptr};
use streaming_iterator::StreamingIterator;
pub(crate) struct MatchIterator {
ptr: *mut librpm_sys::rpmdbMatchIterator_s,
next_item: Option<Header>,
finished: bool,
}
impl MatchIterator {
pub(crate) fn new(
ts: *mut librpm_sys::rpmts_s,
tag: DBIndexTag,
key_opt: Option<&str>,
) -> Self {
let next_item = None;
let finished = false;
if let Some(key) = key_opt
&& !key.is_empty()
{
let ptr = unsafe {
librpm_sys::rpmtsInitIterator(
ts,
tag as librpm_sys::rpm_tag_t,
key.as_ptr() as *const c_void,
key.len(),
)
};
return Self {
ptr,
next_item,
finished,
};
}
let ptr = unsafe {
librpm_sys::rpmtsInitIterator(ts, tag as librpm_sys::rpm_tag_t, ptr::null(), 0)
};
Self {
ptr,
next_item,
finished,
}
}
}
impl StreamingIterator for MatchIterator {
type Item = Header;
fn advance(&mut self) {
if self.finished {
return;
}
let header_ptr = unsafe { librpm_sys::rpmdbNextIterator(self.ptr) };
if header_ptr.is_null() {
self.finished = true;
self.next_item = None;
} else {
self.next_item = Some(unsafe { Header::from_ptr(header_ptr) })
}
}
fn get(&self) -> Option<&Header> {
self.next_item.as_ref()
}
}
impl Drop for MatchIterator {
fn drop(&mut self) {
unsafe {
librpm_sys::rpmdbFreeIterator(self.ptr);
}
}
}