use core::marker::PhantomData;
pub trait Participant {
type In<'message>;
type Out<'message>;
}
pub enum NoInput {}
pub enum NoOutput {}
pub trait Transport<Destination: Participant> {
type Outcome<'transport, 'message>
where
Self: 'transport;
#[must_use = "transport outcomes must be routed or settled"]
fn transport<'transport, 'message>(
&'transport mut self,
input: Destination::In<'message>,
turn: &mut crate::TurnContext<impl crate::TurnObserver>,
) -> Self::Outcome<'transport, 'message>;
}
pub trait MessageFamily {
type Message<'message>;
}
pub struct ParticipantIn<Selected: Participant>(PhantomData<fn() -> Selected>);
impl<Selected: Participant> MessageFamily for ParticipantIn<Selected> {
type Message<'message> = Selected::In<'message>;
}
pub struct ParticipantOut<Selected: Participant>(PhantomData<fn() -> Selected>);
impl<Selected: Participant> MessageFamily for ParticipantOut<Selected> {
type Message<'message> = Selected::Out<'message>;
}
pub struct OwnedMessage<Message>(PhantomData<fn() -> Message>);
impl<Message> MessageFamily for OwnedMessage<Message> {
type Message<'message> = Message;
}
#[derive(Clone, Copy, Debug, Eq, Ord, PartialEq, PartialOrd)]
pub struct EncodedByteCount(usize);
impl EncodedByteCount {
pub const fn new(value: usize) -> Self {
Self(value)
}
pub const fn get(self) -> usize {
self.0
}
}
pub trait MessageEncoder {
type Message<'message>: ?Sized;
type Error;
fn encode<'message>(
&self,
message: &Self::Message<'message>,
destination: &mut [u8],
) -> Result<EncodedByteCount, Self::Error>;
}
pub trait MessageDecoder {
type Message<'frame>;
type Error;
fn decode<'frame>(&self, frame: &'frame mut [u8])
-> Result<Self::Message<'frame>, Self::Error>;
}
#[cfg(test)]
mod tests {
use super::*;
struct Participant;
impl super::Participant for Participant {
type In<'message> = &'message str;
type Out<'message> = &'message [u8];
}
struct Source;
impl super::Participant for Source {
type In<'message> = NoInput;
type Out<'message> = &'message str;
}
struct Sink;
impl super::Participant for Sink {
type In<'message> = &'message str;
type Out<'message> = NoOutput;
}
struct BorrowedInline;
impl Transport<Participant> for BorrowedInline {
type Outcome<'transport, 'message>
= &'message str
where
Self: 'transport;
fn transport<'transport, 'message>(
&'transport mut self,
input: <Participant as super::Participant>::In<'message>,
_turn: &mut crate::TurnContext<impl crate::TurnObserver>,
) -> Self::Outcome<'transport, 'message> {
input
}
}
#[test]
fn participant_message_families_include_uninhabited_directions() {
fn assert_message_families<Selected>()
where
Selected: super::Participant,
for<'message> ParticipantIn<Selected>:
MessageFamily<Message<'message> = Selected::In<'message>>,
for<'message> ParticipantOut<Selected>:
MessageFamily<Message<'message> = Selected::Out<'message>>,
{
}
assert_message_families::<Participant>();
assert_message_families::<Source>();
assert_message_families::<Sink>();
}
#[test]
fn encoded_byte_counts_preserve_their_value() {
assert_eq!(EncodedByteCount::new(7).get(), 7);
}
#[test]
fn transports_without_internal_steps_preserve_observed_delivery() {
let mut transport = BorrowedInline;
let mut turn = crate::TurnContext::new(crate::NoopTurnObserver);
assert_eq!(
Transport::<Participant>::transport(&mut transport, "borrowed", &mut turn),
"borrowed"
);
}
}