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 + Clone + '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 + Clone + '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 + Clone + '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 CompositeFnBoxClone<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)> + Clone + '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> Clone for CompositeBox<T> {
199
200 fn clone(&self) -> Self {
201 CompositeBox {
202 f: self.f.call_clone()
203 }
204 }
205}
206
207impl<T> Composite for CompositeBox<T> {
208
209 type Item = T;
210
211 #[inline]
212 fn call_composite(self, disposable: DisposableBox, p: &Point) -> simulation::Result<(Self::Item, DisposableBox)> {
213 self.call_box((disposable, p,))
214 }
215
216 #[inline]
217 fn into_boxed(self) -> CompositeBox<Self::Item>
218 where Self: Sized + 'static
219 {
220 self
221 }
222}
223
224trait CompositeFnBox<T> {
226
227 fn call_box(self: Box<Self>, args: (DisposableBox, &Point,)) -> simulation::Result<(T, DisposableBox)>;
229}
230
231impl<T, F> CompositeFnBox<T> for F
232 where F: for<'a> FnOnce(DisposableBox, &'a Point) -> simulation::Result<(T, DisposableBox)>
233{
234 fn call_box(self: Box<Self>, args: (DisposableBox, &Point,)) -> simulation::Result<(T, DisposableBox)> {
235 let this: Self = *self;
236 this(args.0, args.1)
237 }
238}
239
240trait CompositeFnBoxClone<T>: CompositeFnBox<T> {
242
243 fn call_clone(&self) -> Box<dyn CompositeFnBoxClone<T>>;
245}
246
247impl<T, F> CompositeFnBoxClone<T> for F
248 where F: for<'a> FnOnce(DisposableBox, &'a Point) -> simulation::Result<(T, DisposableBox)> + Clone + 'static
249{
250 fn call_clone(&self) -> Box<dyn CompositeFnBoxClone<T>> {
251 Box::new(self.clone())
252 }
253}
254
255#[must_use = "computations are lazy and do nothing unless to be run"]
257#[derive(Clone)]
258pub struct Return<T> {
259
260 val: T
262}
263
264impl<T> Composite for Return<T> {
265
266 type Item = T;
267
268 #[doc(hidden)]
269 #[inline]
270 fn call_composite(self, disposable: DisposableBox, _: &Point) -> simulation::Result<(T, DisposableBox)> {
271 let Return { val } = self;
272 Result::Ok((val, disposable))
273 }
274}
275
276#[must_use = "computations are lazy and do nothing unless to be run"]
278#[derive(Clone)]
279pub struct Delay<F, M> {
280
281 f: F,
283
284 _phantom: PhantomData<M>
286}
287
288impl<F, M> Composite for Delay<F, M>
289 where F: FnOnce() -> M,
290 M: Composite
291{
292 type Item = M::Item;
293
294 #[doc(hidden)]
295 #[inline]
296 fn call_composite(self, disposable: DisposableBox, p: &Point) -> simulation::Result<(M::Item, DisposableBox)> {
297 let Delay { f, _phantom } = self;
298 f().call_composite(disposable, p)
299 }
300}
301
302#[must_use = "computations are lazy and do nothing unless to be run"]
304#[derive(Clone)]
305pub struct Cons<F, T> {
306
307 f: F,
309
310 _phantom: PhantomData<T>
312}
313
314impl<F, T> Composite for Cons<F, T>
315 where F: FnOnce(DisposableBox, &Point) -> simulation::Result<(T, DisposableBox)>
316{
317 type Item = T;
318
319 #[doc(hidden)]
320 #[inline]
321 fn call_composite(self, disposable: DisposableBox, p: &Point) -> simulation::Result<(T, DisposableBox)> {
322 let Cons { f, _phantom } = self;
323 f(disposable, p)
324 }
325}
326
327#[must_use = "computations are lazy and do nothing unless to be run"]
329#[derive(Clone)]
330pub struct AndThen<M, U, F> {
331
332 comp: M,
334
335 f: F,
337
338 _phantom: PhantomData<U>
340}
341
342impl<M, U, F> Composite for AndThen<M, U, F>
343 where M: Composite,
344 U: Composite,
345 F: FnOnce(M::Item) -> U,
346{
347 type Item = U::Item;
348
349 #[doc(hidden)]
350 #[inline]
351 fn call_composite(self, disposable: DisposableBox, p: &Point) -> simulation::Result<(U::Item, DisposableBox)> {
352 let AndThen { comp, f, _phantom } = self;
353 match comp.call_composite(disposable, p) {
354 Result::Ok((a, disposable)) => {
355 let m = f(a);
356 m.call_composite(disposable, p)
357 },
358 Result::Err(e) => {
359 Result::Err(e)
360 }
361 }
362 }
363}
364
365#[must_use = "computations are lazy and do nothing unless to be run"]
367#[derive(Clone)]
368pub struct Map<M, B, F> {
369
370 comp: M,
372
373 f: F,
375
376 _phantom: PhantomData<B>
378}
379
380impl<M, B, F> Composite for Map<M, B, F>
381 where M: Composite,
382 F: FnOnce(M::Item) -> B,
383{
384 type Item = B;
385
386 #[doc(hidden)]
387 #[inline]
388 fn call_composite(self, disposable: DisposableBox, p: &Point) -> simulation::Result<(B, DisposableBox)> {
389 let Map { comp, f, _phantom } = self;
390 match comp.call_composite(disposable, p) {
391 Result::Ok((a, disposable)) => Result::Ok((f(a), disposable)),
392 Result::Err(e) => Result::Err(e)
393 }
394 }
395}
396
397#[must_use = "computations are lazy and do nothing unless to be run"]
399#[derive(Clone)]
400pub struct Zip<M, U> {
401
402 comp: M,
404
405 other: U,
407}
408
409impl<M, U> Composite for Zip<M, U>
410 where M: Composite,
411 U: Composite
412{
413 type Item = (M::Item, U::Item);
414
415 #[doc(hidden)]
416 #[inline]
417 fn call_composite(self, disposable: DisposableBox, p: &Point) -> simulation::Result<((M::Item, U::Item), DisposableBox)> {
418 let Zip { comp, other } = self;
419 comp.and_then(move |a| {
420 other.map(move |b| (a, b))
421 }).call_composite(disposable, p)
422 }
423}
424
425#[must_use = "computations are lazy and do nothing unless to be run"]
427#[derive(Clone)]
428pub struct Ap<M, U, B> {
429
430 comp: M,
432
433 other: U,
435
436 _phantom: PhantomData<B>
438}
439
440impl<M, U, B> Composite for Ap<M, U, B>
441 where M: Composite,
442 U: Composite,
443 M::Item: FnOnce(U::Item) -> B,
444{
445 type Item = B;
446
447 #[doc(hidden)]
448 #[inline]
449 fn call_composite(self, disposable: DisposableBox, p: &Point) -> simulation::Result<(B, DisposableBox)> {
450 let Ap { comp, other, _phantom } = self;
451 comp.and_then(move |f| {
452 other.map(move |a| { f(a) })
453 }).call_composite(disposable, p)
454 }
455}
456
457#[must_use = "computations are lazy and do nothing unless to be run"]
459#[derive(Clone)]
460pub struct Sequence<I, M> {
461
462 comps: I,
464
465 _phantom: PhantomData<M>
467}
468
469impl<I, M> Composite for Sequence<I, M>
470 where I: Iterator<Item = M>,
471 M: Composite
472{
473 type Item = Vec<M::Item>;
474
475 #[doc(hidden)]
476 fn call_composite(self, disposable: DisposableBox, p: &Point) -> simulation::Result<(Self::Item, DisposableBox)> {
477 let Sequence { comps, _phantom } = self;
478 let mut v = {
479 match comps.size_hint() {
480 (_, Some(n)) => Vec::with_capacity(n),
481 (_, None) => Vec::new()
482 }
483 };
484 let mut disposable = disposable;
485 for m in comps {
486 match m.call_composite(disposable, p) {
487 Result::Ok((a, x)) => {
488 v.push(a);
489 disposable = x;
490 },
491 Result::Err(e) => {
492 return Result::Err(e)
493 }
494 }
495 }
496 Result::Ok((v, disposable))
497 }
498}
499
500#[must_use = "computations are lazy and do nothing unless to be run"]
502#[derive(Clone)]
503pub struct Sequence_<I, M> {
504
505 comps: I,
507
508 _phantom: PhantomData<M>
510}
511
512impl<I, M> Composite for Sequence_<I, M>
513 where I: Iterator<Item = M>,
514 M: Composite
515{
516 type Item = ();
517
518 #[doc(hidden)]
519 fn call_composite(self, disposable: DisposableBox, p: &Point) -> simulation::Result<(Self::Item, DisposableBox)> {
520 let Sequence_ { comps, _phantom } = self;
521 let mut disposable = disposable;
522 for m in comps {
523 match m.call_composite(disposable, p) {
524 Result::Ok((_, x)) => { disposable = x; },
525 Result::Err(e) => return Result::Err(e)
526 }
527 }
528 Result::Ok(((), disposable))
529 }
530}
531
532#[must_use = "computations are lazy and do nothing unless to be run"]
534#[derive(Clone)]
535pub struct Run<M, D> {
536
537 comp: M,
539
540 disposable: D
542}
543
544impl<M, D> Event for Run<M, D>
545 where M: Composite,
546 D: Disposable + Clone + 'static
547{
548 type Item = (M::Item, DisposableBox);
549
550 #[doc(hidden)]
551 fn call_event(self, p: &Point) -> simulation::Result<Self::Item> {
552 let Run { comp, disposable } = self;
553 let disposable = disposable.into_boxed();
554 comp.call_composite(disposable, p)
555 }
556}
557
558#[must_use = "computations are lazy and do nothing unless to be run"]
560#[derive(Clone)]
561pub struct Run_<M> {
562
563 comp: M
565}
566
567impl<M> Event for Run_<M>
568 where M: Composite
569{
570 type Item = M::Item;
571
572 #[doc(hidden)]
573 fn call_event(self, p: &Point) -> simulation::Result<Self::Item> {
574 let Run_ { comp } = self;
575 let disposable = empty_disposable().into_boxed();
576 let (a, _) = comp.call_composite(disposable, p)?;
577 Result::Ok(a)
578 }
579}
580
581#[must_use = "computations are lazy and do nothing unless to be run"]
583#[derive(Clone)]
584pub struct DisposableComposite<D> {
585
586 action: D
588}
589
590impl<D> Composite for DisposableComposite<D>
591 where D: Disposable + Clone + 'static
592{
593 type Item = ();
594
595 #[doc(hidden)]
596 fn call_composite(self, disposable: DisposableBox, _p: &Point) -> simulation::Result<(Self::Item, DisposableBox)> {
597 let DisposableComposite { action } = self;
598 let disposable = disposable.merge(action).into_boxed();
599 Result::Ok(((), disposable))
600 }
601}
602
603#[must_use = "computations are lazy and do nothing unless to be run"]
605#[derive(Clone)]
606pub struct Trace<M> {
607
608 comp: M,
610
611 msg: String
613}
614
615impl<M> Composite for Trace<M>
616 where M: Composite
617{
618 type Item = M::Item;
619
620 #[doc(hidden)]
621 #[inline]
622 fn call_composite(self, disposable: DisposableBox, p: &Point) -> simulation::Result<(Self::Item, DisposableBox)> {
623 let Trace { comp, msg } = self;
624 p.trace(&msg);
625 comp.call_composite(disposable, p)
626 }
627}