use crossbeam::channel as crossbeam; use std::sync::mpsc; pub trait Chan { const NAME: &'static str; type Tx: Sender; type Rx: Receiver; fn new(cap: Option) -> (Self::Tx, Self::Rx); } pub trait Sender: Send { fn _send(&mut self, value: T) -> Result<(), ()>; } pub trait Receiver { fn _recv(&mut self) -> Result; } // std::sync::mpsc impl_sender! { mpsc::Sender => send } impl_sender! { mpsc::SyncSender => send } impl_receiver! { mpsc::Receiver => recv } impl_chan! { StdMpsc(mpsc::SyncSender, mpsc::Receiver) => |cap| mpsc::sync_channel(cap.unwrap()) } impl_chan! { StdMpscUnbounded(mpsc::Sender, mpsc::Receiver) => |_cap| mpsc::channel() } // crossbeam::channel impl_sender! { crossbeam::Sender => send } impl_receiver! { crossbeam::Receiver => recv } impl_chan! { Crossbeam(crossbeam::Sender, crossbeam::Receiver) => |cap| crossbeam::bounded(cap.unwrap()) } impl_chan! { CrossbeamUnbounded(crossbeam::Sender, crossbeam::Receiver) => |_cap| crossbeam::unbounded() } // flume impl_sender! { flume::Sender => send } impl_receiver! { flume::Receiver => recv } impl_chan! { Flume(flume::Sender, flume::Receiver) => |cap| flume::bounded(cap.unwrap()) } impl_chan! { FlumeUnbounded(flume::Sender, flume::Receiver) => |_cap| flume::unbounded() } // firefly::spsc impl_sender! { firefly::spsc::Sender => send_blocking, firefly::spsc::UnboundedSender => send } impl_receiver! { firefly::spsc::Receiver => recv_blocking, firefly::spsc::UnboundedReceiver => recv_blocking } impl_chan! { FireflySpsc(firefly::spsc::Sender, firefly::spsc::Receiver) => |cap| firefly::spsc::bounded(cap.unwrap()) } impl_chan! { FireflySpscUnbounded(firefly::spsc::UnboundedSender, firefly::spsc::UnboundedReceiver) => |_cap| firefly::spsc::unbounded() } // firefly::mpsc impl_sender! { firefly::mpsc::Sender => send_blocking, firefly::mpsc::UnboundedSender => send } impl_receiver! { firefly::mpsc::Receiver => recv_blocking, firefly::mpsc::UnboundedReceiver => recv_blocking } impl_chan! { FireflyMpsc(firefly::mpsc::Sender, firefly::mpsc::Receiver) => |cap| firefly::mpsc::bounded(cap.unwrap()) } impl_chan! { FireflyMpscUnbounded(firefly::mpsc::UnboundedSender, firefly::mpsc::UnboundedReceiver) => |_cap| firefly::mpsc::unbounded() } // firefly::mpmc impl_sender! { firefly::mpmc::Sender => send_blocking, firefly::mpmc::UnboundedSender => send } impl_receiver! { firefly::mpmc::Receiver => recv_blocking, firefly::mpmc::UnboundedReceiver => recv_blocking } impl_chan! { FireflyMpmc(firefly::mpmc::Sender, firefly::mpmc::Receiver) => |cap| firefly::mpmc::bounded(cap.unwrap()) } impl_chan! { FireflyMpmcUnbounded(firefly::mpmc::UnboundedSender, firefly::mpmc::UnboundedReceiver) => |_cap| firefly::mpmc::unbounded() } // thingbuf::mpsc impl_sender! { thingbuf::mpsc::blocking::Sender => send } impl_receiver! { thingbuf::mpsc::blocking::Receiver => |x| x.recv().ok_or(()) } impl_chan! { ThingbufMpsc(thingbuf::mpsc::blocking::Sender, thingbuf::mpsc::blocking::Receiver) => |cap| thingbuf::mpsc::blocking::channel(cap.unwrap()) } macro_rules! impl_chan { ($chan:ident($tx:ty, $rx:ty) => |$cap:ident| $new:expr) => { pub struct $chan; impl Chan for $chan { const NAME: &'static str = stringify!($chan); type Tx = $tx; type Rx = $rx; fn new($cap: Option) -> (Self::Tx, Self::Rx) { $new } } }; } macro_rules! impl_receiver { ($($rx:ty => |$x:ident| $recv:expr),*) => { $(impl Receiver for $rx { fn _recv(&mut self) -> Result { let $x = self; $recv } })* }; ($($rx:ty => $recv:ident),*) => { $(impl_receiver! { $rx => |x| x.$recv().map_err(|e| panic!("{e:?}")) })* }; } macro_rules! impl_sender { ($($tx:ty => |$x:ident, $val:ident| $send:expr),*) => { $(impl Sender for $tx { fn _send(&mut self, $val: T) -> Result<(), ()> { let $x = self; $send } })* }; ($($tx:ty => $send:ident),*) => { $(impl_sender! { $tx => |x, val| x.$send(val).map_err(drop) })* }; } use {impl_chan, impl_receiver, impl_sender};