midi_toolkit/
lib.rs

1#![feature(coroutines)]
2#![feature(coroutine_trait)]
3#![feature(associated_type_defaults)]
4#![feature(type_alias_impl_trait)]
5#![feature(impl_trait_in_assoc_type)]
6
7use crossbeam_channel::{Receiver, RecvError};
8
9pub mod events;
10mod gen_iter;
11pub mod io;
12pub mod notes;
13pub mod num;
14pub mod sequence;
15
16#[macro_export]
17macro_rules! pipe {
18    ($var:tt |> $function: ident($($params: expr),*) $($calls:tt)*) => {
19        pipe!({$function($var, $($params),*)} $($calls)*)
20    };
21    ($var:tt |> $namespace1:ident :: $function: ident($($params: expr),*) $($calls:tt)*) => {
22        pipe!({$namespace1::$function($var, $($params),*)} $($calls)*)
23    };
24    ($var:tt |> $namespace1:ident :: < $($types: tt ),+ > :: $function: ident($($params: expr),*) $($calls:tt)*) => {
25        pipe!({$namespace1::<$($types,)+>::$function($var, $($params),*)} $($calls)*)
26    };
27    ($var:tt |> $namespace1:ident :: $namespace2:ident :: $function: ident($($params: expr),*) $($calls:tt)*) => {
28        pipe!({$namespace1::$namespace2::$function($var, $($params),*)} $($calls)*)
29    };
30    ($var:tt |> $namespace1:ident :: $namespace2:ident :: $namespace3:ident :: $function: ident($($params: expr),*) $($calls:tt)*) => {
31        pipe!({$namespace1::$namespace2::$namespace3::$function($var, $($params),*)} $($calls)*)
32    };
33    ($var:tt |> $namespace1:ident :: $namespace2:ident :: $namespace3:ident :: $namespace4:ident :: $function: ident($($params: expr),*) $($calls:tt)*) => {
34        pipe!({$namespace1::$namespace2::$namespace3::$namespace4::$function($var, $($params),*)} $($calls)*)
35    };
36    ($var:tt . $function: ident $( :: < $($types: tt $(< $types2: tt >)? ),* > )? ( $($params: expr),* ) $($calls:tt)*) => {
37        pipe!({$var.$function $( :: < $($types $(< $types2 >)?),* > )? ( $($params),* )} $($calls)*)
38    };
39    ($var:tt . $field: ident $($calls:tt)* ) => {
40        pipe!({ $var.$field } $($calls)*)
41    };
42    ($var:tt) => {
43        $var
44    };
45}
46
47#[macro_export(local_inner_macros)]
48macro_rules! unwrap {
49    ($val:expr) => {
50        match $val {
51            Ok(v) => v,
52            Err(e) => {
53                yield_error!(Err(e));
54            }
55        }
56    };
57}
58
59#[macro_export]
60macro_rules! yield_error {
61    ($err:expr) => {{
62        yield $err;
63        panic!("Iterator requested the next item after an error occured");
64    }};
65}
66
67pub struct DelayedReceiver<T> {
68    first: Option<Result<T, RecvError>>,
69    receiver: Receiver<T>,
70}
71
72impl<T> DelayedReceiver<T> {
73    pub fn new(receiver: Receiver<T>) -> Self {
74        Self {
75            first: None,
76            receiver,
77        }
78    }
79
80    pub fn wait_first(&mut self) {
81        if self.first.is_none() {
82            self.first = Some(self.receiver.recv());
83        }
84    }
85
86    pub fn recv(&mut self) -> Result<T, RecvError> {
87        if let Some(val) = self.first.take() {
88            val
89        } else {
90            self.receiver.recv()
91        }
92    }
93}
94
95#[cfg(test)]
96mod tests {
97    use super::*;
98
99    #[test]
100    fn test_delayed_receiver() {
101        let (sender, receiver) = crossbeam_channel::unbounded();
102        let mut receiver = DelayedReceiver::new(receiver);
103        {
104            let sender = sender;
105            sender.send(1).unwrap();
106            sender.send(2).unwrap();
107            sender.send(3).unwrap();
108            sender.send(4).unwrap();
109        }
110        receiver.wait_first();
111        assert_eq!(receiver.recv().unwrap(), 1);
112        assert_eq!(receiver.recv().unwrap(), 2);
113        assert_eq!(receiver.recv().unwrap(), 3);
114        assert_eq!(receiver.recv().unwrap(), 4);
115    }
116}