use core::marker::PhantomData;
pub trait InPipe {
type In<'message>;
}
pub trait OutPipe {
type Out<'message>;
}
pub trait Transport<Destination: InPipe> {
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>,
) -> Self::Outcome<'transport, 'message>;
}
pub trait MessageFamily {
type Message<'message>;
}
pub struct InPipeMessages<Selected: InPipe>(PhantomData<fn() -> Selected>);
impl<Selected: InPipe> MessageFamily for InPipeMessages<Selected> {
type Message<'message> = Selected::In<'message>;
}
pub struct OutPipeMessages<Selected: OutPipe>(PhantomData<fn() -> Selected>);
impl<Selected: OutPipe> MessageFamily for OutPipeMessages<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 ParticipantInPipe;
impl InPipe for ParticipantInPipe {
type In<'message> = &'message str;
}
struct ParticipantOutPipe;
impl OutPipe for ParticipantOutPipe {
type Out<'message> = &'message [u8];
}
#[test]
fn directional_pipe_message_families_remain_independent() {
fn accepts_input_only<Input: InPipe>() {}
fn emits_output_only<Output: OutPipe>() {}
fn assert_message_families<Input, Output>()
where
Input: InPipe,
Output: OutPipe,
for<'message> InPipeMessages<Input>:
MessageFamily<Message<'message> = Input::In<'message>>,
for<'message> OutPipeMessages<Output>:
MessageFamily<Message<'message> = Output::Out<'message>>,
{
}
accepts_input_only::<ParticipantInPipe>();
emits_output_only::<ParticipantOutPipe>();
assert_message_families::<ParticipantInPipe, ParticipantOutPipe>();
}
}