kaspa_notify/
events.rs

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    /// Event type classifying subscriptions (see [`Scope`]) and notifications (see [`Notification`])
39    ///
40    /// Note: This enum is central to the notification system. For supporting a new notification type, it is advised to
41    /// start by adding a new variant here.
42    #[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/// Generic array with [`EventType`] strongly-typed index
79#[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
137/// An event type array of on/off switches
138pub 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}