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 response = sans.start(&Request(&request_buf)).await;
    assert_eq!(response.response().unwrap().0, [2; 20]);

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

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

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

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

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

response_buf.fill(4);
assert!(io.handle(request, &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 SansResponse from the Io. Io starts sans task by using Io::start which returns IoRequest from Sans. The later communication is done using Sans::handle and Io::handle, which consume SansResponse and IoRequest.

See also more examples.

§Safety

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

Structs§

Io
Manages the Io part
IoRequest
The holder of the Request from the Sans to Io
Sans
Manages the Sans part
SansHandle
The Future helper for handling data between Io and Sans
SansResponse
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.