use std::sync::mpsc::{
Receiver as MpscReceiver, SendError as MpscSendError, Sender as MpscSender,
TryRecvError as MpscReceiveError,
};
#[derive(Debug)]
pub struct SendError;
#[derive(Debug)]
pub enum ReceiveError {
Empty,
Disconnected,
}
pub trait Sender<M> {
fn send(&mut self, message: M) -> Result<(), SendError>;
}
pub trait Receiver<M> {
fn receive(&mut self) -> Result<M, ReceiveError>;
}
pub trait Communicator<SendMessage, ReceiveMessage>:
Sender<SendMessage> + Receiver<ReceiveMessage>
{
}
impl<T, SendMessage, ReceiveMessage> Communicator<SendMessage, ReceiveMessage> for T where
T: Sender<SendMessage> + Receiver<ReceiveMessage>
{
}
pub struct SimpleCommunicator<S, R> {
sender: S,
receiver: R,
}
impl<S, R> SimpleCommunicator<S, R> {
pub fn new(sender: S, receiver: R) -> Self {
Self { sender, receiver }
}
#[inline]
fn send<M>(&mut self, message: M) -> Result<(), SendError>
where
S: Sender<M>,
{
self.sender.send(message)
}
#[inline]
fn receive<M>(&mut self) -> Result<M, ReceiveError>
where
R: Receiver<M>,
{
self.receiver.receive()
}
}
impl<S, R, M> Sender<M> for SimpleCommunicator<S, R>
where
S: Sender<M>,
{
#[inline]
fn send(&mut self, message: M) -> Result<(), SendError> {
Self::send(self, message)
}
}
impl<S, R, M> Receiver<M> for SimpleCommunicator<S, R>
where
R: Receiver<M>,
{
#[inline]
fn receive(&mut self) -> Result<M, ReceiveError> {
Self::receive(self)
}
}
impl<M> Sender<M> for MpscSender<M> {
#[inline]
fn send(&mut self, message: M) -> Result<(), SendError> {
Ok(MpscSender::send(self, message)?)
}
}
impl<M> Receiver<M> for MpscReceiver<M> {
#[inline]
fn receive(&mut self) -> Result<M, ReceiveError> {
Ok(self.try_recv()?)
}
}
impl<T> From<MpscSendError<T>> for SendError {
fn from(_err: MpscSendError<T>) -> SendError {
SendError
}
}
impl From<MpscReceiveError> for ReceiveError {
fn from(err: MpscReceiveError) -> ReceiveError {
match err {
MpscReceiveError::Empty => ReceiveError::Empty,
MpscReceiveError::Disconnected => ReceiveError::Disconnected,
}
}
}
#[cfg(feature = "data-stream")]
mod general {
use super::{ReceiveError, Receiver, SendError, Sender};
use data_stream::{from_stream, to_stream, FromStream, ReadError, ToStream};
use std::{
io::{Read, Write},
marker::PhantomData,
};
pub struct StreamCommunicator<S, T> {
stream: T,
settings: PhantomData<S>,
}
impl<S, T> StreamCommunicator<S, T> {
pub fn new(stream: T) -> Self {
Self {
stream,
settings: PhantomData,
}
}
}
impl<S, M: ToStream<S>, W: Write> Sender<M> for StreamCommunicator<S, W> {
#[inline]
fn send(&mut self, message: M) -> Result<(), SendError> {
match to_stream(&message, &mut self.stream) {
Ok(value) => Ok(value),
Err(_) => Err(SendError),
}
}
}
impl<S, M: FromStream<S>, R: Read> Receiver<M> for StreamCommunicator<S, R> {
#[inline]
fn receive(&mut self) -> Result<M, ReceiveError> {
match from_stream::<_, M, _>(&mut self.stream) {
Ok(value) => Ok(value),
Err(err) => Err(match err {
ReadError::Stream => ReceiveError::Disconnected,
ReadError::Invalid => ReceiveError::Empty,
}),
}
}
}
}
#[cfg(feature = "data-stream")]
pub use general::*;