1use super::scope::Scope;
2use crate::error::Error;
3use serde::{Deserialize, Serialize};
4use std::ops::{Index, IndexMut};
5use std::str::FromStr;
6use workflow_core::enums::usize_try_from;
7
8macro_rules! event_type_enum {
9 ($(#[$meta:meta])* $vis:vis enum $name:ident {
10 $($(#[$variant_meta:meta])* $variant_name:ident $(= $val:expr)?,)*
11 }) => {
12 usize_try_from!{
13 $(#[$meta])* $vis enum $name {
14 $($(#[$variant_meta])* $variant_name $(= $val)?,)*
15 }
16 }
17 impl std::convert::From<&Scope> for $name {
18 fn from(value: &Scope) -> Self {
19 match value {
20 $(Scope::$variant_name(_) => $name::$variant_name),*
21 }
22 }
23 }
24 impl std::fmt::Display for $name {
25 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
26 match self {
27 $($name::$variant_name => write!(f, stringify!($variant_name))),*
28 }
29 }
30 }
31 pub const EVENT_TYPE_ARRAY: [EventType; EVENT_COUNT] = [
32 $($name::$variant_name),*
33 ];
34 }
35}
36
37event_type_enum! {
38 #[derive(Clone, Copy, Debug, Eq, PartialEq, Hash, Serialize, Deserialize)]
43 #[serde(rename_all = "kebab-case")]
44 pub enum EventType {
45 BlockAdded = 0,
46 VirtualChainChanged,
47 FinalityConflict,
48 FinalityConflictResolved,
49 UtxosChanged,
50 SinkBlueScoreChanged,
51 VirtualDaaScoreChanged,
52 PruningPointUtxoSetOverride,
53 NewBlockTemplate,
54 }
55}
56
57pub const EVENT_COUNT: usize = 9;
58
59impl FromStr for EventType {
60 type Err = Error;
61
62 fn from_str(s: &str) -> Result<Self, Self::Err> {
63 match s {
64 "block-added" => Ok(EventType::BlockAdded),
65 "virtual-chain-changed" => Ok(EventType::VirtualChainChanged),
66 "finality-conflict" => Ok(EventType::FinalityConflict),
67 "finality-conflict-resolved" => Ok(EventType::FinalityConflictResolved),
68 "utxos-changed" => Ok(EventType::UtxosChanged),
69 "sink-blue-score-changed" => Ok(EventType::SinkBlueScoreChanged),
70 "virtual-daa-score-changed" => Ok(EventType::VirtualDaaScoreChanged),
71 "pruning-point-utxo-set-override" => Ok(EventType::PruningPointUtxoSetOverride),
72 "new-block-template" => Ok(EventType::NewBlockTemplate),
73 _ => Err(Error::InvalidEventType(s.to_string())),
74 }
75 }
76}
77
78#[derive(Default, Clone, Copy, Debug)]
80pub struct EventArray<T>([T; EVENT_COUNT]);
81
82impl<T> EventArray<T> {
83 pub fn from_fn<F>(cb: F) -> Self
84 where
85 F: FnMut(usize) -> T,
86 {
87 let array: [T; EVENT_COUNT] = core::array::from_fn(cb);
88 Self(array)
89 }
90
91 pub fn iter(&self) -> EventArrayIterator<'_, T> {
92 EventArrayIterator::new(self)
93 }
94}
95
96impl<T> Index<EventType> for EventArray<T> {
97 type Output = T;
98
99 fn index(&self, index: EventType) -> &Self::Output {
100 let idx = index as usize;
101 &self.0[idx]
102 }
103}
104
105impl<T> IndexMut<EventType> for EventArray<T> {
106 fn index_mut(&mut self, index: EventType) -> &mut Self::Output {
107 let idx = index as usize;
108 &mut self.0[idx]
109 }
110}
111
112pub struct EventArrayIterator<'a, T> {
113 array: &'a EventArray<T>,
114 index: usize,
115}
116
117impl<'a, T> EventArrayIterator<'a, T> {
118 fn new(array: &'a EventArray<T>) -> Self {
119 Self { array, index: 0 }
120 }
121}
122
123impl<'a, T> Iterator for EventArrayIterator<'a, T> {
124 type Item = &'a T;
125
126 fn next(&mut self) -> Option<Self::Item> {
127 match self.index < EVENT_TYPE_ARRAY.len() {
128 true => {
129 self.index += 1;
130 Some(&self.array[EVENT_TYPE_ARRAY[self.index - 1]])
131 }
132 false => None,
133 }
134 }
135}
136
137pub type EventSwitches = EventArray<bool>;
139
140impl From<&[EventType]> for EventSwitches {
141 fn from(events: &[EventType]) -> Self {
142 let mut switches = EventSwitches::default();
143 events.iter().for_each(|x| switches[*x] = true);
144 switches
145 }
146}