From 00188891eb9d51abd8dff1d0cebe270ca2acbeeb Mon Sep 17 00:00:00 2001 From: "Chris West (Faux)" Date: Thu, 13 Jul 2017 18:28:20 +0100 Subject: [PATCH] fixup borrows on nasty iterators --- src/citer.rs | 29 +++++++++++++++++++++++++++-- src/lib.rs | 27 ++++++++++----------------- src/raw.rs | 1 + 3 files changed, 38 insertions(+), 19 deletions(-) diff --git a/src/citer.rs b/src/citer.rs index 3cee8c0..e701f10 100644 --- a/src/citer.rs +++ b/src/citer.rs @@ -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>, + 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 CIterator where R: RawIterator, { - pub fn next(&mut self) -> Option { + pub fn next<'i>(&mut self) -> Option> { 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(), + }) } } diff --git a/src/lib.rs b/src/lib.rs index e78a60d..ca3996a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -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()); - } } diff --git a/src/raw.rs b/src/raw.rs index 000d3de..a278e4b 100644 --- a/src/raw.rs +++ b/src/raw.rs @@ -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?