use core::fmt::{self, Debug, Formatter};
use core::marker::PhantomData;
use core::mem;
use core::num::NonZeroUsize;
use core::ops::{Generator, GeneratorState};
use core::pin::Pin;
use crate::NoData;
pub trait Resumable<'a, R, G: Generator<R>> {
#[must_use]
fn as_mut(&mut self) -> Pin<&mut G>;
#[must_use]
fn resume(&mut self, arg: R) -> GeneratorState<G::Yield, G::Return> {
self.as_mut().resume(arg)
}
fn expect_yield(&mut self, arg: R) -> G::Yield {
match self.resume(arg) {
GeneratorState::Yielded(item) => item,
GeneratorState::Complete(..) => panic!("generator completed"),
}
}
fn expect_complete(&mut self, arg: R) -> G::Return {
match self.resume(arg) {
GeneratorState::Yielded(..) => panic!("generator yielded"),
GeneratorState::Complete(item) => item,
}
}
#[must_use]
fn iter(self) -> Iter<'a, G>
where G: Generator<(), Return = ()>;
#[must_use]
fn fuse(self) -> Fuse<'a, R, G>
where G: Generator<R, Return = ()>;
#[must_use]
fn states(self) -> States<'a, R, G>;
#[must_use]
fn unify<T>(self) -> Unify<'a, R, T, G>
where G: Generator<R, Yield = T, Return = T>;
}
impl<'a, R, G: Generator<R>> Resumable<'a, R, G> for Pin<&'a mut G> {
fn as_mut(&mut self) -> Pin<&mut G> {
Pin::as_mut(self)
}
fn iter(self) -> Iter<'a, G>
where G: Generator<(), Return = ()> {
Iter::new(self)
}
fn unify<T>(self) -> Unify<'a, R, T, G>
where G: Generator<R, Yield = T, Return = T> {
Unify::new(self)
}
fn fuse(self) -> Fuse<'a, R, G>
where G: Generator<R, Return = ()> {
Fuse::new(self)
}
fn states(self) -> States<'a, R, G> {
States::new(self)
}
}
impl<'a, R, G: Generator<R> + Unpin> Resumable<'a, R, G> for &'a mut G {
fn as_mut(&mut self) -> Pin<&mut G> {
Pin::new(self)
}
fn iter(self) -> Iter<'a, G>
where G: Generator<(), Return = ()> {
Iter::new(Pin::new(self))
}
fn unify<T>(self) -> Unify<'a, R, T, G>
where G: Generator<R, Yield = T, Return = T> {
Unify::new(Pin::new(self))
}
fn fuse(self) -> Fuse<'a, R, G>
where G: Generator<R, Return = ()> {
Fuse::new(Pin::new(self))
}
fn states(self) -> States<'a, R, G> {
States::new(Pin::new(self))
}
}
pub struct Iter<'a, G: Generator<()>> {
pin: Pin<&'a mut G>,
}
impl<'a, G: Generator<(), Return = ()>> Iter<'a, G> {
#[must_use]
pub fn new(pin: Pin<&'a mut G>) -> Self {
Self { pin }
}
#[must_use]
pub fn into_inner(self) -> Pin<&'a mut G> {
self.pin
}
}
impl<'a, G: Generator<(), Return = ()>> Debug for Iter<'a, G> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.debug_struct("Iter").field("ptr", &(self.pin.as_ref().get_ref() as *const G)).finish()
}
}
impl<'a, G: Generator<(), Return = ()>> Iterator for Iter<'a, G> {
type Item = G::Yield;
fn next(&mut self) -> Option<Self::Item> {
match self.pin.as_mut().resume(()) {
GeneratorState::Yielded(item) => Some(item),
GeneratorState::Complete(()) => None,
}
}
}
#[repr(transparent)]
struct TaggedPin<'a, G> {
ptr: NonZeroUsize,
_data: PhantomData<Pin<&'a mut G>>,
}
impl<'a, G> TaggedPin<'a, G> {
#[must_use]
fn new(pin: Pin<&'a mut G>) -> Self {
assert!(mem::align_of::<G>() > 1);
unsafe {
Self {
ptr: NonZeroUsize::new_unchecked(pin.get_unchecked_mut() as *mut G as usize),
_data: PhantomData,
}
}
}
fn get_ptr(&self) -> *mut G {
(self.ptr.get() & !1) as *mut G
}
fn get_pin(&mut self) -> Pin<&'a mut G> {
unsafe { Pin::new_unchecked(&mut *self.get_ptr()) }
}
fn get_tag(&self) -> bool {
(self.ptr.get() & 1) != 0
}
fn set_tag(&mut self) {
self.ptr = unsafe { NonZeroUsize::new_unchecked(self.ptr.get() | 1) };
}
fn into_inner(mut self) -> Pin<&'a mut G> {
self.get_pin()
}
}
pub struct States<'a, R, G: Generator<R>> {
pin: TaggedPin<'a, G>,
_arg: NoData<R>,
}
impl<'a, R, G: Generator<R>> States<'a, R, G> {
#[must_use]
pub fn new(pin: Pin<&'a mut G>) -> Self {
Self { pin: TaggedPin::new(pin), _arg: NoData::new() }
}
#[must_use]
pub fn into_inner(self) -> Pin<&'a mut G> {
self.pin.into_inner()
}
}
impl<'a, R, G: Generator<R>> Debug for States<'a, R, G> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.debug_struct("States").field("ptr", &self.pin.get_ptr()).finish()
}
}
impl<'a, R, G: Generator<R>> Generator<R> for States<'a, R, G> {
type Yield = GeneratorState<G::Yield, G::Return>;
type Return = ();
fn resume(mut self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return> {
if self.pin.get_tag() {
GeneratorState::Complete(())
} else {
match self.pin.get_pin().resume(arg) {
yielded @ GeneratorState::Yielded(..) => GeneratorState::Yielded(yielded),
complete @ GeneratorState::Complete(..) => {
self.pin.set_tag();
GeneratorState::Yielded(complete)
}
}
}
}
}
pub struct Unify<'a, R, T, G: Generator<R, Yield = T, Return = T>> {
pin: TaggedPin<'a, G>,
_arg: NoData<R>,
}
impl<'a, R, T, G: Generator<R, Yield = T, Return = T>> Unify<'a, R, T, G> {
#[must_use]
pub fn new(pin: Pin<&'a mut G>) -> Self {
Self { pin: TaggedPin::new(pin), _arg: NoData::new() }
}
#[must_use]
pub fn into_inner(self) -> Pin<&'a mut G> {
self.pin.into_inner()
}
}
impl<'a, R, T, G: Generator<R, Yield = T, Return = T>> Debug for Unify<'a, R, T, G> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.debug_struct("Unify").field("ptr", &self.pin.get_ptr()).finish()
}
}
impl<'a, R, T, G: Generator<R, Yield = T, Return = T>> Generator<R> for Unify<'a, R, T, G> {
type Yield = T;
type Return = ();
fn resume(mut self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return> {
if self.pin.get_tag() {
GeneratorState::Complete(())
} else {
match self.pin.get_pin().resume(arg) {
GeneratorState::Yielded(item) => GeneratorState::Yielded(item),
GeneratorState::Complete(item) => {
self.pin.set_tag();
GeneratorState::Yielded(item)
}
}
}
}
}
pub struct Fuse<'a, R, G: Generator<R>> {
pin: TaggedPin<'a, G>,
_arg: NoData<R>,
}
impl<'a, R, G: Generator<R, Return = ()>> Fuse<'a, R, G> {
#[must_use]
pub fn new(pin: Pin<&'a mut G>) -> Self {
Self { pin: TaggedPin::new(pin), _arg: NoData::new() }
}
#[must_use]
pub fn is_complete(&self) -> bool {
self.pin.get_tag()
}
pub fn stop(&mut self) {
self.pin.set_tag()
}
#[must_use]
pub fn into_inner(self) -> Pin<&'a mut G> {
self.pin.into_inner()
}
}
impl<'a, R, G: Generator<R, Return = ()>> Debug for Fuse<'a, R, G> {
fn fmt(&self, f: &mut Formatter) -> fmt::Result {
f.debug_struct("Fuse")
.field("fuse", &self.pin.get_tag())
.field("ptr", &self.pin.get_ptr())
.finish()
}
}
impl<'a, R, G: Generator<R, Return = ()>> Generator<R> for Fuse<'a, R, G> {
type Yield = G::Yield;
type Return = ();
fn resume(mut self: Pin<&mut Self>, arg: R) -> GeneratorState<Self::Yield, Self::Return> {
if self.pin.get_tag() {
GeneratorState::Complete(())
} else {
match self.pin.get_pin().resume(arg) {
yielded @ GeneratorState::Yielded(..) => yielded,
complete @ GeneratorState::Complete(..) => {
self.pin.set_tag();
complete
}
}
}
}
}