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}