I am trying to create a clean Rust API over FFI bindings generated by bindgen. The complete code below is available on the Playground.
A design goal is to use the FFI structs for storing data and avoid allocation additional memory and copying, maintaining duplicate structures, etc.
This is a simplified facsimile of the FFI generated by bindgen:
struct ffi_item { /* elided for brevity */}
struct ffi_bucket {
items: [ffi_item], /* simplified */
}
impl ffi_bucket {
/// orignal ffi method returns a slice from a ptr and the number of
/// items. Lifetimes are implicit and the same as in this method.
fn items(&self) -> &[ffi_item] {
&self.items
}
}
The iterator is what is giving me trouble:
impl<'s> MyBucket<'s> {
fn items(&self) -> ItemIterator<'s> {
ItemIterator {
items: unsafe { &*self.bucket }.items(),
item: None,
index: 0,
}
}
}
While the code compiles, I cannot get the implementation of the Iterator right:
struct ItemIterator<'s> {
items: &'s [ffi_item],
item: Option<MyItem<'s>>,
index: usize,
}
impl<'s> Iterator for ItemIterator<'s> {
type Item = &'s MyItem<'s>;
fn next(&mut self) -> Option<Self::Item> {
if self.index < self.items.len() {
self.item = Some(MyItem { item: &self.items[self.index] });
self.index += 1;
self.item.as_ref()
} else {
None
}
}
}
It fails with the following error:
error: lifetime may not live long enough
--> src/lib.rs:44:13
|
37 | impl<'s> Iterator for ItemIterator<'s> {
| -- lifetime `'s` defined here
...
40 | fn next(&mut self) -> Option<Self::Item> {
| - let's call the lifetime of this reference `'1`
...
44 | self.item.as_ref()
| ^^^^^^^^^^^^^^^^^^ method was supposed to return data with lifetime `'s` but it is returning data with lifetime `'1`
Given that I want to provide a safe and simplified wrapper API around the FFI generated by bindgen, how do I best implement an iterator over the ffi_item in the ffi_bucket?