pub fn new<F>(stack: Stack, f: F) -> Generator<'a, Input, Output, Stack>
    where
        F: FnOnce(&Yielder<Input, Output>, Input) + 'a,
    {
        // This function will be written to the new stack (by `arch::init`) as the initial
        // entry point. During the `arch::swap_and_link_stacks` call it will be called with
        // the correct closure passed as the first argument. This function will never return.
        // Yielding back into it after `yielder.suspend_(GeneratorOutput::Finished)` was
        // called would be undefined behavior.
        unsafe extern "C" fn generator_wrapper<Input, Output, Stack, F>(
            f_ptr: usize,
            stack_ptr: *mut usize,
        ) where
            Stack: stack::Stack,
            F: FnOnce(&Yielder<Input, Output>, Input),
        {
            let f = std::ptr::read(f_ptr as *const F);
            let (data, stack_ptr) = arch::swap(0, stack_ptr);
            let input = std::ptr::read(data as *const Input);
            let yielder = Yielder::new(stack_ptr);

            // It is not safe to unwind across the context switch.
            // The unwind will continue in the original context.
            match catch_unwind(AssertUnwindSafe(|| {
                f(&yielder, input);
            })) {
                Ok(_) => yielder.suspend_(GeneratorOutput::Finished),
                Err(panic) => yielder.suspend_(GeneratorOutput::Panic(panic)),
            };
        }

        // Prepare the stack
        let stack_ptr = unsafe { arch::init(&stack, generator_wrapper::<Input, Output, Stack, F>) };

        // f needs to live on after this function, it is part of the new context. This prevents it
        // from being dropped. The drop happens inside of the `generator_wrapper()` function.
        let f = mem::ManuallyDrop::new(f);

        // This call will link the stacks together with assembly directives magic, but once the
        // first `arch::swap` inside `generator_wrapper` is reached it will yield back before the
        // execution of the closure `f`.
        // Only the next call to `resume` will start executing the closure.
        let stack_ptr = unsafe {
            arch::swap_and_link_stacks(
                &f as *const mem::ManuallyDrop<F> as usize,
                stack_ptr,
                stack.bottom(),
            )
            .1
        };

        Generator {
            started: false,
            stack: Some(stack),
            stack_ptr: Some(NonNull::new(stack_ptr).unwrap()),
            phantom: PhantomData,
        }
    }
/// Create a new generator from a stack and closure.
Create a new generator from a stack and closure.
Create a new generator from a stack and closure .
pub fn new<F>(stack: Stack, f: F) -> Generator<'a, Input, Output, Stack>
    where
        F: FnOnce(&Yielder<Input, Output>, Input) + 'a,
    {
        // This function will be written to the new stack (by `arch::init`) as the initial
        // entry point. During the `arch::swap_and_link_stacks` call it will be called with
        // the correct closure passed as the first argument. This function will never return.
        // Yielding back into it after `yielder.suspend_(GeneratorOutput::Finished)` was
        // called would be undefined behavior.
        unsafe extern "C" fn generator_wrapper<Input, Output, Stack, F>(
            f_ptr: usize,
            stack_ptr: *mut usize,
        ) where
            Stack: stack::Stack,
            F: FnOnce(&Yielder<Input, Output>, Input),
        {
            let f = std::ptr::read(f_ptr as *const F);
            let (data, stack_ptr) = arch::swap(0, stack_ptr);
            let input = std::ptr::read(data as *const Input);
            let yielder = Yielder::new(stack_ptr);
            // It is not safe to unwind across the context switch.
            // The unwind will continue in the original context.
            match catch_unwind(AssertUnwindSafe(|| {
                f(&yielder, input);
            })) {
                Ok(_) => yielder.suspend_(GeneratorOutput::Finished),
                Err(panic) => yielder.suspend_(GeneratorOutput::Panic(panic)),
            };
        }
        // Prepare the stack
        let stack_ptr = unsafe { arch::init(&stack, generator_wrapper::<Input, Output, Stack, F>) };
        // f needs to live on after this function, it is part of the new context. This prevents it
        // from being dropped. The drop happens inside of the `generator_wrapper()` function.
        let f = mem::ManuallyDrop::new(f);
        // This call will link the stacks together with assembly directives magic, but once the
        // first `arch::swap` inside `generator_wrapper` is reached it will yield back before the
        // execution of the closure `f`.
        // Only the next call to `resume` will start executing the closure.
        let stack_ptr = unsafe {
            arch::swap_and_link_stacks(
                &f as *const mem::ManuallyDrop<F> as usize,
                stack_ptr,
                stack.bottom(),
            )
            .1
        };
        Generator {
            started: false,
            stack: Some(stack),
            stack_ptr: Some(NonNull::new(stack_ptr).unwrap()),
            phantom: PhantomData,
        }
    }
pub fn new < F > ( stack : Stack , f : F ) -> Generator < ' a , Input , Output , Stack > where F : FnOnce ( & Yielder < Input , Output > , Input ) + ' a , { // This function will be written to the new stack (by `arch::init`) as the initial // entry point. During the `arch::swap_and_link_stacks` call it will be called with // the correct closure passed as the first argument. This function will never return. // Yielding back into it after `yielder.suspend_(GeneratorOutput::Finished)` was // called would be undefined behavior. unsafe extern " " fn generator_wrapper < Input , Output , Stack , F > ( f_ptr : usize , stack_ptr : * mut usize , ) where Stack : stack :: Stack , F : FnOnce ( & Yielder < Input , Output > , Input ) , { let f = std :: ptr :: read ( f_ptr as * const F ) ; let ( data , stack_ptr ) = arch :: swap ( 0 , stack_ptr ) ; let input = std :: ptr :: read ( data as * const Input ) ; let yielder = Yielder :: new ( stack_ptr ) ; // It is not safe to unwind across the context switch. // The unwind will continue in the original context. match catch_unwind ( AssertUnwindSafe ( | | { f ( & yielder , input ) ; } ) ) { Ok ( _ ) => yielder . suspend_ ( GeneratorOutput :: Finished ) , Err ( panic ) => yielder . suspend_ ( GeneratorOutput :: Panic ( panic ) ) , } ; } // Prepare the stack let stack_ptr = unsafe { arch :: init ( & stack , generator_wrapper :: < Input , Output , Stack , F > ) } ; // f needs to live on after this function, it is part of the new context. This prevents it // from being dropped. The drop happens inside of the `generator_wrapper()` function. let f = mem :: ManuallyDrop :: new ( f ) ; // This call will link the stacks together with assembly directives magic, but once the // first `arch::swap` inside `generator_wrapper` is reached it will yield back before the // execution of the closure `f`. // Only the next call to `resume` will start executing the closure. let stack_ptr = unsafe { arch :: swap_and_link_stacks ( & f as * const mem :: ManuallyDrop < F > as usize , stack_ptr , stack . bottom ( ) , ) . 1 } ; Generator { started : false , stack : Some ( stack ) , stack_ptr : Some ( NonNull :: new ( stack_ptr ) . unwrap ( ) ) , phantom : PhantomData , } }
Create a new generator from a stack and closure.
Create a new generator from a stack and closure .
stack
Stack
f
F
stack
Stack
f
F