generate 1.1.0

Provides compatability layers for `std::ops::Generator` on stable rust.
Documentation
use std::future::Future;
use std::marker::Unpin;
use std::marker::{Send, Sync};
use std::pin::Pin;
use std::rc::Rc;
use std::task::{Context, Poll, RawWaker, RawWakerVTable, Waker};

use crate::{Generator, GeneratorState};

pub fn generator_mem<R, Y>() -> (Rc<Option<R>>, Rc<Option<Y>>) {
    (Rc::new(None), Rc::new(None))
}

struct YieldFuture<R> {
    __resume: Rc<Option<R>>,
}

impl<R> Future for YieldFuture<R> {
    type Output = R;

    fn poll(self: Pin<&mut Self>, _cx: &mut Context<'_>) -> Poll<Self::Output> {
        if let Some(r) = unsafe {
            (Rc::as_ptr(&mut Pin::into_inner(self).__resume) as *mut Option<R>)
                .as_mut()
                .expect("not null")
                .take()
        } {
            Poll::Ready(r)
        } else {
            Poll::Pending
        }
    }
}

pub fn yield_future<R, Y>(
    __resume: Rc<Option<R>>,
    mut __yield: Rc<Option<Y>>,
    val: Y,
) -> impl Future<Output = R> {
    let __yield = unsafe {
        (Rc::as_ptr(&mut __yield) as *mut Option<Y>)
            .as_mut()
            .expect("not null")
    };
    *__yield = Some(val);
    YieldFuture { __resume }
}

fn null_waker() -> Waker {
    unsafe fn clone(_: *const ()) -> RawWaker {
        RawWaker::new(&UNIT, &VTABLE)
    }
    unsafe fn nothing(_: *const ()) {}
    const UNIT: () = ();
    const VTABLE: RawWakerVTable = RawWakerVTable::new(clone, nothing, nothing, nothing);

    let raw_waker = RawWaker::new(&UNIT, &VTABLE);

    unsafe { Waker::from_raw(raw_waker) }
}

struct GeneratorImpl<R, Y, F> {
    __resume: Rc<Option<R>>,
    __yield: Rc<Option<Y>>,
    future: Pin<Box<F>>,
    done: bool,
}

impl<R, Y, F> Unpin for GeneratorImpl<R, Y, F> {}

unsafe impl<R, Y, F> Send for GeneratorImpl<R, Y, F>
where
    R: Send,
    Y: Send,
    F: Send,
{
}

unsafe impl<R, Y, F> Sync for GeneratorImpl<R, Y, F>
where
    R: Sync,
    Y: Sync,
    F: Sync,
{
}

impl<R, Y, F> Generator<R> for GeneratorImpl<R, Y, F>
where
    F: Future,
{
    type Yield = Y;
    type Return = F::Output;

    fn resume(self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return> {
        let me = Pin::get_mut(self);

        if me.done {
            panic!("Attempted to resume an already completed generator");
        }

        let waker = null_waker();
        let mut ctx = Context::from_waker(&waker);

        unsafe {
            let resume = (Rc::as_ptr(&mut me.__resume) as *mut Option<R>)
                .as_mut()
                .expect("not null");
            *resume = Some(arg);
        }

        let result = me.future.as_mut().poll(&mut ctx);

        match result {
            Poll::Pending => {
                let val = unsafe {
                    (Rc::as_ptr(&mut me.__yield) as *mut Option<Y>)
                        .as_mut()
                        .expect("not null")
                        .take()
                }
                .expect("generator compat future returned pending without setting yield");

                GeneratorState::Yielded(val)
            }
            Poll::Ready(val) => {
                me.done = true;
                GeneratorState::Complete(val)
            }
        }
    }
}

pub fn generator_for<R, Y, Ret, F>(
    __resume: Rc<Option<R>>,
    __yield: Rc<Option<Y>>,
    future: F,
) -> impl Generator<R, Yield = Y, Return = Ret>
where
    F: Future<Output = Ret>,
{
    GeneratorImpl {
        __resume,
        __yield,
        future: Box::pin(future),
        done: false,
    }
}