dewit is a library that allows the caller to control how code is
scheduled and executed separately from how data flows through it.
dewit is `#![no_std]`, no alloc, and `#![forbid(unsafe_code)]` by
default.
## Notes
Most of this is... at best semi-functional. I'm writing it on a private git
forge. You should probably not use this. Hopefully a future version will be more
fleshed out and less actively in flux. This is pretty heavily inspired by
chumsky's approach to... everything. They do it much better.
## Motivating example
dewit makes it possible to define code as a [`Task`](crate::task::Task)
with defined inputs and outputs, then request a specific execution mode.
```rust
use dewit::prelude::*;
use std::{fs::File, io, path::Path};
fn recursively_count_files<'a>() -> impl Task<'a, &'a Path, io::Result<usize>> {
// TODO: actually write this example :)
io(async move |path: &Path| {
tokio::time::sleep(std::time::Duration::from_secs(1)).await;
Ok(path.as_os_str().len())
})
}
#[tokio::main]
async fn main() -> io::Result<()> {
let (combinator_count, mode_count) =
// TODO: try_join
join(
recursively_count_files(),
recursively_count_files(),
)
.run_async((Path::new("./src/combinators"), Path::new("./src/mode")))
.await;
assert_eq!(combinator_count?, 17);
assert_eq!(mode_count?, 10);
Ok(())
}
```
Code which embeds a requirement to use a dependency, e.g.
[`rayon`](https://crates.io/crates/rayon) as part of its execution
"leaks" the usage of rayon into its environment, when the motivation of
the author may just be to execute more quickly. That can cause headaches
when a consumer doesn't want to potentially use all of their CPU.
Similarly, when writing code that consumes an async API, it can be a
headache to write an API for both the async and non-async versions of
the function when all the author wants is to block until the result is
available.
## Anti-motivation
An effort is made to be relatively efficient, but a hand-written
implementation that uses the underlying concurrency primitives in a
well-reasoned and careful way will likely be faster and use fewer
resources.
## Recommendations
Library dependents should avoid depending on any [`Mode`](crate::mode::Mode)
providing features unless strictly necessary, to avoid pulling in unnecessary
dependencies in client code.
## Feature flags
* `alloc`: Support for combinators which require allocation.
* `std`: Support for standard library features in combinators and modes.
* `async` (enables `alloc`): Provides an implementation of an async
[`Mode`](crate::mode::Mode), [`Async`](crate::mode::runtime::Async).
* `blocking` (enables `alloc`, `std`): Provides an implementation of a blocking
[`Mode`](crate::mode::Mode), [`Blocking`](crate::mode::runtime::Blocking).
* `rayon` (enables `alloc`, `std`): Provides implementations of work-stealing,
[`ScopedRayon`](crate::mode::runtime::ScopedRayon) and
[`Rayon`](crate::mode::runtime::Rayon). When `blocking` is enabled, additional
blocking versions of these will be available.