[][src]Macro dialectic::offer

macro_rules! offer {
    (
        $chan:ident => $($t:tt)*
    ) => { ... };
    (
        @branches $branch:ident, $chan:ident, $code:expr $(,)?
    ) => { ... };
    (
        @branches $branch:ident, $chan:ident, $code:expr, $($t:tt)+
    ) => { ... };
    (
        @branches $branch:ident, $chan:ident, ? => $empty:expr $(,)?
    ) => { ... };
}

Offer a set of different protocols, allowing the other side of the channel to choose with which one to proceed. This macro only works in a Try context, i.e. somewhere the ? operator would make sense to use.

Notes

  • You must specify exactly as many branches as there are options in the type of the Offer to which this expression corresponds.
  • In the body of each branch, the identifier for the channel is rebound to have the session type corresponding to that branch.
  • To use offer! as an expression, ensure the type of every branch matches.

Examples

use dialectic::*;
use dialectic::constants::*;

type GiveOrTake = Choose<(Send<i64>, Recv<String>)>;

let (c1, c2) = GiveOrTake::channel(|| backend::mpsc::channel(1));

// Spawn a thread to offer a choice
let t1 = tokio::spawn(async move {
    offer! { c2 =>
        { c2.recv().await?; },
        { c2.send("Hello!".to_string()).await?; },
    }
    Ok::<_, backend::mpsc::Error>(())
});

// Choose to send an integer
c1.choose(_0).await?.send(42).await?;

// Wait for the offering thread to finish
t1.await??;

Errors

The generated code may result in the Transmit::Error of the underlying connection, as well as OutOfRangeChoice in the case where the other side of the connection breaks the protocol and selects a choice that does not exist. If the other side of the channel is also using this session type, that case is impossible.

Alternatively, you may specify an optional clause to handle protocol violations where the other side signals an invalid choice. In the example above, we could choose to immediately panic in that scenario:

offer! { c2 =>
    { c2.recv().await?; },
    { c2.send("Hello!".to_string()).await?; },
    ? => panic!("Protocol violation!"),
}