1trait ListenFn<P, N, R>: 'static + Send + Sync + Fn(P, Option<&N>) -> R {}
2
3impl<T, P, N, R> ListenFn<P, N, R> for T where
4 T: 'static + ?Sized + Send + Sync + Fn(P, Option<&N>) -> R
5{
6}
7
8pub struct Event<P, R> {
9 l: Listen<P, R>,
10}
11
12impl<P, R> Event<P, R> {
13 #[inline]
14 pub fn listen<F>(f: F) -> Listen<P, R>
15 where
16 F: Fn(P, Option<&Next<P, R>>) -> R + Send + Sync + 'static,
17 {
18 Listen::new(f)
19 }
20
21 #[inline]
22 pub fn fire(&self, args: P) -> R {
23 let n = self.l.next.as_ref().map(|n| n.as_ref());
24 (self.l.f)(args, n)
25 }
26}
27
28pub struct Next<P, R> {
29 l: Listen<P, R>,
30}
31
32impl<P, R> Next<P, R> {
33 #[inline]
34 fn new(l: Listen<P, R>) -> Self {
35 Self { l }
36 }
37
38 #[inline]
39 pub fn forward(&self, args: P) -> R {
40 let n = self.l.next.as_ref().map(|n| n.as_ref());
41 (self.l.f)(args, n)
42 }
43
44 #[inline]
45 fn link(&mut self, next: Self) {
46 if let Some(n) = self.l.next.as_mut() {
47 n.link(next);
48 } else {
49 self.l.next = Some(Box::new(next));
50 }
51 }
52}
53
54pub struct Listen<P, R> {
55 f: Box<dyn ListenFn<P, Next<P, R>, R>>,
56 next: Option<Box<Next<P, R>>>,
57}
58
59impl<P, R> Listen<P, R> {
60 #[inline]
61 fn new<F>(f: F) -> Self
62 where
63 F: Fn(P, Option<&Next<P, R>>) -> R + Send + Sync + 'static,
64 {
65 Self {
66 f: Box::new(f),
67 next: None,
68 }
69 }
70
71 #[inline]
72 pub fn listen<F>(mut self, f: F) -> Self
73 where
74 F: Fn(P, Option<&Next<P, R>>) -> R + Send + Sync + 'static,
75 {
76 let next = Next::new(Self::new(f));
77 if let Some(n) = self.next.as_mut() {
78 n.link(next);
79 } else {
80 self.next = Some(Box::new(next));
81 }
82 self
83 }
84
85 #[inline]
86 pub fn finish(self) -> Event<P, R> {
87 Event { l: self }
88 }
89}
90
91#[test]
92fn test_event() {
93 let simple1 = Event::<i32, i32>::listen(|args: i32, next| {
94 if args == 100 {
95 return args;
96 }
97 if let Some(next) = next {
98 next.forward(args)
99 } else {
100 1 * args
101 }
102 })
103 .listen(|args: i32, next| {
104 if args == 200 {
105 return args;
106 }
107 if let Some(next) = next {
108 next.forward(args)
109 } else {
110 2 * args
111 }
112 })
113 .listen(|args: i32, next| {
114 if args == 300 {
115 return args;
116 }
117 if let Some(next) = next {
118 next.forward(args)
119 } else {
120 3 * args
121 }
122 })
123 .finish();
124
125 assert_eq!(simple1.fire(10), 30);
126 assert_eq!(simple1.fire(100), 100);
127 assert_eq!(simple1.fire(300), 300);
128}
129
130#[test]
131fn test_event_single_listener() {
132 let event = Event::<i32, i32>::listen(|args, _next| args * 2).finish();
133
134 assert_eq!(event.fire(5), 10);
135 assert_eq!(event.fire(21), 42);
136}
137
138#[test]
139fn test_event_no_listener() {
140 let event = Event::<i32, i32>::listen(|args, next| {
142 assert!(next.is_none());
143 args * 3
144 })
145 .finish();
146
147 assert_eq!(event.fire(7), 21);
148}
149
150#[test]
151fn test_event_chained() {
152 let event = Event::<i32, i32>::listen(|args: i32, next| {
154 if let Some(next) = next {
155 next.forward(args + 1)
156 } else {
157 args
158 }
159 })
160 .listen(|args: i32, next| {
161 if let Some(next) = next {
162 next.forward(args + 2)
163 } else {
164 args
165 }
166 })
167 .listen(|args: i32, next| {
168 if let Some(next) = next {
169 next.forward(args + 3)
170 } else {
171 args
172 }
173 })
174 .listen(|args: i32, _next| args + 4)
175 .finish();
176
177 assert_eq!(event.fire(10), 20);
179 assert_eq!(event.fire(0), 10);
181}
182
183#[test]
184fn test_event_chain_broken() {
185 let event = Event::<i32, String>::listen(|args: i32, next| {
187 if let Some(next) = next {
188 next.forward(args)
189 } else {
190 "end".to_string()
191 }
192 })
193 .listen(|args: i32, _next| {
194 format!("broken at {}", args)
196 })
197 .listen(|_args: i32, _next| unreachable!("this listener should never be called"))
198 .finish();
199
200 assert_eq!(event.fire(42), "broken at 42");
201}
202
203#[test]
204fn test_event_with_data() {
205 let event = Event::<String, usize>::listen(|args: String, next| {
207 if let Some(next) = next {
208 next.forward(args)
209 } else {
210 args.len()
211 }
212 })
213 .listen(|args: String, _next| args.len() * 2)
214 .finish();
215
216 assert_eq!(event.fire("hello".to_string()), 10);
217 assert_eq!(event.fire("rust".to_string()), 8);
218}
219
220#[test]
221fn test_event_multiple_fire() {
222 let event = Event::<i32, i32>::listen(|args: i32, next| {
224 if let Some(next) = next {
225 next.forward(args * 2)
226 } else {
227 args
228 }
229 })
230 .listen(|args: i32, _next| args + 1)
231 .finish();
232
233 assert_eq!(event.fire(5), 11);
235 assert_eq!(event.fire(5), 11);
237 assert_eq!(event.fire(3), 7);
239 assert_eq!(event.fire(10), 21);
240}