Wrapper for items in iterator over FFI slice generated by bindgen

⚓ rust    📅 2025-05-06    👤 surdeus    👁️ 4      

surdeus

Warning

This post was published 56 days ago. The information described in this article may have changed.

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?

2 posts - 2 participants

Read full topic

🏷️ rust_feed