| Crates.io | asansio |
| lib.rs | asansio |
| version | 0.2.0 |
| created_at | 2025-10-06 19:35:24.549467+00 |
| updated_at | 2025-12-25 21:32:34.544478+00 |
| description | The Async/await state machine for the Sans I/O design pattern |
| homepage | |
| repository | https://github.com/ewienik/asansio |
| max_upload_size | |
| id | 1870728 |
| size | 69,085 |
Async/await state machine for the Sans I/O design pattern.
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.
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.
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.
Licensed under either of
at your option.