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}