package com.zarbosoft.coroutines; import com.zarbosoft.coroutinescore.SuspendExecution; import com.zarbosoft.coroutinescore.SuspendableRunnable; import java.util.Iterator; import java.util.Spliterator; import java.util.Spliterators; import java.util.stream.Stream; import java.util.stream.StreamSupport; import static com.zarbosoft.coroutines.Coroutine.yield; public class Generator<T> { private final static Object END = new Object(); private Generator() { } private T value; public void yieldValue(T value) throws SuspendExecution { this.value = value; yield(); } public static <T> Stream<T> stream(SuspendableConsumer<Generator<T>> runnable) { Generator<T> g = new Generator<T>(); Coroutine c = new Coroutine(new SuspendableRunnable() { @Override public void run() throws SuspendExecution { runnable.apply(g); } }); return StreamSupport.stream(Spliterators.spliteratorUnknownSize(new Iterator() { @Override public boolean hasNext() { return !c.isFinished(); } @Override public Object next() { c.process(); if (c.isFinished()) return END; return g.value; } }, Spliterator.ORDERED), false).filter(v -> v != END); } }