use core::marker::PhantomData;
use crate::stack;
#[cfg(feature = "default-stack")]
use crate::stack::DefaultStack;
use crate::trap::CoroutineTrapHandler;
use crate::{Coroutine, CoroutineResult, Yielder};
#[cfg(not(feature = "default-stack"))]
pub struct ScopedCoroutine<'a, Input, Yield, Return, Stack: stack::Stack> {
inner: Coroutine<Input, Yield, Return, Stack>,
marker: PhantomData<&'a mut ()>,
}
#[cfg(feature = "default-stack")]
pub struct ScopedCoroutine<'a, Input, Yield, Return, Stack: stack::Stack = DefaultStack> {
inner: Coroutine<Input, Yield, Return, Stack>,
marker: PhantomData<&'a mut ()>,
}
#[cfg(feature = "default-stack")]
impl<'a, Input, Yield, Return> ScopedCoroutine<'a, Input, Yield, Return, DefaultStack> {
pub fn new<F: 'a>(func: F) -> Self
where
F: FnOnce(&Yielder<Input, Yield>, Input) -> Return,
{
Self::with_stack(Default::default(), func)
}
}
impl<'a, Input, Yield, Return, Stack: stack::Stack>
ScopedCoroutine<'a, Input, Yield, Return, Stack>
{
pub fn with_stack<F: 'a>(stack: Stack, func: F) -> Self
where
F: FnOnce(&Yielder<Input, Yield>, Input) -> Return,
{
Self {
inner: unsafe { Coroutine::with_stack_unchecked(stack, func) },
marker: PhantomData,
}
}
pub fn into_stack(self) -> Stack {
self.inner.into_stack()
}
pub fn scope<F, T>(mut self, f: F) -> T
where
F: FnOnce(ScopedCoroutineRef<'_, Input, Yield, Return, Stack>) -> T,
{
let coroutine = ScopedCoroutineRef {
inner: &mut self.inner,
};
f(coroutine)
}
}
pub struct ScopedCoroutineRef<'a, Input, Yield, Return, Stack: stack::Stack> {
inner: &'a mut Coroutine<Input, Yield, Return, Stack>,
}
impl<Input, Yield, Return, Stack: stack::Stack>
ScopedCoroutineRef<'_, Input, Yield, Return, Stack>
{
pub fn as_mut(&mut self) -> ScopedCoroutineRef<'_, Input, Yield, Return, Stack> {
ScopedCoroutineRef { inner: self.inner }
}
pub fn resume(&mut self, val: Input) -> CoroutineResult<Yield, Return> {
self.inner.resume(val)
}
pub fn started(&self) -> bool {
self.inner.started()
}
pub fn done(&self) -> bool {
self.inner.done()
}
pub unsafe fn force_reset(&mut self) {
self.inner.force_reset()
}
pub fn force_unwind(&mut self) {
self.inner.force_unwind()
}
pub fn trap_handler(&self) -> CoroutineTrapHandler<Return> {
self.inner.trap_handler()
}
}