Skip to content
Oeiuwq Faith Blog OpenSource Porfolio

ewienik/asansio

Async/await state machine lite framework for sans-io functionality

ewienik/asansio.json
{
"createdAt": "2025-09-09T21:54:50Z",
"defaultBranch": "master",
"description": "Async/await state machine lite framework for sans-io functionality",
"fullName": "ewienik/asansio",
"homepage": null,
"language": "Rust",
"name": "asansio",
"pushedAt": "2026-05-30T16:04:52Z",
"stargazersCount": 9,
"topics": [],
"updatedAt": "2026-05-30T15:45:20Z",
"url": "https://github.com/ewienik/asansio"
}

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

crates.io docs.rs

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([u8; 10]);
struct Response([u8; 20]);
async fn sans_task(sans: Sans<Request, Response>) {
let mut request_buf = [1u8; 10];
let response = sans.handle(Request(request_buf)).await;
assert_eq!(response.0, [2; 20]);
request_buf.fill(3);
let response = sans.handle(Request(request_buf)).await;
assert_eq!(response.0, [4; 20]);
}
let (sans, io) = asansio::new();
let task = pin!(sans_task(sans));
let (handle, request) = io.start(task).unwrap();
assert_eq!(request.0, [1; 10]);
let mut response_buf = [2; 20];
let (handle, request) = io.handle(handle, Response(response_buf)).unwrap();
assert_eq!(request.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]!(examples).

Licensed under either of

at your option.