Skip to content

Commit

Permalink
Polish docs for backend
Browse files Browse the repository at this point in the history
  • Loading branch information
sdleffler committed Apr 13, 2021
1 parent 4890d62 commit 1baed3d
Showing 1 changed file with 27 additions and 21 deletions.
48 changes: 27 additions & 21 deletions dialectic/src/backend.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@
//! [`TransmitChoice`] and [`ReceiveChoice`]. These two pairs of traits are what need to be
//! implemented for a transport backend to function with Dialectic; if a custom backend for an
//! existing protocol is being implemented, [`TransmitChoice`] and [`ReceiveChoice`] do not
//! necessarily need to be implemented and can be left out as necessary/desired.
//! necessarily need to be implemented and can be left out as necessary/desired. Branching with
//! `offer` and `choose` can still be achieved with any type that implements the Vesta `Match`
//! trait, as long as that type can be transmitted or received by the backend in question.
//!
//! Functions which are generic over their backend will in turn need to specify the bounds
//! [`Transmit<T>`](Transmit) and [`Receive<T>`](Receive) for all `T`s they send and receive,
Expand Down Expand Up @@ -118,7 +120,8 @@ where

/// A trait describing how we can transmit a [`Choice<N>`](Choice) for any `N: usize`. If your
/// backend should be able to transmit any [`Choice<N>`](Choice), this is the trait to implement;
/// you'll get a blanket impl from it for `TransmitCase<Choice<N>>`.
/// you'll get a blanket impl from it for `TransmitCase<Choice<N>>`. Implementing this trait will
/// not allow your backend to [`Transmit`] a `Choice<N>`, but there is generally no reason to do so.
pub trait TransmitChoice: Transmitter {
/// Send a [`Choice<N>`](Choice) over the backend, for some `N`.
fn send_choice<'async_lifetime, const LENGTH: usize>(
Expand All @@ -136,9 +139,9 @@ pub trait TransmitChoice: Transmitter {
/// method. This matching/construction/deconstruction is done through the
/// [`vesta`](https://docs.rs/vesta) crate and its `Match` and `Case` traits; implementation of
/// these traits does not need to be done by hand as Vesta provides a derive macro for them.
///
/// You do not need to ever implement `TransmitCase`. It has blanket implementations for all types
/// that matter.
/// Similarly, [`TransmitCase`] never needs to be implemented by hand; blanket implementations are
/// provided to allow branching transmissions of `Choice<N>` for all `N` (when a backend supports
/// `TransmitChoice`) and `T: Match` (when a backend supports [`Transmit<T>`](Transmit).)
pub trait TransmitCase<T: ?Sized, C: Convention, const N: usize>:
Transmitter + sealed::TransmitCase<T, C>
where
Expand All @@ -156,7 +159,11 @@ where
}

/// This is a wrapper type which disambiguates, at the type level, "custom" choice types, and makes
/// sure Rust sees them as a different type from `Choice<N>`.
/// sure Rust sees them as a different type from `Choice<N>`. `CustomChoice` is an implementation
/// detail which is generated by the `Session!` macro when outputting [`Choose`](crate::Choose) and
/// [`Offer`](crate::Offer) types. If you see it in an error message, it means you wrote a `choose`
/// or `offer` statement with a custom carrier type, which is held as the type parameter to
/// `CustomChoice<T>`.
#[derive(Debug)]
pub struct CustomChoice<T>(pub T);

Expand Down Expand Up @@ -250,12 +257,10 @@ pub trait Receive<T>: Receiver {
) -> Pin<Box<dyn Future<Output = Result<T, Self::Error>> + Send + 'async_lifetime>>;
}

/// A trait describing how a receiver can receive a `Choice<N>` for any `N`. Implementing this trait
/// is sufficient to get a blanket impl of `ReceiveCase<Choice<N>>` for all `N` across your receiver
/// type.
///
/// [`ReceiveCase`] and [`ReceiveChoice`] exist due to current Rust limitations on quantifying over
/// const generics and type parameters; if we had rank-2 types, they would not be necessary.
/// A trait describing how we can receive a [`Choice<N>`](Choice) for any `N: usize`. If your
/// backend should be able to receive any [`Choice<N>`](Choice), this is the trait to implement;
/// you'll get a blanket impl from it for `ReceiveCase<Choice<N>>`. Implementing this trait will
/// not allow your backend to [`Receive`] a `Choice<N>`, but there is generally no reason to do so.
pub trait ReceiveChoice: Receiver {
/// Receive any `Choice<N>`. It is impossible to construct a `Choice<0>`, so if `N = 0`, a
/// [`Receiver::Error`] must be returned.
Expand All @@ -265,15 +270,16 @@ pub trait ReceiveChoice: Receiver {
}

/// A trait describing how a receiver can receive some `T` which can be matched on and has one or
/// more associated "cases". This casing/matching is done through the
/// [`vesta`](https://docs.rs/vesta) crate's [`Match`] and [`Case`] traits, which can be derived for
/// some types through Vesta's `Match` derive macro.
///
/// If you're writing a function and need a lot of different `ReceiveCase<T, C>` bounds, the
/// [`Receiver`](macro@crate::Receiver) attribute macro can help you specify them more succinctly.
///
/// You do not ever need to implement `ReceiveCase` yourself. Blanket implementations are provided
/// for all types that matter, and rely on `ReceiveChoice` and `Receive<T>`.
/// more associated "cases". [`ReceiveCase`] is highly similar to
/// [`Receive`], with a major difference: [`ReceiveCase`] may be used to send only *part* of an
/// `enum` datatype, as part of a [`Chan::choose`](crate::Chan::choose) call. This is because the
/// discriminant is actually the constant `N: usize` parameter to the [`ReceiveCase::send_case`]
/// method. This matching/construction/deconstruction is done through the
/// [`vesta`](https://docs.rs/vesta) crate and its `Match` and `Case` traits; implementation of
/// these traits does not need to be done by hand as Vesta provides a derive macro for them.
/// Similarly, [`ReceiveCase`] never needs to be implemented by hand; blanket implementations are
/// provided to allow branching transmissions of `Choice<N>` for all `N` (when a backend supports
/// `ReceiveChoice`) and `T: Match` (when a backend supports [`Receive<T>`](Receive).)
pub trait ReceiveCase<T>: Receiver
where
T: Match,
Expand Down

0 comments on commit 1baed3d

Please sign in to comment.