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
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
pub mod map;
pub use map::*;
use alloc::string::{String, ToString};
use core::time::Duration;
use serde::{Deserialize, Serialize};
use crate::{
bolts::tuples::{MatchName, Named},
executors::HasExecHooks,
utils::current_time,
Error,
};
pub trait Observer: Named + serde::Serialize + serde::de::DeserializeOwned {
#[inline]
fn flush(&mut self) -> Result<(), Error> {
Ok(())
}
}
pub trait ObserversTuple: MatchName + serde::Serialize + serde::de::DeserializeOwned {}
impl ObserversTuple for () {}
impl<Head, Tail> ObserversTuple for (Head, Tail)
where
Head: Observer,
Tail: ObserversTuple,
{
}
#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct TimeObserver {
name: String,
start_time: Duration,
last_runtime: Option<Duration>,
}
impl TimeObserver {
#[must_use]
pub fn new(name: &'static str) -> Self {
Self {
name: name.to_string(),
start_time: Duration::from_secs(0),
last_runtime: None,
}
}
#[must_use]
pub fn last_runtime(&self) -> &Option<Duration> {
&self.last_runtime
}
}
impl Observer for TimeObserver {}
impl<EM, I, S> HasExecHooks<EM, I, S> for TimeObserver {
fn pre_exec(&mut self, _state: &mut S, _mgr: &mut EM, _input: &I) -> Result<(), Error> {
self.last_runtime = None;
self.start_time = current_time();
Ok(())
}
fn post_exec(&mut self, _state: &mut S, _mgr: &mut EM, _input: &I) -> Result<(), Error> {
self.last_runtime = Some(current_time() - self.start_time);
Ok(())
}
}
impl Named for TimeObserver {
fn name(&self) -> &str {
&self.name
}
}
#[cfg(feature = "std")]
#[cfg(test)]
mod tests {
use crate::{
bolts::tuples::{tuple_list, tuple_list_type, Named},
observers::{StdMapObserver, TimeObserver},
};
static mut MAP: [u32; 4] = [0; 4];
#[test]
fn test_observer_serde() {
let obv = tuple_list!(
TimeObserver::new("time"),
StdMapObserver::new("map", unsafe { &mut MAP })
);
let vec = postcard::to_allocvec(&obv).unwrap();
println!("{:?}", vec);
let obv2: tuple_list_type!(TimeObserver, StdMapObserver<u32>) =
postcard::from_bytes(&vec).unwrap();
assert_eq!(obv.0.name(), obv2.0.name());
}
}