1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111
//! Rust crate to help perform deferred execution of code logic.
//!
//! # Problems that `deferred` crate helps to solve
//! Probably at some point in your project you will want to make a function that can have
//! partitioned logic and you want to call each of that parts at some strictly defined time
//! specified by you.
//! ```
//! # #[macro_use] extern crate deferred;
//! # use deferred::*;
//! # fn main() {
//! fn foo(v: i32) -> Deferred<i32> {
//! deferred!(v, [
//! |c| state!(c.state() + 1),
//! |c| foo2(c.state()).into(),
//! |c| state!(c.state() + 2)
//! ])
//! }
//!
//! fn foo2(v: i32) -> Deferred<i32> {
//! deferred!(v, [
//! |c| state!(c.state() * 2),
//! |c| state!(c.state() * 3)
//! ])
//! }
//!
//! let d = foo(1);
//! assert_eq!(d.state(), Some(&1));
//! let d = d.resume().unwrap();
//! assert_eq!(d.state(), Some(&2));
//! let d = d.resume().unwrap();
//! assert_eq!(d.state(), Some(&4));
//! let d = d.resume().unwrap();
//! assert_eq!(d.state(), Some(&12));
//! let d = d.resume().unwrap();
//! assert_eq!(d.state(), Some(&14));
//! assert_eq!(d.can_resume(), false);
//! # }
//! ```
//!
//! You can think of it as staticaly defined `Promise`-like abstraction known in JavaScript or
//! other languages with high abstraction of deferred code execution.
//!
//! # It is not based on threads
//! Main reason that this crate was created is that when you work with WASM target, you cannot use
//! `Futures` or threads but you still need to run some of your code asynchronously, most likely
//! execute heavy/long calculations "in background" and you cannot make browser freeze.
//!
//! # Need to use undefined state type? Look, there is `Value` wrapper!
//! Sometimes you cannot have the same context input and output types, for example:
//! ```ignore
//! fn foo(v: i32) -> Deferred<String> {
//! deferred!(v, [
//! |c| state!(c.state() + 1),
//! |c| state!(format!("{}", c.state()))
//! ])
//! }
//!
//! let result: String = foo(42).consume();
//! ```
//! Code above gets `i32` as input and expects that at the end we get `String` value and it does
//! not compile. You could solve it by making tuple with options of each types used in context
//! inputs and outputs, like this:
//! ```
//! # #[macro_use] extern crate deferred;
//! # use deferred::*;
//! # fn main() {
//! type State = (Option<i32>, Option<String>);
//!
//! fn foo(v: i32) -> Deferred<State> {
//! deferred!((Some(v), None), [
//! |c| state!((Some(c.state().0.unwrap() + 1), None)),
//! |c| state!((None, Some(format!("{}", c.state().0.unwrap()))))
//! ])
//! }
//!
//! let result = foo(41).consume().1.unwrap();
//! assert_eq!(&result, "42");
//! # }
//! ```
//! but this looks ugly and gets even worse when you have much much more types to use - we do not
//! want that. We can use `Value` type which is basically a boxed wrapper of any value (that means:
//! you have to deal with a little runtime overhead because of storing and accessing value on heap).
//!
//! Here is how to use `Value` as state:
//! ```
//! # #[macro_use] extern crate deferred;
//! # use deferred::*;
//! # fn main() {
//! fn foo(v: i32) -> Deferred<Value> {
//! deferred!(value!(v), [
//! |c| state!(value!(c.state().consume::<i32>() + 1)),
//! |c| state!(value!(format!("{}", c.state().consume::<i32>())))
//! ])
//! }
//!
//! let result = foo(41).consume().consume::<String>();
//! assert_eq!(&result, "42");
//! # }
//! ```
pub mod context;
pub mod deferred;
pub mod deferred_manager;
mod macros;
mod tests;
pub mod value;
pub use crate::context::*;
pub use crate::deferred::*;
pub use crate::deferred_manager::*;
pub use crate::value::*;