use std::cell::Cell;
use std::marker::PhantomData;
-use std::pin::Pin;
use std::ops::{Generator, GeneratorState};
+use std::pin::Pin;
#[derive(Copy, Clone)]
pub struct AccessAction(*mut dyn FnMut());
thread_local!(pub static BOX_REGION_ARG: Cell<Action> = Cell::new(Action::Complete));
pub struct PinnedGenerator<I, A, R> {
- generator: Pin<Box<dyn Generator<Yield = YieldType<I, A>, Return = R>>>
+ generator: Pin<Box<dyn Generator<Yield = YieldType<I, A>, Return = R>>>,
}
impl<I, A, R> PinnedGenerator<I, A, R> {
- pub fn new<
- T: Generator<Yield = YieldType<I, A>, Return = R> + 'static
- >(generator: T) -> (I, Self) {
- let mut result = PinnedGenerator {
- generator: Box::pin(generator)
- };
+ #[cfg(bootstrap)]
+ pub fn new<T: Generator<Yield = YieldType<I, A>, Return = R> + 'static>(
+ generator: T,
+ ) -> (I, Self) {
+ let mut result = PinnedGenerator { generator: Box::pin(generator) };
// Run it to the first yield to set it up
let init = match Pin::new(&mut result.generator).resume() {
- GeneratorState::Yielded(
- YieldType::Initial(y)
- ) => y,
- _ => panic!()
+ GeneratorState::Yielded(YieldType::Initial(y)) => y,
+ _ => panic!(),
+ };
+
+ (init, result)
+ }
+
+ #[cfg(not(bootstrap))]
+ pub fn new<T: Generator<Yield = YieldType<I, A>, Return = R> + 'static>(
+ generator: T,
+ ) -> (I, Self) {
+ let mut result = PinnedGenerator { generator: Box::pin(generator) };
+
+ // Run it to the first yield to set it up
+ let init = match Pin::new(&mut result.generator).resume(()) {
+ GeneratorState::Yielded(YieldType::Initial(y)) => y,
+ _ => panic!(),
};
(init, result)
}
+ #[cfg(bootstrap)]
pub unsafe fn access(&mut self, closure: *mut dyn FnMut()) {
BOX_REGION_ARG.with(|i| {
i.set(Action::Access(AccessAction(closure)));
}
}
- pub fn complete(&mut self) -> R {
- // Tell the generator we want it to complete, consuming it and yielding a result
+ #[cfg(not(bootstrap))]
+ pub unsafe fn access(&mut self, closure: *mut dyn FnMut()) {
BOX_REGION_ARG.with(|i| {
- i.set(Action::Complete)
+ i.set(Action::Access(AccessAction(closure)));
});
- let result = Pin::new(&mut self.generator).resume();
- if let GeneratorState::Complete(r) = result {
- r
- } else {
+ // Call the generator, which in turn will call the closure in BOX_REGION_ARG
+ if let GeneratorState::Complete(_) = Pin::new(&mut self.generator).resume(()) {
panic!()
}
}
+
+ #[cfg(bootstrap)]
+ pub fn complete(&mut self) -> R {
+ // Tell the generator we want it to complete, consuming it and yielding a result
+ BOX_REGION_ARG.with(|i| i.set(Action::Complete));
+
+ let result = Pin::new(&mut self.generator).resume();
+ if let GeneratorState::Complete(r) = result { r } else { panic!() }
+ }
+
+ #[cfg(not(bootstrap))]
+ pub fn complete(&mut self) -> R {
+ // Tell the generator we want it to complete, consuming it and yielding a result
+ BOX_REGION_ARG.with(|i| i.set(Action::Complete));
+
+ let result = Pin::new(&mut self.generator).resume(());
+ if let GeneratorState::Complete(r) = result { r } else { panic!() }
+ }
}
#[derive(PartialEq)]