Diffstat (limited to 'src/effect/async/value.rs')
-rw-r--r--src/effect/async/value.rs98
1 files changed, 98 insertions, 0 deletions
diff --git a/src/effect/async/value.rs b/src/effect/async/value.rs
new file mode 100644
index 0000000..c3a80ca
--- /dev/null
+++ b/src/effect/async/value.rs
@@ -0,0 +1,98 @@
+use core::ops::ControlFlow;
+
+use crate::effect::{Effective, ErasedEffective};
+
+use super::{Async, BoxOrReady};
+
+pub struct Value<T>(pub T);
+
+impl<'lt, U: Send + Sync + 'lt> Effective<'lt> for Value<U> {
+ fn into_erased<B>(self) -> ErasedEffective<'lt, Self::Output, Self::Effect, B> {
+ BoxOrReady::Ready(self.0)
+ }
+
+ type Effect = Async;
+
+ type Output = U;
+
+ type IntoFuture = core::future::Ready<U>;
+
+ fn into_future(self) -> Self::IntoFuture {
+ core::future::ready(self.0)
+ }
+
+ type Loop<'ctx: 'a, 'a, T: Send + Sync + 'a, F: Send + Sync + 'a>
+ = BoxOrReady<'a, (U, T)>
+ where
+ F: for<'b> FnMut(&'b mut Self::Output) -> ErasedEffective<'b, ControlFlow<T>, Self::Effect>,
+ 'lt: 'a;
+
+ fn r#loop<'ctx: 'a, 'a, T: Send + Sync + 'a, F: Send + Sync + 'a>(self, mut cb: F) -> Self::Loop<'ctx, 'a, T, F>
+ where
+ F: for<'b> FnMut(&'b mut Self::Output) -> ErasedEffective<'b, ControlFlow<T>, Self::Effect>,
+ 'lt: 'a,
+ {
+ BoxOrReady::Boxed(Box::pin(async move {
+ let mut this = self.into_future().await;
+
+ loop {
+ if let ControlFlow::Break(value) = cb(&mut this).into_future().await {
+ return (this, value);
+ }
+ }
+ }))
+ }
+
+ type Map<'a, T: Send + Sync + 'a, F: Send + Sync + 'a>
+ = Value<T>
+ where
+ F: FnOnce(Self::Output) -> T,
+ 'lt: 'a;
+
+ fn map<'a, T: Send + Sync + 'a, F: Send + Sync + 'a>(self, cb: F) -> Self::Map<'a, T, F>
+ where
+ F: FnOnce(Self::Output) -> T,
+ 'lt: 'a,
+ {
+ Value(cb(self.0))
+ }
+
+ type Then<'a, T: Send + Sync + 'a, V: Send + Sync + 'a, F: Send + Sync + 'a>
+ = V
+ where
+ F: FnOnce(Self::Output) -> V,
+ V: Effective<'a, Output = T, Effect = Self::Effect>,
+ 'lt: 'a;
+
+ fn then<'a, T: Send + Sync + 'a, V: Send + Sync + 'a, F: Send + Sync + 'a>(
+ self,
+ cb: F,
+ ) -> Self::Then<'a, T, V, F>
+ where
+ F: FnOnce(Self::Output) -> V,
+ V: Effective<'a, Output = T, Effect = Self::Effect>,
+ 'lt: 'a,
+ {
+ cb(self.0)
+ }
+
+ type AsCtx<'ctx: 'a, 'a, T: Send + Sync + 'a, F: Send + Sync + 'a>
+ = BoxOrReady<'a, (Self::Output, T)>
+ where
+ F: for<'b> FnOnce(&'b mut Self::Output) -> ErasedEffective<'b, T, Self::Effect, (&'b mut Self::Output, &'ctx ())>,
+ 'lt: 'a;
+
+ fn as_ctx<'ctx: 'a, 'a, T: Send + Sync + 'a, F: Send + Sync + 'a>(self, cb: F) -> Self::AsCtx<'ctx, 'a, T, F>
+ where
+ F: for<'b> FnOnce(&'b mut Self::Output) -> ErasedEffective<'b, T, Self::Effect, (&'b mut Self::Output, &'ctx ())>,
+ 'lt: 'a,
+ {
+ BoxOrReady::Boxed(Box::pin(async {
+ let mut this = self.0;
+
+ let result = cb(&mut this).into_future().await;
+
+ (this, result)
+ }))
+ }
+}