linkk/lib.rs
1//! This crate is real simple, if makes a set of channels and criss-crosses them.
2//!
3//! I find myself using this pattern a bit lately to get... things that're hard to get talking to
4//! eachother talking to eachother.
5//! There is probably a better way -- but, I don't know it.
6//!
7//! Conceptually, I think of it as making a bridge, it needn't send the same `<T>` across,
8//! infact you can put all sorts of things in there.. I know, I have.
9//!
10//!
11//!```rust
12//!use linkk;
13//!linkk::setup_linkk!(pub, Window2os<u32>, Os2Window<u64>);
14//!
15//!let (w2os, os2w) = make_new_linkk();
16//!// link2 receives from link1
17//!w2os.send(42).unwrap();
18//!assert_eq!(os2w.recv().unwrap(), 42u32);
19//!
20//!// link1 receives from link2
21//!os2w.tx.send(43 as u64).unwrap();
22//!assert_eq!(w2os.rx.recv().unwrap(), 43);
23//! ```
24//!
25//! ## Which should save you typing that alernative which would be all this:
26//!
27//! ```
28//!pub struct Link1 {
29//! tx: std::sync::mpsc::Sender<u32>,
30//! rx: std::sync::mpsc::Receiver<u64>,
31//!}
32//!pub struct Link2 {
33//! tx: std::sync::mpsc::Sender<u64>,
34//! rx: std::sync::mpsc::Receiver<u32>,
35//!}
36//!impl Link1 {
37//! fn send(&self, t: u32) -> std::result::Result<(), std::sync::mpsc::SendError<u32>> {
38//! self.tx.send(t)
39//! }
40//!
41//! fn recv(&self) -> Result<u64, std::sync::mpsc::RecvError> {
42//! self.rx.recv()
43//! }
44//!}
45//!
46//!impl Link2 {
47//! fn send(&self, t: u64) -> std::result::Result<(), std::sync::mpsc::SendError<u64>> {
48//! self.tx.send(t)
49//! }
50//!
51//! fn recv(&self) -> Result<u32, std::sync::mpsc::RecvError> {
52//! self.rx.recv()
53//! }
54//!}
55//!fn init() {
56//! let (tx1, rx1) = std::sync::mpsc::channel::<u32>();
57//! let (tx2, rx2) = std::sync::mpsc::channel::<u64>();
58//!
59//! let link1 = Link1 { tx: tx1, rx: rx2 };
60//! let link2 = Link2 { tx: tx2, rx: rx1 };
61//!}
62//!```
63//! See the tests for example usage.
64
65#[macro_export]
66macro_rules! setup_linkk {
67 ($v:vis, $struct1:ident<$t:ty>, $struct2:ident<$t2:ty>) => {
68 //
69 $v struct $struct1 {
70 $v tx: std::sync::mpsc::Sender<$t>,
71 $v rx: std::sync::mpsc::Receiver<$t2>,
72 }
73
74 $v struct $struct2 {
75 $v tx: std::sync::mpsc::Sender<$t2>,
76 $v rx: std::sync::mpsc::Receiver<$t>,
77 }
78
79 impl $struct1 {
80 $v fn send(&self, t: $t) -> std::result::Result<(), std::sync::mpsc::SendError<$t>> {
81 self.tx.send(t)
82 }
83
84 $v fn recv(&self) -> Result<$t2, std::sync::mpsc::RecvError> {
85 self.rx.recv()
86 }
87
88 pub fn new(tx: std::sync::mpsc::Sender<$t>, rx: std::sync::mpsc::Receiver<$t2>)-> Self {
89 Self {
90 tx,
91 rx
92 }
93 }
94 }
95
96 impl $struct2 {
97 $v fn send(&self, t: $t2) -> std::result::Result<(), std::sync::mpsc::SendError<$t2>> {
98 self.tx.send(t)
99 }
100
101 $v fn recv(&self) -> Result<$t, std::sync::mpsc::RecvError> {
102 self.rx.recv()
103 }
104
105 pub fn new(tx: std::sync::mpsc::Sender<$t2>, rx: std::sync::mpsc::Receiver<$t>)-> Self {
106 Self {
107 tx,
108 rx
109 }
110 }
111
112 }
113
114 pub fn make_new_linkk() -> ($struct1, $struct2) {
115 let (tx1, rx1) = std::sync::mpsc::channel::<$t>();
116 let (tx2, rx2) = std::sync::mpsc::channel::<$t2>();
117
118 ($struct1 { tx: tx1, rx: rx2 }, $struct2 { tx: tx2, rx: rx1 })
119 }
120 //
121 };
122}
123
124#[cfg(test)]
125mod tests {
126 use super::*;
127
128 #[test]
129 fn test_link_macro() {
130 setup_linkk!(pub, Window2os<u32>, Os2Window<u64>);
131
132 let (link2, link1) = make_new_linkk();
133
134 // link2 receives from link1
135 link2.send(42).unwrap();
136 assert_eq!(link1.recv().unwrap(), 42u32);
137
138 // link1 receives from link2
139 link1.tx.send(43 as u64).unwrap();
140 assert_eq!(link2.rx.recv().unwrap(), 43);
141 }
142}