1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
use alloc::vec::Vec;
use core::{fmt, marker::PhantomData};

use necsim_core::{
    event::{PackedEvent, TypedEvent},
    impl_report,
    reporter::Reporter,
};

use necsim_partitioning_core::LocalPartition;

pub struct BufferingReporterProxy<'l, 'p, R: Reporter, P: LocalPartition<'p, R>> {
    local_partition: &'l mut P,
    event_buffer: Vec<PackedEvent>,
    _marker: PhantomData<(&'p (), R)>,
}

impl<'l, 'p, R: Reporter, P: LocalPartition<'p, R>> fmt::Debug
    for BufferingReporterProxy<'l, 'p, R, P>
{
    fn fmt(&self, fmt: &mut fmt::Formatter) -> fmt::Result {
        struct EventBufferLen(usize);

        impl fmt::Debug for EventBufferLen {
            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
                write!(f, "Vec<PackedEvent; {}>", self.0)
            }
        }

        fmt.debug_struct(stringify!(BufferingReporterProxy))
            .field("event_buffer", &EventBufferLen(self.event_buffer.len()))
            .finish()
    }
}

impl<'l, 'p, R: Reporter, P: LocalPartition<'p, R>> Reporter
    for BufferingReporterProxy<'l, 'p, R, P>
{
    impl_report!(speciation(&mut self, speciation: MaybeUsed<
        <<P as LocalPartition<'p, R>>::Reporter as Reporter
    >::ReportSpeciation>) {
        self.event_buffer.push(speciation.clone().into());
    });

    impl_report!(dispersal(&mut self, dispersal: MaybeUsed<
        <<P as LocalPartition<'p, R>>::Reporter as Reporter
    >::ReportDispersal>) {
        self.event_buffer.push(dispersal.clone().into());
    });

    impl_report!(progress(&mut self, progress: MaybeUsed<
        <<P as LocalPartition<'p, R>>::Reporter as Reporter
    >::ReportProgress>) {
        self.local_partition.get_reporter().report_progress(progress.into());
    });
}

impl<'l, 'p, R: Reporter, P: LocalPartition<'p, R>> BufferingReporterProxy<'l, 'p, R, P> {
    pub fn from(local_partition: &'l mut P) -> Self {
        Self {
            local_partition,
            event_buffer: Vec::new(),
            _marker: PhantomData::<(&'p (), R)>,
        }
    }

    pub fn clear_events(&mut self) {
        self.event_buffer.clear();
    }

    pub fn report_events(&mut self) {
        for event in self.event_buffer.drain(..) {
            match event.into() {
                TypedEvent::Speciation(event) => {
                    self.local_partition
                        .get_reporter()
                        .report_speciation(&event.into());
                },
                TypedEvent::Dispersal(event) => {
                    self.local_partition
                        .get_reporter()
                        .report_dispersal(&event.into());
                },
            }
        }
    }

    pub fn local_partition(&mut self) -> &mut P {
        self.local_partition
    }
}