1use std::marker::PhantomData;
8
9use crate::simulation;
10use crate::simulation::Point;
11use crate::simulation::event::*;
12use crate::simulation::observable::disposable::*;
13
14#[inline]
16pub fn return_composite<T>(val: T) -> Return<T> {
17 Return { val: val }
18}
19
20#[inline]
22pub fn delay_composite<F, M>(f: F) -> Delay<F, M>
23 where F: FnOnce() -> M,
24 M: Composite
25{
26 Delay { f: f, _phantom: PhantomData }
27}
28
29#[inline]
31pub fn cons_composite<F, T>(f: F) -> Cons<F, T>
32 where F: FnOnce(DisposableBox, &Point) -> simulation::Result<(T, DisposableBox)>
33{
34 Cons { f: f, _phantom: PhantomData }
35}
36
37#[inline]
39pub fn disposable_composite<D>(action: D) -> DisposableComposite<D>
40 where D: Disposable + 'static
41{
42 DisposableComposite { action: action }
43}
44
45#[inline]
47pub fn composite_sequence<I, M>(comps: I) -> Sequence<I::IntoIter, M>
48 where I: IntoIterator<Item = M>,
49 M: Composite
50{
51 Sequence { comps: comps.into_iter(), _phantom: PhantomData }
52}
53
54#[inline]
56pub fn composite_sequence_<I, M>(comps: I) -> Sequence_<I::IntoIter, M>
57 where I: IntoIterator<Item = M>,
58 M: Composite
59{
60 Sequence_ { comps: comps.into_iter(), _phantom: PhantomData }
61}
62
63#[inline]
65pub fn trace_composite<M>(msg: String, comp: M) -> Trace<M>
66 where M: Composite
67{
68 Trace { comp: comp, msg: msg}
69}
70
71pub trait Composite {
73
74 type Item;
76
77 #[doc(hidden)]
79 fn call_composite(self, disposable: DisposableBox, p: &Point) -> simulation::Result<(Self::Item, DisposableBox)>;
80
81 #[inline]
83 fn and_then<U, F>(self, f: F) -> AndThen<Self, U, F>
84 where Self: Sized,
85 U: Composite,
86 F: FnOnce(Self::Item) -> U,
87 {
88 AndThen { comp: self, f: f, _phantom: PhantomData }
89 }
90
91 #[inline]
93 fn map<B, F>(self, f: F) -> Map<Self, B, F>
94 where Self: Sized,
95 F: FnOnce(Self::Item) -> B,
96 {
97 Map { comp: self, f: f, _phantom: PhantomData }
98 }
99
100 #[inline]
102 fn zip<U>(self, other: U) -> Zip<Self, U>
103 where Self: Sized,
104 U: Composite
105 {
106 Zip { comp: self, other: other }
107 }
108
109 #[inline]
111 fn ap<U, B>(self, other: U) -> Ap<Self, U, B>
112 where Self: Sized,
113 Self::Item: FnOnce(U::Item) -> B,
114 U: Composite
115 {
116 Ap { comp: self, other: other, _phantom: PhantomData }
117 }
118
119 #[inline]
121 fn into_boxed(self) -> CompositeBox<Self::Item>
122 where Self: Sized + 'static
123 {
124 CompositeBox::new(move |disposable, p: &Point| { self.call_composite(disposable, p) })
125 }
126
127 #[inline]
129 fn run<D>(self, disposable: D) -> Run<Self, D>
130 where Self: Sized,
131 D: Disposable + 'static
132 {
133 Run { comp: self, disposable: disposable }
134 }
135
136 #[inline]
138 fn run_(self) -> Run_<Self>
139 where Self: Sized
140 {
141 Run_ { comp: self }
142 }
143}
144
145pub trait IntoComposite {
147
148 type Composite: Composite<Item = Self::Item>;
150
151 type Item;
153
154 fn into_composite(self) -> Self::Composite;
156}
157
158impl<M: Composite> IntoComposite for M {
159
160 type Composite = M;
161
162 type Item = M::Item;
163
164 #[inline]
165 fn into_composite(self) -> Self::Composite {
166 self
167 }
168}
169
170#[must_use = "computations are lazy and do nothing unless to be run"]
172pub struct CompositeBox<T> {
173 f: Box<dyn CompositeFnBox<T>>
174}
175
176impl<T> CompositeBox<T> {
177
178 #[doc(hidden)]
180 #[inline]
181 fn new<F>(f: F) -> Self
182 where F: FnOnce(DisposableBox, &Point) -> simulation::Result<(T, DisposableBox)> + 'static
183 {
184 CompositeBox {
185 f: Box::new(f)
186 }
187 }
188
189 #[doc(hidden)]
191 #[inline]
192 pub fn call_box(self, arg: (DisposableBox, &Point,)) -> simulation::Result<(T, DisposableBox)> {
193 let CompositeBox { f } = self;
194 f.call_box(arg)
195 }
196}
197
198impl<T> Composite for CompositeBox<T> {
199
200 type Item = T;
201
202 #[inline]
203 fn call_composite(self, disposable: DisposableBox, p: &Point) -> simulation::Result<(Self::Item, DisposableBox)> {
204 self.call_box((disposable, p,))
205 }
206
207 #[inline]
208 fn into_boxed(self) -> CompositeBox<Self::Item>
209 where Self: Sized + 'static
210 {
211 self
212 }
213}
214
215trait CompositeFnBox<T> {
217
218 fn call_box(self: Box<Self>, args: (DisposableBox, &Point,)) -> simulation::Result<(T, DisposableBox)>;
220}
221
222impl<T, F> CompositeFnBox<T> for F
223 where F: for<'a> FnOnce(DisposableBox, &'a Point) -> simulation::Result<(T, DisposableBox)>
224{
225 fn call_box(self: Box<Self>, args: (DisposableBox, &Point,)) -> simulation::Result<(T, DisposableBox)> {
226 let this: Self = *self;
227 this(args.0, args.1)
228 }
229}
230
231#[must_use = "computations are lazy and do nothing unless to be run"]
233#[derive(Clone)]
234pub struct Return<T> {
235
236 val: T
238}
239
240impl<T> Composite for Return<T> {
241
242 type Item = T;
243
244 #[doc(hidden)]
245 #[inline]
246 fn call_composite(self, disposable: DisposableBox, _: &Point) -> simulation::Result<(T, DisposableBox)> {
247 let Return { val } = self;
248 Result::Ok((val, disposable))
249 }
250}
251
252#[must_use = "computations are lazy and do nothing unless to be run"]
254#[derive(Clone)]
255pub struct Delay<F, M> {
256
257 f: F,
259
260 _phantom: PhantomData<M>
262}
263
264impl<F, M> Composite for Delay<F, M>
265 where F: FnOnce() -> M,
266 M: Composite
267{
268 type Item = M::Item;
269
270 #[doc(hidden)]
271 #[inline]
272 fn call_composite(self, disposable: DisposableBox, p: &Point) -> simulation::Result<(M::Item, DisposableBox)> {
273 let Delay { f, _phantom } = self;
274 f().call_composite(disposable, p)
275 }
276}
277
278#[must_use = "computations are lazy and do nothing unless to be run"]
280#[derive(Clone)]
281pub struct Cons<F, T> {
282
283 f: F,
285
286 _phantom: PhantomData<T>
288}
289
290impl<F, T> Composite for Cons<F, T>
291 where F: FnOnce(DisposableBox, &Point) -> simulation::Result<(T, DisposableBox)>
292{
293 type Item = T;
294
295 #[doc(hidden)]
296 #[inline]
297 fn call_composite(self, disposable: DisposableBox, p: &Point) -> simulation::Result<(T, DisposableBox)> {
298 let Cons { f, _phantom } = self;
299 f(disposable, p)
300 }
301}
302
303#[must_use = "computations are lazy and do nothing unless to be run"]
305#[derive(Clone)]
306pub struct AndThen<M, U, F> {
307
308 comp: M,
310
311 f: F,
313
314 _phantom: PhantomData<U>
316}
317
318impl<M, U, F> Composite for AndThen<M, U, F>
319 where M: Composite,
320 U: Composite,
321 F: FnOnce(M::Item) -> U,
322{
323 type Item = U::Item;
324
325 #[doc(hidden)]
326 #[inline]
327 fn call_composite(self, disposable: DisposableBox, p: &Point) -> simulation::Result<(U::Item, DisposableBox)> {
328 let AndThen { comp, f, _phantom } = self;
329 match comp.call_composite(disposable, p) {
330 Result::Ok((a, disposable)) => {
331 let m = f(a);
332 m.call_composite(disposable, p)
333 },
334 Result::Err(e) => {
335 Result::Err(e)
336 }
337 }
338 }
339}
340
341#[must_use = "computations are lazy and do nothing unless to be run"]
343#[derive(Clone)]
344pub struct Map<M, B, F> {
345
346 comp: M,
348
349 f: F,
351
352 _phantom: PhantomData<B>
354}
355
356impl<M, B, F> Composite for Map<M, B, F>
357 where M: Composite,
358 F: FnOnce(M::Item) -> B,
359{
360 type Item = B;
361
362 #[doc(hidden)]
363 #[inline]
364 fn call_composite(self, disposable: DisposableBox, p: &Point) -> simulation::Result<(B, DisposableBox)> {
365 let Map { comp, f, _phantom } = self;
366 match comp.call_composite(disposable, p) {
367 Result::Ok((a, disposable)) => Result::Ok((f(a), disposable)),
368 Result::Err(e) => Result::Err(e)
369 }
370 }
371}
372
373#[must_use = "computations are lazy and do nothing unless to be run"]
375#[derive(Clone)]
376pub struct Zip<M, U> {
377
378 comp: M,
380
381 other: U,
383}
384
385impl<M, U> Composite for Zip<M, U>
386 where M: Composite,
387 U: Composite
388{
389 type Item = (M::Item, U::Item);
390
391 #[doc(hidden)]
392 #[inline]
393 fn call_composite(self, disposable: DisposableBox, p: &Point) -> simulation::Result<((M::Item, U::Item), DisposableBox)> {
394 let Zip { comp, other } = self;
395 comp.and_then(move |a| {
396 other.map(move |b| (a, b))
397 }).call_composite(disposable, p)
398 }
399}
400
401#[must_use = "computations are lazy and do nothing unless to be run"]
403#[derive(Clone)]
404pub struct Ap<M, U, B> {
405
406 comp: M,
408
409 other: U,
411
412 _phantom: PhantomData<B>
414}
415
416impl<M, U, B> Composite for Ap<M, U, B>
417 where M: Composite,
418 U: Composite,
419 M::Item: FnOnce(U::Item) -> B,
420{
421 type Item = B;
422
423 #[doc(hidden)]
424 #[inline]
425 fn call_composite(self, disposable: DisposableBox, p: &Point) -> simulation::Result<(B, DisposableBox)> {
426 let Ap { comp, other, _phantom } = self;
427 comp.and_then(move |f| {
428 other.map(move |a| { f(a) })
429 }).call_composite(disposable, p)
430 }
431}
432
433#[must_use = "computations are lazy and do nothing unless to be run"]
435#[derive(Clone)]
436pub struct Sequence<I, M> {
437
438 comps: I,
440
441 _phantom: PhantomData<M>
443}
444
445impl<I, M> Composite for Sequence<I, M>
446 where I: Iterator<Item = M>,
447 M: Composite
448{
449 type Item = Vec<M::Item>;
450
451 #[doc(hidden)]
452 fn call_composite(self, disposable: DisposableBox, p: &Point) -> simulation::Result<(Self::Item, DisposableBox)> {
453 let Sequence { comps, _phantom } = self;
454 let mut v = {
455 match comps.size_hint() {
456 (_, Some(n)) => Vec::with_capacity(n),
457 (_, None) => Vec::new()
458 }
459 };
460 let mut disposable = disposable;
461 for m in comps {
462 match m.call_composite(disposable, p) {
463 Result::Ok((a, x)) => {
464 v.push(a);
465 disposable = x;
466 },
467 Result::Err(e) => {
468 return Result::Err(e)
469 }
470 }
471 }
472 Result::Ok((v, disposable))
473 }
474}
475
476#[must_use = "computations are lazy and do nothing unless to be run"]
478#[derive(Clone)]
479pub struct Sequence_<I, M> {
480
481 comps: I,
483
484 _phantom: PhantomData<M>
486}
487
488impl<I, M> Composite for Sequence_<I, M>
489 where I: Iterator<Item = M>,
490 M: Composite
491{
492 type Item = ();
493
494 #[doc(hidden)]
495 fn call_composite(self, disposable: DisposableBox, p: &Point) -> simulation::Result<(Self::Item, DisposableBox)> {
496 let Sequence_ { comps, _phantom } = self;
497 let mut disposable = disposable;
498 for m in comps {
499 match m.call_composite(disposable, p) {
500 Result::Ok((_, x)) => { disposable = x; },
501 Result::Err(e) => return Result::Err(e)
502 }
503 }
504 Result::Ok(((), disposable))
505 }
506}
507
508#[must_use = "computations are lazy and do nothing unless to be run"]
510#[derive(Clone)]
511pub struct Run<M, D> {
512
513 comp: M,
515
516 disposable: D
518}
519
520impl<M, D> Event for Run<M, D>
521 where M: Composite,
522 D: Disposable + 'static
523{
524 type Item = (M::Item, DisposableBox);
525
526 #[doc(hidden)]
527 fn call_event(self, p: &Point) -> simulation::Result<Self::Item> {
528 let Run { comp, disposable } = self;
529 let disposable = disposable.into_boxed();
530 comp.call_composite(disposable, p)
531 }
532}
533
534#[must_use = "computations are lazy and do nothing unless to be run"]
536#[derive(Clone)]
537pub struct Run_<M> {
538
539 comp: M
541}
542
543impl<M> Event for Run_<M>
544 where M: Composite
545{
546 type Item = M::Item;
547
548 #[doc(hidden)]
549 fn call_event(self, p: &Point) -> simulation::Result<Self::Item> {
550 let Run_ { comp } = self;
551 let disposable = empty_disposable().into_boxed();
552 let (a, _) = comp.call_composite(disposable, p)?;
553 Result::Ok(a)
554 }
555}
556
557#[must_use = "computations are lazy and do nothing unless to be run"]
559#[derive(Clone)]
560pub struct DisposableComposite<D> {
561
562 action: D
564}
565
566impl<D> Composite for DisposableComposite<D>
567 where D: Disposable + 'static
568{
569 type Item = ();
570
571 #[doc(hidden)]
572 fn call_composite(self, disposable: DisposableBox, _p: &Point) -> simulation::Result<(Self::Item, DisposableBox)> {
573 let DisposableComposite { action } = self;
574 let disposable = disposable.merge(action).into_boxed();
575 Result::Ok(((), disposable))
576 }
577}
578
579#[must_use = "computations are lazy and do nothing unless to be run"]
581#[derive(Clone)]
582pub struct Trace<M> {
583
584 comp: M,
586
587 msg: String
589}
590
591impl<M> Composite for Trace<M>
592 where M: Composite
593{
594 type Item = M::Item;
595
596 #[doc(hidden)]
597 #[inline]
598 fn call_composite(self, disposable: DisposableBox, p: &Point) -> simulation::Result<(Self::Item, DisposableBox)> {
599 let Trace { comp, msg } = self;
600 p.trace(&msg);
601 comp.call_composite(disposable, p)
602 }
603}