1use alloc::{borrow::Cow, string::String};
2use core::fmt::{Display, Formatter};
3
4use miden_crypto::{
5 field::PrimeField64,
6 utils::{ByteReader, ByteWriter, Deserializable, DeserializationError, Serializable},
7};
8
9use crate::{Felt, utils::hash_string_to_word};
10
11mod sys_events;
12pub use sys_events::SystemEvent;
13
14#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)]
30#[cfg_attr(
31 all(feature = "arbitrary", test),
32 miden_test_serialization_macros::serialization_test
33)]
34pub struct EventId(u64);
35
36impl EventId {
37 pub fn from_name(name: impl AsRef<str>) -> Self {
52 let digest_word = hash_string_to_word(name.as_ref());
53 Self(digest_word[0].as_canonical_u64())
54 }
55
56 pub fn from_felt(event_id: Felt) -> Self {
58 Self(event_id.as_canonical_u64())
59 }
60
61 pub const fn from_u64(event_id: u64) -> Self {
63 Self(event_id % Felt::ORDER_U64)
64 }
65
66 pub const fn as_felt(&self) -> Felt {
68 Felt::new_unchecked(self.0)
69 }
70
71 pub const fn as_u64(&self) -> u64 {
73 self.0
74 }
75}
76
77impl Display for EventId {
78 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
79 Display::fmt(&self.0, f)
80 }
81}
82
83#[derive(Debug, Clone, PartialEq, Eq)]
98#[cfg_attr(
99 all(feature = "arbitrary", test),
100 miden_test_serialization_macros::serialization_test
101)]
102pub struct EventName(Cow<'static, str>);
103
104impl EventName {
105 pub const fn new(name: &'static str) -> Self {
109 Self(Cow::Borrowed(name))
110 }
111
112 pub fn from_string(name: String) -> Self {
116 Self(Cow::Owned(name))
117 }
118
119 pub fn as_str(&self) -> &str {
121 self.0.as_ref()
122 }
123
124 pub fn to_event_id(&self) -> EventId {
128 EventId::from_name(self.as_str())
129 }
130}
131
132impl Display for EventName {
133 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
134 write!(f, "{}", self.0)
135 }
136}
137
138impl AsRef<str> for EventName {
139 fn as_ref(&self) -> &str {
140 self.0.as_ref()
141 }
142}
143
144impl Serializable for EventId {
148 fn write_into<W: ByteWriter>(&self, target: &mut W) {
149 self.as_felt().write_into(target);
150 }
151}
152
153impl Deserializable for EventId {
154 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
155 Ok(Self(Felt::read_from(source)?.as_canonical_u64()))
156 }
157}
158
159impl Serializable for EventName {
160 fn write_into<W: ByteWriter>(&self, target: &mut W) {
161 self.0.as_ref().write_into(target)
163 }
164}
165
166impl Deserializable for EventName {
167 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
168 let name = String::read_from(source)?;
169 Ok(Self::from_string(name))
170 }
171}
172
173#[cfg(all(feature = "arbitrary", test))]
177impl proptest::prelude::Arbitrary for EventId {
178 type Parameters = ();
179
180 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
181 use proptest::prelude::*;
182 any::<u64>().prop_map(EventId::from_u64).boxed()
183 }
184
185 type Strategy = proptest::prelude::BoxedStrategy<Self>;
186}
187
188#[cfg(all(feature = "arbitrary", test))]
189impl proptest::prelude::Arbitrary for EventName {
190 type Parameters = ();
191
192 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
193 use proptest::prelude::*;
194
195 prop_oneof![
197 Just(EventName::new("test::static::event")),
199 Just(EventName::new("core::handler::example")),
200 Just(EventName::new("user::custom::event")),
201 any::<(u32, u32)>()
203 .prop_map(|(a, b)| EventName::from_string(format!("dynamic::event::{a}::{b}"))),
204 ]
205 .boxed()
206 }
207
208 type Strategy = proptest::prelude::BoxedStrategy<Self>;
209}
210
211#[cfg(test)]
215mod tests {
216 use alloc::string::ToString;
217
218 use super::*;
219
220 #[test]
221 fn event_basics() {
222 let id1 = EventId::from_u64(100);
224 assert_eq!(id1.as_u64(), 100);
225 assert_eq!(id1.as_felt(), Felt::new_unchecked(100));
226
227 let id2 = EventId::from_felt(Felt::new_unchecked(200));
228 assert_eq!(id2.as_u64(), 200);
229
230 let id3 = EventId::from_name("test::event");
232 let id4 = EventId::from_name("test::event");
233 assert_eq!(id3, id4);
234
235 let name1 = EventName::new("static::event");
237 assert_eq!(name1.as_str(), "static::event");
238 assert_eq!(format!("{name1}"), "static::event");
239
240 let name2 = EventName::from_string("dynamic::event".to_string());
241 assert_eq!(name2.as_str(), "dynamic::event");
242
243 assert_eq!(name1.to_event_id(), EventId::from_name("static::event"));
245 }
246}