1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
use_prelude!();

pub
struct ItemSlot<'item_slot, Item : 'item_slot> (
    Pin<&'item_slot CellOption<Item>>,
);

impl<'item_slot, Item : 'item_slot> From<Pin<&'item_slot CellOption<Item>>>
    for ItemSlot<'item_slot, Item>
{
    #[inline]
    fn from (p: Pin<&'item_slot CellOption<Item>>)
      -> Self
    {
        Self(p)
    }
}

impl<Item> Clone for ItemSlot<'_, Item> {
    #[inline]
    fn clone (self: &'_ Self)
      -> Self
    {
        let Self(ref inner) = *self;
        Self(*inner)
    }
}

#[pin_project]
pub
struct Generator<'item_slot, Item : 'item_slot, F : Future> {
    item_slot: ItemSlot<'item_slot, Item>,

    #[pin]
    future: F,
}

impl<'item_slot, Item : 'item_slot, F : Future> Generator<'item_slot, Item, F> {
    pub
    fn new<Args> (
        item_slot: ItemSlot<'item_slot, Item>,
        factory: impl FnOnce(Coroutine<'item_slot, Item>, Args) -> F,
        args: Args,
    ) -> Self
    {
        Self {
            future: factory(Coroutine { item_slot: item_slot.clone() }, args),
            item_slot,
        }
    }

    pub
    fn resume (self: Pin<&'_ mut Self>)
      -> GeneratorState<Item, F::Output>
    {
        let this = self.project();
        create_context!(cx);
        match this.future.poll(&mut cx) {
            | Poll::Pending => {
                let value =
                    this.item_slot
                        .0
                        .take()
                        .expect("Missing item in item_slot!")
                ;
                GeneratorState::Yield(value)
            },

            | Poll::Ready(value) => {
                GeneratorState::Return(value)
            }
        }
    }
}

#[derive(
    Debug,
    Clone, Copy,
    PartialEq, Eq,
)]
pub
enum GeneratorState<Yield, Return = ()> {
    Yield(Yield),

    Return(Return),
}

pub
struct Coroutine<'item_slot, Item : 'item_slot> {
    item_slot: ItemSlot<'item_slot, Item>,
}

impl<'slot_item, Item> Coroutine<'slot_item, Item> {
    pub
    fn _yield (self: &'_ Self, value: Item)
      -> impl Future<Output = ()> + '_
    {
        let Self { ref item_slot, .. } = *self;
        let _ = item_slot.0.set(value);
        WaitForClear { item_slot }
    }
}

struct WaitForClear<'item_slot, Item : 'item_slot> {
    item_slot: &'item_slot ItemSlot<'item_slot, Item>,
}

impl<'item_slot, Item> Future for WaitForClear<'item_slot, Item>
{
    type Output = ();

    fn poll (self: Pin<&'_ mut Self>, _: &'_ mut Context<'_>)
      -> Poll<()>
    {
        if /* while */ self.item_slot.0.is_some() {
            Poll::Pending
        } else {
            Poll::Ready(())
        }
    }
}