pub use crate::proc_macro::{karutin, karutin_str};
#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
pub enum KarutinState<Yield, Return> {
Yielded(Yield),
Returned(Return),
Completed,
}
impl<Y, R> KarutinState<Y, R> {
pub fn is_concluded(&self) -> bool {
match self {
Self::Yielded(_) => false,
Self::Returned(_) => true,
Self::Completed => true,
}
}
}
impl<T> KarutinState<T, T> {
pub fn into_option(self) -> Option<T> {
match self {
Self::Yielded(v) | Self::Returned(v) => Some(v),
Self::Completed => None,
}
}
}
pub trait Karutin<Args = ()>: Sized {
type Yield;
type Return;
fn resume(&mut self, args: Args) -> KarutinState<Self::Yield, Self::Return>;
}
#[doc(inline)]
pub use crate::iter::KarutinIter;
#[doc(inline)]
pub use crate::future::KarutinFuture;
pub trait KarutinGen: Karutin<()> {
fn resume(&mut self) -> KarutinState<Self::Yield, Self::Return> {
Karutin::resume(self, ())
}
fn into_iter(self) -> KarutinIter<Self> {
KarutinIter::new(self)
}
fn into_iter_outed(self) -> KarutinIter<Self> {
KarutinIter::new_outed(self)
}
fn into_iter_endless(self) -> KarutinIter<Self> {
KarutinIter::new_endless(self)
}
fn into_closure(mut self) -> impl FnMut() -> KarutinState<Self::Yield, Self::Return> {
move || KarutinGen::resume(&mut self)
}
}
pub trait KarutinPal<T>: Karutin<Yield = T, Return = T> {}
pub trait KarutinPalGen<T>: KarutinPal<T> + KarutinGen {
fn into_value_iter(self) -> impl Iterator<Item = T> {
self.into_iter().into_value_iter()
}
fn into_values(self) -> Vec<T> {
self.into_iter().into_values()
}
}
pub trait KarutinUniGen: KarutinGen<Yield = ()> {
fn into_future(self) -> KarutinFuture<Self> {
self.into()
}
fn into_closure_once(self) -> impl FnOnce() -> Option<Self::Return> {
|| {
let mut iter = self.into_iter_outed();
let concluded = iter.find(KarutinState::is_concluded);
match concluded {
Some(KarutinState::Returned(ret)) => Some(ret),
_ => None,
}
}
}
}
impl<T: Karutin<()>> KarutinGen for T {}
impl<U, T: Karutin<Yield = U, Return = U>> KarutinPal<U> for T {}
impl<U, T: KarutinPal<U> + KarutinGen> KarutinPalGen<U> for T {}
impl<T: KarutinGen<Yield = ()>> KarutinUniGen for T {}
pub mod proc_macro {
#[doc(inline)]
pub use karutin_proc_macro::karutin;
#[doc(inline)]
pub use karutin_proc_macro::karutin_str;
}
pub mod iter {
use crate::{Karutin, KarutinGen, KarutinState};
pub enum CompleteStrategy {
Once,
Outed,
Infinite,
}
impl Default for CompleteStrategy {
fn default() -> Self {
CompleteStrategy::Once
}
}
pub struct KarutinIter<T: KarutinGen> {
complete_strategy: CompleteStrategy,
is_ended: bool,
inner: T,
}
impl<T: KarutinGen> KarutinIter<T> {
fn _new(i: T, s: CompleteStrategy) -> KarutinIter<T> {
KarutinIter {
complete_strategy: s,
is_ended: false,
inner: i,
}
}
pub fn new(karutin: T) -> KarutinIter<T> {
Self::_new(karutin, Default::default())
}
pub fn new_outed(karutin: T) -> KarutinIter<T> {
Self::_new(karutin, CompleteStrategy::Outed)
}
pub fn new_endless(karutin: T) -> KarutinIter<T> {
Self::_new(karutin, CompleteStrategy::Infinite)
}
fn is_next_last(&self, next: &KarutinState<T::Yield, T::Return>) -> bool {
match (&next, &self.complete_strategy) {
| (KarutinState::Completed, CompleteStrategy::Once)
| (KarutinState::Completed, CompleteStrategy::Outed)
| (KarutinState::Returned(_), CompleteStrategy::Outed) => true,
_whoever_reads_this_is_gay_ => false,
}
}
}
impl<T, U> KarutinIter<T>
where
T: Karutin<(), Yield = U, Return = U>,
{
pub fn into_value_iter(mut self) -> impl Iterator<Item = U> {
self.complete_strategy = CompleteStrategy::Outed;
self.filter_map(KarutinState::into_option)
}
pub fn into_values(self) -> Vec<U> {
Self::into_value_iter(self).collect()
}
}
impl<T: KarutinGen> Iterator for KarutinIter<T> {
type Item = KarutinState<T::Yield, T::Return>;
fn next(&mut self) -> Option<Self::Item> {
if self.is_ended {
return None;
}
let next = KarutinGen::resume(&mut self.inner);
if self.is_next_last(&next) {
self.is_ended = true;
}
Some(next)
}
}
impl<T: KarutinGen> From<T> for KarutinIter<T> {
fn from(karutin: T) -> Self {
Self::new(karutin)
}
}
struct KarutinBridgeIter<T, U>
where
T: Iterator<Item = U>,
{
inner: T,
}
impl<T, U> Karutin<()> for KarutinBridgeIter<T, U>
where
T: Iterator<Item = U>,
{
type Yield = T::Item;
type Return = T::Item;
fn resume(&mut self, _args: ()) -> KarutinState<Self::Yield, Self::Return> {
if let Some(yielded) = self.inner.next() {
KarutinState::Yielded(yielded)
} else {
KarutinState::Completed
}
}
}
impl<T, U> Iterator for KarutinBridgeIter<T, U>
where
T: Iterator<Item = U>,
{
type Item = U;
fn next(&mut self) -> Option<Self::Item> {
self.inner.next()
}
}
impl<T, U> From<T> for KarutinBridgeIter<T::IntoIter, U>
where
T: IntoIterator<Item = U>,
T::IntoIter: Iterator<Item = U>,
{
fn from(value: T) -> Self {
Self {
inner: value.into_iter(),
}
}
}
impl<T, U> From<T> for KarutinIter<KarutinBridgeIter<T::IntoIter, U>>
where
T: IntoIterator<Item = U>,
T::IntoIter: Iterator<Item = U>,
{
fn from(value: T) -> Self {
Self::new(KarutinBridgeIter::from(value))
}
}
#[doc(hidden)]
#[rustfmt::skip]
#[macro_export]
macro_rules! into_value_iter {
($expr:expr) => {
::karutin::iter::KarutinIter::from($expr).into_value_iter()
};
}
#[doc(inline)]
pub use into_value_iter;
}
pub mod future {
use crate::{KarutinIter, KarutinState, KarutinUniGen};
use std::pin::Pin;
use std::task::{Context, Poll};
pub struct KarutinFuture<T: KarutinUniGen> {
iter: KarutinIter<T>,
}
impl<T: KarutinUniGen> KarutinFuture<T> {
pub fn new(karutin: T) -> KarutinFuture<T> {
Self {
iter: karutin.into_iter_outed(),
}
}
}
impl<T: KarutinUniGen> From<T> for KarutinFuture<T> {
fn from(karutin: T) -> Self {
Self::new(karutin)
}
}
impl<T: KarutinUniGen + Unpin> Future for KarutinFuture<T> {
type Output = Option<T::Return>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let Some(next) = self.get_mut().iter.next() else {
return Poll::Pending;
};
cx.waker().wake_by_ref();
match next {
KarutinState::Yielded(_) => Poll::Pending,
KarutinState::Returned(r) => Poll::Ready(r.into()),
KarutinState::Completed => Poll::Ready(None),
}
}
}
}
#[doc(hidden)]
pub mod internal {
use crate::KarutinState;
#[inline(always)]
pub fn unchecked_zeroed<T>() -> T {
unsafe {
#[allow(invalid_value)]
std::mem::MaybeUninit::zeroed().assume_init()
}
}
pub type RawStackPair<'a> = (&'a [u8], &'a [u8]);
pub type LeakedStackPair<'a, T> = (&'a mut T, &'a mut T);
pub type BoxedStackPair<T> = (Box<T>, Box<T>);
#[derive(Debug)]
pub struct KarutinStack<'a> {
inner: &'a [u8],
rep: &'a [u8],
}
impl<'a> KarutinStack<'a> {
pub fn create_zeroeds<T>() -> BoxedStackPair<T> {
(Box::new(unchecked_zeroed()), Box::new(unchecked_zeroed()))
}
pub fn get_boxes<T>(&self) -> BoxedStackPair<T> {
unsafe {
(
Box::from_raw(self.inner.as_ptr() as *mut T),
Box::from_raw(self.rep.as_ptr() as *mut T),
)
}
}
fn leak<'b, T>(boxeds: BoxedStackPair<T>) -> LeakedStackPair<'b, T> {
(Box::leak(boxeds.0), Box::leak(boxeds.1))
}
fn get_raws<'b, T>(refs: LeakedStackPair<'b, T>) -> RawStackPair<'b> {
let get_raw = |ref_| unsafe {
let pointer = ref_ as *mut T as *mut u8;
std::slice::from_raw_parts_mut(pointer, std::mem::size_of::<T>())
};
(get_raw(refs.0), get_raw(refs.1))
}
fn from_raws(value: RawStackPair<'a>) -> Self {
Self {
inner: value.0,
rep: value.1,
}
}
}
impl<'a, T: 'a> From<BoxedStackPair<T>> for KarutinStack<'a> {
fn from(value: BoxedStackPair<T>) -> Self {
let leakeds = KarutinStack::leak(value);
let raws = KarutinStack::get_raws(leakeds);
KarutinStack::from_raws(raws)
}
}
pub enum KarutinResponse<'a, Y, R> {
StackExpose(KarutinStack<'a>),
StateLoop(KarutinState<Y, R>),
}
}
pub mod prelude {
pub use crate::KarutinState;
pub use crate::proc_macro::karutin;
pub use crate::{Karutin, KarutinGen, KarutinPal, KarutinPalGen, KarutinUniGen};
}