Skip to main content

midi_toolkit/
lib.rs

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