More natural interface; no idea why it needs that annotation
This commit is contained in:
parent
e3f5bd3633
commit
e90ee73dc8
@ -29,7 +29,8 @@ extern "C" {
|
||||
PPkgIterator *pkg_cache_pkg_iter(PCache *cache);
|
||||
void pkg_iter_release(PPkgIterator *iterator);
|
||||
|
||||
bool pkg_iter_next(PPkgIterator *iterator);
|
||||
void pkg_iter_next(PPkgIterator *iterator);
|
||||
bool pkg_iter_end(PPkgIterator *iterator);
|
||||
|
||||
const char *pkg_iter_name(PPkgIterator *iterator);
|
||||
|
||||
@ -68,9 +69,12 @@ void pkg_iter_release(PPkgIterator *wrapper) {
|
||||
delete wrapper;
|
||||
}
|
||||
|
||||
bool pkg_iter_next(PPkgIterator *wrapper) {
|
||||
void pkg_iter_next(PPkgIterator *wrapper) {
|
||||
++wrapper->iterator;
|
||||
return wrapper->cache->PkgEnd() != wrapper->iterator;
|
||||
}
|
||||
|
||||
bool pkg_iter_end(PPkgIterator *wrapper) {
|
||||
return wrapper->cache->PkgEnd() == wrapper->iterator;
|
||||
}
|
||||
|
||||
const char *pkg_iter_name(PPkgIterator *wrapper) {
|
||||
|
12
src/lib.rs
12
src/lib.rs
@ -1,6 +1,7 @@
|
||||
extern crate libc;
|
||||
|
||||
pub mod raw;
|
||||
pub mod sane;
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
@ -19,7 +20,8 @@ mod tests {
|
||||
let pretty = raw::pkg_iter_pretty(cache, iter);
|
||||
println!("{}", CStr::from_ptr(pretty).to_str().expect("package names are always valid utf-8, in that they're always valid low ascii"));
|
||||
libc::free(pretty as *mut libc::c_void);
|
||||
if !raw::pkg_iter_next(iter) {
|
||||
raw::pkg_iter_next(iter);
|
||||
if raw::pkg_iter_end(iter) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -27,4 +29,12 @@ mod tests {
|
||||
raw::pkg_cache_release(cache);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn list_all() {
|
||||
let mut cache = sane::Cache::new();
|
||||
for name in cache.iter().map(|item: &sane::PkgIterator| item.pretty_print()) {
|
||||
println!("{}", name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -6,8 +6,8 @@
|
||||
use libc::c_void;
|
||||
use libc::c_char;
|
||||
|
||||
type PCache = *mut c_void;
|
||||
type PPkgIterator = *mut c_void;
|
||||
pub type PCache = *mut c_void;
|
||||
pub type PPkgIterator = *mut c_void;
|
||||
|
||||
#[link(name = "apt-c")]
|
||||
#[link(name = "apt-pkg")]
|
||||
@ -19,7 +19,8 @@ extern {
|
||||
pub fn pkg_cache_pkg_iter(cache: PCache) -> PPkgIterator;
|
||||
pub fn pkg_iter_release(iterator: PPkgIterator);
|
||||
|
||||
pub fn pkg_iter_next(iterator: PPkgIterator) -> bool;
|
||||
pub fn pkg_iter_next(iterator: PPkgIterator);
|
||||
pub fn pkg_iter_end(iterator: PPkgIterator) -> bool;
|
||||
|
||||
pub fn pkg_iter_name(iterator: PPkgIterator) -> *const c_char;
|
||||
pub fn pkg_iter_pretty(cache: PCache, iterator: PPkgIterator) -> *mut c_char;
|
||||
|
129
src/sane.rs
Normal file
129
src/sane.rs
Normal file
@ -0,0 +1,129 @@
|
||||
use std::ffi;
|
||||
|
||||
use libc;
|
||||
use raw;
|
||||
|
||||
// Probably not cloneable / copyable.
|
||||
#[derive(Debug)]
|
||||
pub struct Cache {
|
||||
ptr: raw::PCache
|
||||
}
|
||||
|
||||
impl Drop for Cache {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
raw::pkg_cache_release(self.ptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Cache {
|
||||
pub fn new() -> Cache {
|
||||
Cache {
|
||||
ptr: unsafe { raw::pkg_cache_create() }
|
||||
}
|
||||
}
|
||||
|
||||
pub fn iter(&mut self) -> PkgIterator {
|
||||
unsafe {
|
||||
PkgIterator {
|
||||
cache: self,
|
||||
ptr: raw::pkg_cache_pkg_iter(self.ptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct PkgIterator<'c> {
|
||||
cache: &'c Cache,
|
||||
ptr: raw::PPkgIterator
|
||||
}
|
||||
|
||||
impl<'c> Drop for PkgIterator<'c> {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
raw::pkg_iter_release(self.ptr)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Iterator-like interface.
|
||||
/// Can't implement Iterator due to the mutation / lifetime constraints?
|
||||
impl<'c> PkgIterator<'c> {
|
||||
pub fn next<'i>(&'i mut self) -> Option<&'i Self> {
|
||||
unsafe {
|
||||
// we were at the end last time, leave us alone!
|
||||
if raw::pkg_iter_end(self.ptr) {
|
||||
return None;
|
||||
}
|
||||
|
||||
raw::pkg_iter_next(self.ptr);
|
||||
|
||||
// we don't want to observe the end marker
|
||||
if raw::pkg_iter_end(self.ptr) {
|
||||
None
|
||||
} else {
|
||||
Some(self)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn count(mut self) -> usize {
|
||||
let mut count = 0;
|
||||
loop {
|
||||
if self.next().is_none() {
|
||||
break;
|
||||
}
|
||||
|
||||
count += 1;
|
||||
}
|
||||
|
||||
count
|
||||
}
|
||||
|
||||
pub fn map<F>(self, f: F) -> PkgMap<'c, F> {
|
||||
PkgMap {
|
||||
it: self,
|
||||
f,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Actual accessors
|
||||
impl<'c> PkgIterator<'c> {
|
||||
pub fn name(&self) -> String {
|
||||
unsafe {
|
||||
ffi::CStr::from_ptr(raw::pkg_iter_name(self.ptr))
|
||||
}.to_str().expect("package names are always low-ascii").to_string()
|
||||
}
|
||||
|
||||
pub fn pretty_print(&self) -> String {
|
||||
unsafe {
|
||||
let ptr = raw::pkg_iter_pretty(self.cache.ptr, self.ptr);
|
||||
let result = ffi::CStr::from_ptr(ptr)
|
||||
.to_str()
|
||||
.expect("package names are always low-ascii")
|
||||
.to_string();
|
||||
libc::free(ptr as *mut libc::c_void);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[must_use = "iterator adaptors are lazy and do nothing unless consumed"]
|
||||
pub struct PkgMap<'c, F> {
|
||||
it: PkgIterator<'c>,
|
||||
f: F,
|
||||
}
|
||||
|
||||
impl<'c, B, F> Iterator for PkgMap<'c, F>
|
||||
where F: FnMut(&PkgIterator) -> B {
|
||||
|
||||
type Item = B;
|
||||
|
||||
fn next(&mut self) -> Option<Self::Item> {
|
||||
self.it.next().map(&mut self.f)
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user