use crate::{
fib::{Fiber, FiberRoot, FiberState},
thr::prelude::*,
};
use core::{marker::Unpin, pin::Pin};
pub struct FiberFn<F, Y, R>(Option<F>)
where
F: FnMut() -> FiberState<Y, R>;
pub struct FiberOnce<F, R>(Option<F>)
where
F: FnOnce() -> R,
F: Unpin;
#[marker]
pub trait ReturnNone: Send + 'static {}
impl ReturnNone for () {}
impl ReturnNone for ! {}
impl<F, Y, R> Fiber for FiberFn<F, Y, R>
where
F: FnMut() -> FiberState<Y, R>,
{
type Input = ();
type Yield = Y;
type Return = R;
fn resume(self: Pin<&mut Self>, (): ()) -> FiberState<Y, R> {
let option = unsafe { &mut self.get_unchecked_mut().0 };
match option {
Some(f) => {
let state = f();
if state.is_complete() {
*option = None;
}
state
}
None => panic!("fiber resumed after completion"),
}
}
}
impl<F, R> FiberRoot for FiberFn<F, (), R>
where
F: FnMut() -> FiberState<(), R>,
F: Send + 'static,
R: ReturnNone,
{
#[inline]
fn advance(self: Pin<&mut Self>) -> bool {
match self.resume(()) {
FiberState::Yielded(()) => true,
FiberState::Complete(_) => false,
}
}
}
impl<F, R> Fiber for FiberOnce<F, R>
where
F: FnOnce() -> R,
F: Unpin,
{
type Input = ();
type Yield = !;
type Return = R;
fn resume(self: Pin<&mut Self>, (): ()) -> FiberState<!, R> {
FiberState::Complete(match self.get_mut().0.take() {
Some(f) => f(),
None => panic!("fiber resumed after completion"),
})
}
}
impl<F> FiberRoot for FiberOnce<F, ()>
where
F: FnOnce(),
F: Unpin + Send + 'static,
{
#[inline]
fn advance(self: Pin<&mut Self>) -> bool {
match self.resume(()) {
FiberState::Complete(()) => false,
}
}
}
#[inline]
pub fn new_fn<F, Y, R>(f: F) -> FiberFn<F, Y, R>
where
F: FnMut() -> FiberState<Y, R>,
{
FiberFn(Some(f))
}
#[inline]
pub fn new_once<F, R>(f: F) -> FiberOnce<F, R>
where
F: FnOnce() -> R,
F: Unpin,
{
FiberOnce(Some(f))
}
pub trait ThrFiberClosure: ThrToken {
#[inline]
fn add_fn<F, R>(self, f: F)
where
F: FnMut() -> FiberState<(), R>,
F: Send + 'static,
R: ReturnNone,
{
self.add_fib(new_fn(f))
}
#[inline]
fn add_once<F>(self, f: F)
where
F: FnOnce(),
F: Unpin + Send + 'static,
{
self.add_fib(new_once(f))
}
}
impl<T: ThrToken> ThrFiberClosure for T {}