Skip to main content

Crate hibana

Crate hibana 

Expand description

Hibana is a Rust 2024 no_std / no-alloc-oriented runtime for affine multiparty session types.

The crate intentionally has two faces:

Everything starts from one global choreography and ends in a small localside endpoint:

g choreography -> project role program -> attach endpoint -> drive localside

§App path

Application code writes choreography with g and drives an endpoint that a protocol crate has already attached.

use hibana::g;

let app = g::seq(
    g::send::<0, 1, g::Msg<1, u32>>(),
    g::send::<1, 0, g::Msg<2, u32>>(),
);

endpoint.send::<g::Msg<1, u32>>(&7).await?;
let reply = endpoint.recv::<g::Msg<2, u32>>().await?;

The localside API is deliberately small:

A route branch whose selected arm begins with a send is handled by RouteBranch::send. Dropping the returned future restores the branch preview before any progress commits. Successful sends, receives, and route branch first-step operations consume progress.

let branch = endpoint.offer().await?;
match branch.label() {
    10 => {
        let value = branch.recv::<g::Msg<10, [u8; 4]>>().await?;
    }
    11 => {
        branch.send::<g::Msg<11, ()>>(&()).await?;
    }
    label => panic!("unexpected route label {label}"),
}

§Protocol path

Protocol crates compose prefixes around an app choreography, project a role-local witness, bind transport state, and return an attached endpoint.

use hibana::{g, runtime};
use hibana::runtime::program::{RoleProgram, project};

let program = g::seq(transport_prefix, app);
let role0: RoleProgram<0> = project(&program);

let mut slab = [0u8; 4096];
let mut kit_storage = runtime::SessionKitStorage::<MyTransport>::uninit();
let kit = kit_storage.init();
let rv = kit.rendezvous(&mut slab, transport)?;
let endpoint = rv.enter(sid, &role0)?;

Runtime capacities are derived from Hibana’s wire/domain limits and projected descriptors, not chosen by callers. Hidden timeout fuses are not protocol API or attach config. Protocol-invisible carrier watchdogs live inside the transport implementation: terminal I/O waits are reported as runtime::transport::TransportError from poll_send or poll_recv, not as Hibana timeout branches.

runtime::transport::Transport owns I/O readiness, wire buffers, and ingress demux evidence. runtime::resolver owns dynamic resolver input. None of those layers become app concepts.

§Payloads, receive evidence, and resolvers

Payload types implement runtime::wire::WireEncode for sends and runtime::wire::WirePayload for receives. Decoded values may borrow from the received frame. Built-in exact codecs cover (), integers, bool, byte slices, and fixed byte arrays.

Branch choice is either an in-band protocol message, a projected first visible endpoint operation confirmed by descriptor-checked receive evidence, or an explicit resolver decision. Transport evidence is descriptor evidence only; it is not route authority and it does not create a public branch-authority catalogue.

§Boundary contract

Hibana keeps the public API small because the projection boundary carries the proof work:

  • route shape, ambiguous simultaneous endpoint operations, and intrinsic route controller mismatch are rejected before runtime;
  • parallel composition rejects empty arms and ambiguous simultaneous endpoint operations;
  • labels are choreography identities, while transport frame labels are descriptor facts;
  • endpoint progress is affine: successful sends, receives, and route branch first-step operations commit progress, while dropped previews restore the endpoint;
  • EndpointError fails closed, carries compact endpoint operation evidence, and never authorizes hidden progress.

Modules§

g
Choreography language used by app authors.
runtime
Runtime surface for protocol implementors. Protocol-neutral runtime surface for protocol implementors.

Structs§

Endpoint
App-facing affine executor for a projected role.
EndpointError
Domain error for endpoint progress.
RouteBranch
Preview of a selected route branch returned by Endpoint::offer.