Crate asansio

Crate asansio 

Source
Expand description

§asansio

This library contains the async/await state machine for the sans-io design pattern. 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.

This crate could be used also for non network protocol cases, everywhere there is a need for creating a state machine.

This is no_std crate and it doesn’t allocate on the heap.

§Usage

See this simple example:

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());

This 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. There are two types to manage them: the Io and the Sans, which are constructed by the new function. These two parts communicate using Request and Respond types, which are defined by the user (for real scenarios they could be enums).

Sans starts communicating with Io using Sans::start and providing the initial Request; it returns the SansHandle from the Io. Io starts sans task by using Io::start which returns IoHandle from Sans. The later communication is done using Sans::handle and Io::handle, which consume SansHandle and IoHandle.

See also more examples.

§Safety

The crate uses unsafe parts for preparing a proper async/await infrastructure. Safety is guaranteed by consuming the latest IoHandle and SansHandle - these handlers store Request and Response objects and their lifetime is limited to the adjecent calls.

Structs§

Io
Manages the Io part
IoHandle
The holder of the Request from the Sans to Io
Sans
Manages the Sans part
SansHandle
The holder of the Response from the Io to Sans

Functions§

new
Creates a two parts: Sans and Io for the specified Request and Response.