# Async Iter This library offers an asynchronous version of the rust's `Iterator` trait and utilities. ## Quick Start ### Add to Dependencies Add async-iter to your dependencies: ```bash cargo add asynciter ``` ### Entrance to Utilities Then, import the basic traits: ```rust use asynciter::{ // This offers standard api, just like the `std::iter::Iterator` AsyncIterator, // use `.aiter()` to convert a synchronous iterator // into an asynchronous one ToAsyncIterator, // use `.into_aiter()` to convert a synchronous iterable object // into an asynchronous iterator IntoAsyncIterator, } ``` ### Api Call Stack All api names and restrictions are the same as the std ones. You just need to change your `.iter()` or `.into_iter()` to `.aiter()` or `.into_aiter()`: ```rust assert_eq!( ["Hello%", "World%", "!"] .into_aiter() .map(|s| s.to_ascii_lowercase()) .intersperse(" ".into()) .flat_map(|s| s.chars().filter(|s| s != &'%').collect::>()) .collect::() .await, "hello world !" ); ``` ### Asynchronous Alternative If you want to use asynchronous functions inside your iterators, api prefixed with `a` will accept a function returning a `Future` while works the same as synchronous ones: ```rust async fn do_async(val: i32) -> String { format!("Async! {val}") } (0..=10) .aiter() // `amap` accepts `FnMut(Item) -> Future` .amap(do_async) // `afor_each` accepts `FnMut(Item) -> Future` .afor_each(|s| async move { println!("{s}"); }) .await; ``` ### Awaited Asynchronous Iterator If you have an iterator which yields `Future`s, use `.awaited()` to change them into an `AsyncIterator`: ```rust // impl Iterator> let sync_it = (0..10).map(|s| async move { s + 1 }); // impl AsyncIterator let async_it = sync_it.aiter().awaited(); ``` ## Internal Implementation All internal implementations can be found in the `asynciter::iterimpl` module, and are exported publicly, but direct usage is not recommended. ## Notes For those api which accept `FnXXX(&Self::Item) -> Future`, there's another extra restriction. Since the `Future` will be used later than the function call, the reference might outlive the function call's lifetime, leading to compiler failures. To keep code safe, the reference must be processed and dropped outside of the `Future`. For example, the following code will not pass the compiler check: ```rust (0..10) .aiter() .afilter( |s| // Here we accept the reference async move { *s < 5 // And we use it here. // The reference will live longer than the function, // which is not safe. } ) ``` Instead, we must use the following solution: ```rust (0..10) .map(|s| s.to_string()) .aiter() .afilter(|s| { let s = s.clone(); // Here we save the reference // by cloning the value async move { // do something false } }) .for_each(|_| {}).await; ``` ## License This project is licensed under the [MIT License](./LICENSE-MIT) or [Apache V2.0 License](./LICENSE-APACHE).