[][src]Struct next_gen::GeneratorFn

pub struct GeneratorFn<Item, F: Future> { /* fields omitted */ }

An instance of a #[generator]-tagged function.

These are created in a two-step fashion:

  1. First, an empty() generator is created, which is to be pinned.

  2. Once it is pinned, it can be .init()-ialized with a #[generator]-tagged function.

As with any Generator, for a GeneratorFn to be usable, it must have been previously Pinned:

  • either in the heap, through Box::pin;

    use ::next_gen::{prelude::*, GeneratorFn};
    
    #[generator(u32)]
    fn countdown (mut remaining: u32)
    {
        while let Some(next) = remaining.checked_sub(1) {
            yield_!(remaining);
            remaining = next;
        }
    }
    
    let generator = GeneratorFn::empty();
    let mut generator = Box::pin(generator);
    generator.as_mut().init(countdown, (3,));
    
    let mut next = || generator.as_mut().resume();
    assert_eq!(next(), GeneratorState::Yield(3));
    assert_eq!(next(), GeneratorState::Yield(2));
    assert_eq!(next(), GeneratorState::Yield(1));
    assert_eq!(next(), GeneratorState::Return(()));
  • or in the stack, through stack_pinned!.

    use ::next_gen::{prelude::*, GeneratorFn};
    
    #[generator(u32)]
    fn countdown (mut remaining: u32)
    {
        while let Some(next) = remaining.checked_sub(1) {
            yield_!(remaining);
            remaining = next;
        }
    }
    
    let generator = GeneratorFn::empty();
    stack_pinned!(mut generator);
    generator.as_mut().init(countdown, (3,));
    let mut next = || generator.as_mut().resume();
    assert_eq!(next(), GeneratorState::Yield(3));
    assert_eq!(next(), GeneratorState::Yield(2));
    assert_eq!(next(), GeneratorState::Yield(1));
    assert_eq!(next(), GeneratorState::Return(()));

mk_gen!

mk_gen! is a macro that reduces the boilerplate of the above patterns, by performing the two step-initialization within a single macro call.

Stack vs. heap

Since stack-pinning prevents ever moving the generator around (duh), once stack-pinned, a Generator cannot be, for instance, returned. For that, Pinning in the heap is necessary:

use ::next_gen::prelude::*;

pub
fn countdown (count: u32)
  -> impl Iterator<Item = u32> + 'static
{
    #[generator(u32)]
    fn countdown (mut remaining: u32)
    {
        while let Some(next) = remaining.checked_sub(1) {
            yield_!(remaining);
            remaining = next;
        }
    }

    mk_gen!(let generator = box countdown(count));
    generator.into_iter() // A pinned generator is iterable.
}

However, pinning in the stack is vastly more performant (it is zero-cost in release mode), and suffices for local iteration. It is thus the blessed form of Pinning, which should be favored over box-ing.

use ::next_gen::prelude::*;

#[generator(u32)]
fn countdown (mut remaining: u32)
{
    while let Some(next) = remaining.checked_sub(1) {
        yield_!(remaining);
        remaining = next;
    }
}

mk_gen!(let generator = countdown(3));
assert_eq!(
    generator.into_iter().collect::<Vec<_>>(),
    [3, 2, 1],
);

Methods

impl<Item, F: Future> GeneratorFn<Item, F>[src]

pub fn empty() -> Self[src]

Reserves memory for an empty generator.

pub fn init<'pin, 'yield_slot, Args>(
    self: Pin<&'pin mut Self>,
    factory: impl FnOnce(YieldSlot<'yield_slot, Item>, Args) -> F,
    args: Args
) where
    Item: 'yield_slot, 
[src]

Fill the memory reserved by GeneratorFn::empty() with an instance of the generator function / factory.

pub fn resume(self: Pin<&mut Self>) -> GeneratorState<Item, F::Output>[src]

Associated method version of Generator::resume.

Trait Implementations

impl<Item, F: Future> Drop for GeneratorFn<Item, F>[src]

impl<Item, F: Future> Generator for GeneratorFn<Item, F>[src]

type Yield = Item

The type of value this generator yields. Read more

type Return = F::Output

The type of value this generator returns. Read more

Auto Trait Implementations

impl<Item, F> !RefUnwindSafe for GeneratorFn<Item, F>

impl<Item, F> Send for GeneratorFn<Item, F> where
    F: Send,
    Item: Send

impl<Item, F> !Sync for GeneratorFn<Item, F>

impl<Item, F> Unpin for GeneratorFn<Item, F> where
    F: Unpin,
    Item: Unpin

impl<Item, F> UnwindSafe for GeneratorFn<Item, F> where
    F: UnwindSafe,
    Item: UnwindSafe

Blanket Implementations

impl<T> Any for T where
    T: 'static + ?Sized
[src]

impl<T> Borrow<T> for T where
    T: ?Sized
[src]

impl<T> BorrowMut<T> for T where
    T: ?Sized
[src]

impl<T> From<T> for T[src]

impl<T, U> Into<U> for T where
    U: From<T>, 
[src]

impl<T, U> TryFrom<U> for T where
    U: Into<T>, 
[src]

type Error = Infallible

The type returned in the event of a conversion error.

impl<T, U> TryInto<U> for T where
    U: TryFrom<T>, 
[src]

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.