Iterators and iterables

(Supported by js, dart, kotlin, queried with supports = iterators and supports = iterables)

Some languages support a first-class notion of "iterator", a type that can be looped over in a for loop, stepping through its values typically until they are exhausted.

Furthermore, some languages support a first-class notion of an "iterable": types like collections that can be asked to produce an iterator over their values which can be stepped through. Typically for loops will also accept iterables, and looping through an iterable involves producing and then looping through the associated iterator.

The distinction here is: iterators are mutated by iteration and often one-time use, iterables are not mutated and can be iterated over multiple times. Put in Rust terms, Iterator types are iterators, and IntoIterator types are iterables.

Diplomat supports marking types as such by using iterator and iterable on a specific method of the type.

Marking a type as an iterator

To mark a type as an iterator, it should have a signature of fn next(&mut self) -> Option<...>. The method name may be anything, and it may take self by immutable reference instead, if needed (this is useful for situations where aliasing safety is needed, see #225 ).

#![allow(unused)]
fn main() {
#[diplomat::bridge]
mod ffi {
    #[diplomat::opaque]
    struct MyIterator<'a>(std::slice::Iter<'a, u8>);

    impl<'a> MyIterator<'a> {
        #[diplomat::attr(auto, iterator)]
        pub fn next(&mut self) -> Option<u8> {
            self.0.next().copied()
        }
    }
}
}

Marking a type as an iterable

Marking a type as an iterable requires annotating it with iterable, and it just needs to be a method that takes self and returns a type that has a method marked as iterator.

#![allow(unused)]
fn main() {
#[diplomat::bridge]
mod ffi {
    #[diplomat::opaque]
    struct MyVector(Vec<u8>);

    impl MyVector {
        #[diplomat::attr(auto, iterable)]
        pub fn iter<'a> (&'a self) -> Box<MyIterator<'a>> {
            Box::new(MyIterator(self.0.iter()))
        }
    }
}
}