asansio

Crates.ioasansio
lib.rsasansio
version0.2.0
created_at2025-10-06 19:35:24.549467+00
updated_at2025-12-25 21:32:34.544478+00
descriptionThe Async/await state machine for the Sans I/O design pattern
homepage
repositoryhttps://github.com/ewienik/asansio
max_upload_size
id1870728
size69,085
Pawel Pery (ewienik)

documentation

README

asansio

Async/await state machine for the Sans I/O design pattern.

crates.io docs.rs

The Idea

This crate is a experiment for Sans I/O in Rust (see sans I/O for network protocols documentation to familiar with the concept). Writing network protocol without performing I/O operations means creating a state machine. Manually creating a state machine could be a tedious process. As Rust async/await concept is an actual state machine with implicit states created during compilation, this library is an experiment with using async/await to provide such state machine automatically. Let's check if this is good solution to the problem.

Dependency

It is no_std crate without allocations on the heap. It depends only on the core, no other crates. Only examples uses std, clap and tokio as dev-dependencies.

Usage

struct Request<'a>(&'a [u8]);
struct Response<'a>(&'a [u8]);

async fn sans_task<'a>(sans: Sans<Request<'a>, Response<'a>>) {
    let mut request_buf = [1u8; 10];
    let handle = sans.start(&Request(&request_buf)).await;
    assert_eq!(handle.message().unwrap().0, [2; 20]);

    request_buf.fill(3);
    let handle = sans.handle(handle, &Request(&request_buf)).await;
    assert_eq!(handle.message().unwrap().0, [4; 20]);
}

let (sans, io) = asansio::new();

let task = pin!(sans_task(sans));

let handle = io.start(task).unwrap();
assert_eq!(handle.message().unwrap().0, [1; 10]);

let mut response_buf = [2; 20];
let handle = io.handle(handle, &Response(&response_buf)).unwrap();
assert_eq!(handle.message().unwrap().0, [3; 10]);

response_buf.fill(4);
assert!(io.handle(handle, &Response(&response_buf)).is_none());

The crate divides a problem into two parts. The first Sans takes care of the state machine independent of the I/O and the second Io is responsible with I/O communication. These two parts communicate using Request and Respond types, which are defined by the user (for real scenarios they could be enums).

See also more examples.

License

Licensed under either of

at your option.

Commit count: 0

cargo fmt