radiate_core/domain/sync/
channel.rs1use crossbeam::channel;
2
3pub struct CommandChannel<T> {
4 sender: channel::Sender<T>,
5 receiver: channel::Receiver<T>,
6}
7
8impl<T> CommandChannel<T> {
9 pub fn new() -> Self {
10 let (tx, rx) = crossbeam::channel::unbounded();
11 Self {
12 sender: tx,
13 receiver: rx,
14 }
15 }
16
17 pub fn dispatcher(&self) -> channel::Sender<T> {
18 self.sender.clone()
19 }
20
21 pub fn next(&self) -> Result<T, channel::RecvError> {
22 self.receiver.recv()
23 }
24}
25
26impl<T> Default for CommandChannel<T> {
27 fn default() -> Self {
28 Self::new()
29 }
30}
31
32impl<T> Iterator for CommandChannel<T> {
33 type Item = T;
34
35 fn next(&mut self) -> Option<Self::Item> {
36 self.receiver.recv().ok()
37 }
38}
39
40pub trait IntoPair<T> {
41 fn into_pair(self) -> (T, T);
42}
43
44impl<T> IntoPair<channel::Sender<T>> for channel::Sender<T> {
45 fn into_pair(self) -> (channel::Sender<T>, channel::Sender<T>) {
46 (self.clone(), self)
47 }
48}
49
50#[cfg(test)]
51mod tests {
52 use super::*;
53
54 #[test]
55 fn test_command_channel() {
56 let channel: CommandChannel<i32> = CommandChannel::new();
57 let dispatcher = channel.dispatcher();
58 dispatcher.send(42).unwrap();
59 assert_eq!(channel.next().unwrap(), 42);
60 }
61
62 #[test]
63 fn test_command_channel_iterator() {
64 let channel: CommandChannel<i32> = CommandChannel::new();
65 let dispatcher = channel.dispatcher();
66 dispatcher.send(1).unwrap();
67 dispatcher.send(2).unwrap();
68
69 for (i, value) in channel.into_iter().enumerate() {
70 assert_eq!(value, (i + 1) as i32);
71 if i == 1 {
72 break;
73 }
74 }
75 }
76}