fixup borrows on nasty iterators

This commit is contained in:
Chris West (Faux) 2017-07-13 18:28:20 +01:00
parent d4d85c2485
commit 00188891eb
3 changed files with 38 additions and 19 deletions

View File

@ -1,3 +1,6 @@
use std::ops::Deref;
use std::marker::PhantomData;
pub trait RawIterator {
type View;
@ -26,11 +29,30 @@ where
}
}
pub struct Borrowed<'i, R>
where
R: 'i + RawIterator,
{
it: PhantomData<&'i CIterator<R>>,
val: R::View,
}
impl<'i, R> Deref for Borrowed<'i, R>
where
R: RawIterator,
{
type Target = R::View;
fn deref(&self) -> &R::View {
&self.val
}
}
impl<R> CIterator<R>
where
R: RawIterator,
{
pub fn next(&mut self) -> Option<R::View> {
pub fn next<'i>(&mut self) -> Option<Borrowed<R>> {
if self.raw.is_end() {
return None;
}
@ -45,7 +67,10 @@ where
if self.raw.is_end() {
None
} else {
Some(self.raw.as_view())
Some(Borrowed {
it: PhantomData,
val: self.raw.as_view(),
})
}
}

View File

@ -13,8 +13,7 @@
//! a bit more like Rust `Iterator`s, but is crippled by the insanity.
//!
//! Methods which "find" something will reposition one of these "iterators" at the right place
//! in an existing stream of items. Note that currently you don't technically need to call
//! `next()` before observing the result of a `find..()`, but hopefully this will be fixed.
//! in an existing stream of items.
//!
//! I recommend using `.map()` to turn an "iterator" into a Rust type as soon as possible.
//! The returned map-like thing *is* a Rust `Iterator`, so you can do normal operations on it.
@ -25,7 +24,7 @@
//!
//! ```rust,no_run
//! extern crate apt_pkg_native;
//! let cache = apt_pkg_native::Cache::get_singleton();
//! let mut cache = apt_pkg_native::Cache::get_singleton();
//! let total_packages = cache.iter().map(|_| ()).count();
//! ```
//!
@ -63,20 +62,14 @@ mod tests {
panic!("not found!");
}
assert!(cache.find_by_name(
"this-package-doesnt-exist-and-if-someone-makes-it-ill-be-really-angry",
).next().is_none());
assert!(
cache
.find_by_name(
"this-package-doesnt-exist-and-if-someone-makes-it-ill-be-really-angry",
)
.next()
.is_none()
);
}
// TODO: this should not even remotely compile
#[test]
fn demonstrate_insane_iterator_behaviour() {
let mut cache = Cache::get_singleton();
let mut it = cache.iter();
let first = it.next().unwrap();
let second = it.next().unwrap();
assert_eq!(first.arch(), second.arch());
assert_eq!(first.name(), second.name());
}
}

View File

@ -10,6 +10,7 @@ pub type PCache = *mut c_void;
pub type PPkgIterator = *mut c_void;
pub type PVerIterator = *mut c_void;
#[link(name = "apt-pkg-c", kind = "static")]
#[link(name = "apt-pkg")]
extern "C" {
/// Must be called exactly once, before anything else?