diff --git a/CHANGELOG.md b/CHANGELOG.md index 8738244..658ed9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,6 @@ +# version 0.4.0 +* follow [rename Generator to Coroutine](https://github.com/rust-lang/rust/pull/116958) and fix #10 + # version 0.3 * made the crate no_std compatible (#5) * added struct GenIterReturn and macro gen_iter_return! to iterate over a generator and get the return value (#6) diff --git a/Cargo.toml b/Cargo.toml index c0070a7..3c5bb56 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,9 +1,10 @@ [package] name = "gen-iter" -version = "0.2.1" +version = "0.4.0" +edition = "2021" authors = ["tinaun "] -keywords = ["generator", "iterator"] -description = "temporary util for creating iterators using generators" +keywords = ["coroutine", "generator", "iterator"] +description = "temporary util for creating iterators using coroutines" documentation = "https://docs.rs/gen-iter" repository = "https://github.com/tinaun/gen-iter" diff --git a/README.md b/README.md index ddf65cf..d8059c7 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -# gen_iter - iterators using generators. +# gen_iter - iterators using coroutines/generators. see [the docs](https://docs.rs/gen-iter) for examples and usage. diff --git a/src/gen_iter.rs b/src/gen_iter.rs index 37fa916..dd95e3c 100644 --- a/src/gen_iter.rs +++ b/src/gen_iter.rs @@ -1,33 +1,33 @@ -use core::ops::{Generator, GeneratorState}; use core::iter::Iterator; use core::marker::Unpin; +use core::ops::{Coroutine, CoroutineState}; use core::pin::Pin; -/// an iterator that holds an internal generator representing +/// an iterator that holds an internal coroutine representing /// the iteration state #[derive(Copy, Clone, Debug)] pub struct GenIter(pub T) where - T: Generator + Unpin; + T: Coroutine + Unpin; impl Iterator for GenIter where - T: Generator + Unpin, + T: Coroutine + Unpin, { type Item = T::Yield; #[inline] fn next(&mut self) -> Option { match Pin::new(&mut self.0).resume(()) { - GeneratorState::Yielded(n) => Some(n), - GeneratorState::Complete(()) => None, + CoroutineState::Yielded(n) => Some(n), + CoroutineState::Complete(()) => None, } } } impl From for GenIter where - G: Generator + Unpin, + G: Coroutine + Unpin, { #[inline] fn from(gen: G) -> Self { @@ -36,10 +36,10 @@ where } -/// macro to simplify iterator - via - generator construction +/// macro to simplify iterator - via - coroutine construction /// /// ``` -/// #![feature(generators)] +/// #![feature(coroutines)] /// /// use gen_iter::gen_iter; /// @@ -56,10 +56,10 @@ where #[macro_export] macro_rules! gen_iter { ($block: block) => { - $crate::GenIter(|| $block) + $crate::GenIter(#[coroutine] || $block) }; (move $block: block) => { - $crate::GenIter(move || $block) + $crate::GenIter(#[coroutine] move || $block) } } @@ -82,10 +82,13 @@ mod tests { #[test] fn into_gen_iter() { - let mut g: GenIter<_> = (|| { - yield 1; - yield 2; - }).into(); + let mut g: GenIter<_> = ( + #[coroutine] + || { + yield 1; + yield 2; + } + ).into(); assert_eq!(g.next(), Some(1)); assert_eq!(g.next(), Some(2)); diff --git a/src/gen_iter_return.rs b/src/gen_iter_return.rs index 9ad2bc3..349fc1e 100644 --- a/src/gen_iter_return.rs +++ b/src/gen_iter_return.rs @@ -1,19 +1,19 @@ -use core::ops::{Generator, GeneratorState}; -use core::iter::{Iterator, FusedIterator}; +use core::iter::{FusedIterator, Iterator}; use core::marker::Unpin; +use core::ops::{Coroutine, CoroutineState}; use core::pin::Pin; -/// `GenIterReturn` holds a generator `G` or the return value of `G`, +/// `GenIterReturn` holds a coroutine `G` or the return value of `G`, /// `&mut GenIterReturn` acts as an iterator. -/// +/// /// Differences with `GenIter`: -/// 1. able to get return value of a generator -/// 2. safe to call `next()` after generator is done without panic +/// 1. able to get return value of a coroutine +/// 2. safe to call `next()` after coroutine is done without panic /// 3. maybe less efficient than `GenIter` #[derive(Copy, Clone, Debug)] -pub struct GenIterReturn(Result); +pub struct GenIterReturn(Result); -impl GenIterReturn { +impl GenIterReturn { #[inline] pub fn new(g: G) -> Self { GenIterReturn(Err(g)) @@ -37,13 +37,13 @@ impl GenIterReturn { /// in which return value cannot be got. /// ```compile_fail /// // !!INVALID CODE!! -/// # #![feature(generators)] +/// # #![feature(coroutines)] /// # use gen_iter::gen_iter_return; /// let mut g = gen_iter_return!({ yield 1; return "done"; }); /// for v in g {} // invalid, because `GenIterReturn` is not `Iterator` /// let ret = g.return_or_self(); // g is dropped after for loop /// ``` -impl Iterator for &mut GenIterReturn { +impl Iterator for &mut GenIterReturn { type Item = G::Yield; #[inline] @@ -51,29 +51,29 @@ impl Iterator for &mut GenIterReturn { match self.0 { Ok(_) => None, Err(ref mut g) => match Pin::new(g).resume(()) { - GeneratorState::Yielded(y) => Some(y), - GeneratorState::Complete(r) => { + CoroutineState::Yielded(y) => Some(y), + CoroutineState::Complete(r) => { self.0 = Ok(r); None }, - } + }, } } } /// `GenIterReturn` satisfies the trait `FusedIterator` -impl FusedIterator for &mut GenIterReturn {} +impl FusedIterator for &mut GenIterReturn {} -impl From for GenIterReturn { +impl From for GenIterReturn { #[inline] fn from(g: G) -> Self { GenIterReturn::new(g) } } -/// macro to simplify iterator - via - generator with return value construction +/// macro to simplify iterator - via - coroutine with return value construction /// ``` -/// #![feature(generators)] +/// #![feature(coroutines)] /// /// use gen_iter::gen_iter_return; /// @@ -84,18 +84,18 @@ impl From for GenIterReturn { /// }); /// /// assert_eq!((&mut g).collect::>(), [1, 2]); // use `&mut g` as an iterator -/// assert_eq!(g.is_done(), true); // check whether generator is done +/// assert_eq!(g.is_done(), true); // check whether the coroutine is done /// assert_eq!((&mut g).next(), None); // safe to call `next()` after done -/// assert_eq!(g.return_or_self().ok(), Some("done")); // get return value of generator +/// assert_eq!(g.return_or_self().ok(), Some("done")); // get return value of the coroutine /// ``` #[macro_export] macro_rules! gen_iter_return { ($block: block) => { - $crate::GenIterReturn::new(|| $block) + $crate::GenIterReturn::new(#[coroutine] || $block) }; (move $block: block) => { - $crate::GenIterReturn::new(move || $block) - } + $crate::GenIterReturn::new(#[coroutine] move || $block) + }; } #[cfg(test)] @@ -106,17 +106,20 @@ mod tests { /// and show that it won't panic when call `next()` even exhausted. #[test] fn it_works() { - let mut g = GenIterReturn::new(|| { - yield 1; - return "done"; - }); + let mut g = GenIterReturn::new( + #[coroutine] + || { + yield 1; + return "done"; + }, + ); assert_eq!((&mut g).next(), Some(1)); assert_eq!(g.is_done(), false); g = match g.return_or_self() { - Ok(_) => panic!("generator is done but should not"), - Err(g) => g + Ok(_) => panic!("coroutine is done but should not"), + Err(g) => g, }; assert_eq!((&mut g).next(), None); @@ -128,11 +131,14 @@ mod tests { } #[test] - fn from_generator() { - let mut g = GenIterReturn::from(|| { - yield 1; - return "done"; - }); + fn from_coroutine() { + let mut g = GenIterReturn::from( + #[coroutine] + || { + yield 1; + return "done"; + }, + ); assert_eq!((&mut g).next(), Some(1)); assert_eq!((&mut g).next(), None); diff --git a/src/lib.rs b/src/lib.rs index ee9c5a4..0344f48 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,13 +1,18 @@ -//! # gen_iter - create generators to use as iterators +//! # gen_iter - create coroutines to use as iterators +//! +//! **Important: [rename Generator to Coroutine](https://github.com/rust-lang/rust/pull/116958)** //! -//! ## [`GenIter`] and [`gen_iter!`] -//! [`GenIter`] converts a [`Generator<(), Return=()>`](core::ops::Generator) into an iterator over the -//! yielded type of the generator. The return type of the generator needs to be `()`. +//! ## Prerequirements +//! Nightly rust toolchain of edition 2021 after 2023-10-21. //! +//! ## [`GenIter`] and [`gen_iter!`] +//! [`GenIter`] converts a [`Coroutine<(), Return=()>`](core::ops::Coroutine) into an iterator over the +//! yielded type of the coroutine. The return type of the coroutine needs to be `()`. +//! //! [`gen_iter!`] helps to create a [`GenIter`] //! //! ``` -//! #![feature(generators)] +//! #![feature(coroutines)] //! //! use gen_iter::gen_iter; //! @@ -32,14 +37,14 @@ //! ``` //! //! ## [`GenIterReturn`] and [`gen_iter_return!`] -//! [`GenIterReturn`] can be converted from a [`Generator<()>`](core::ops::Generator), +//! [`GenIterReturn`] can be converted from a [`Coroutine<()>`](core::ops::Coroutine), //! `&mut GenIterReturn` can be used as iterator. -//! The return value of the generator can be got after the iterator is exhausted. +//! The return value of the coroutine can be got after the iterator is exhausted. //! //! [`gen_iter_return!`] helps to create a [`GenIterReturn`]. //! //! ``` -//! #![feature(generators)] +//! #![feature(coroutines)] //! //! use gen_iter::gen_iter_return; //! @@ -52,12 +57,13 @@ //! for y in &mut g { //! println!("yield {}", y); //! } -//! println!("generator is_done={}", g.is_done()); // true -//! println!("generator returns {}", g.return_or_self().ok().unwrap()); // "done" +//! println!("coroutine is_done={}", g.is_done()); // true +//! println!("coroutine returns {}", g.return_or_self().ok().unwrap()); // "done" //! ``` #![no_std] -#![feature(generators, generator_trait)] +#![feature(coroutines, coroutine_trait)] +#![feature(stmt_expr_attributes)] mod gen_iter; pub use gen_iter::*;