I have collections dumped on disk. When requested, these collections should be retrieved (no problem) and an iterator
should be build for it that returns references to the retrieved values.
After the iterator
is dropped, I do not need the collection anymore. I want it to be dropped, too.
What I have tried so far:
The
Iterator
owns the collection. This made the most sense for me, but it is not possible; I am not quite sure why. Some say theIterator
traits' method signature fornext
is the problem. (example)Reference Counting: The
Retriever
returns aRc<Vec<usize>>
. I ran into the same problems as in the owning iterator. (example)Letting the retriever own the collection and handing out a reference to it. I tried to implement the retriever with interior mutability (
RefCell<HashMap>
), but I cannot return references into theHashMap
with long enough lifetimes.
I see two basic possibilities with this.
The retriever transfers ownership. Then the
Iterator
would need to own the data. Something in the lines of:use std::slice::Iter; fn retrieve(id: usize) -> Vec<usize> { //Create Data out of the blue (or disk, or memory, or network. I dont care) //Move the data out. Transfer ownership let data = vec![0, 1, 2, 3]; data } fn consume_iterator<'a, TIterator: Iterator<Item=&'a usize>>(iterator: TIterator) { for i in iterator { println!("{}", i); } } fn handler<'a>(id: usize) -> Iter<'a, usize> { //handle_request now owns the vector. //I now want to build an owning iterator.. //This does of course not compile as vector will be dropped at the end of this method retrieve(id).iter() } fn main() { consume_iterator(handler(0)) }
The retriever owns the collection. But then two new problems arise:
- How can I drop the data when the iterator is out of range?
- How do I tell the borrow-checker that I will own the collection long enough?
use std::cell::{Ref, RefCell}; struct Retriever { //Own the data. But I want it to be dropped as soon as the references to it go out of scope. data: RefCell<Vec<usize>> } impl Retriever{ fn retrieve<'a>(&'a self, id: usize) -> Ref<'a, Vec<usize>> { //Create Data out of the blue (or disk, or memory, or network. I dont care) //Now data can be stored internally and a referece to it can be supplied. let mut data = self.data.borrow_mut(); *data = vec![0, 1, 2, 3]; self.data.borrow() } } fn consume_iterator<'a, TIterator: Iterator<Item=&'a usize>>(iterator: TIterator) { for i in iterator { println!("{}", i); } } fn handler<'a>(ret: &'a Retriever, id: usize) -> IterWrapper<'a> { //andle_request now has a reference to the collection //So just call iter()? Nope. Lifetime issues. ret.retrieve(id).iter() } fn main() { let retriever = Retriever{data: RefCell::new(Vec::new())}; consume_iterator(handler(&retriever, 0)) }
I feel a bit lost here and am overlooking something obvious.