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}