| Crates.io | dewit |
| lib.rs | dewit |
| version | 0.0.1 |
| created_at | 2025-11-02 05:55:44.783389+00 |
| updated_at | 2025-11-02 05:55:44.783389+00 |
| description | Define scheduling and execution of code separately from data flow |
| homepage | |
| repository | |
| max_upload_size | |
| id | 1912709 |
| size | 52,096 |
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.
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.
dewit makes it possible to define code as a Task
with defined inputs and outputs, then request a specific execution mode.
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 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.
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.
Library dependents should avoid depending on any Mode
providing features unless strictly necessary, to avoid pulling in unnecessary
dependencies in client code.
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, Async.
blocking (enables alloc, std): Provides an implementation of a blocking
Mode, Blocking.
rayon (enables alloc, std): Provides implementations of work-stealing,
ScopedRayon and
Rayon. When blocking is enabled, additional
blocking versions of these will be available.