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#[cfg(feature = "serde")]
9use serde::{Deserialize, Serialize};
10
11use crate::{Felt, utils::hash_string_to_word};
12
13mod sys_events;
14pub use sys_events::SystemEvent;
15
16#[derive(Debug, Clone, Copy, PartialEq, Eq, Ord, PartialOrd, Hash)]
32#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
33#[cfg_attr(feature = "serde", serde(transparent))]
34#[cfg_attr(
35 all(feature = "arbitrary", test),
36 miden_test_serde_macros::serde_test(binary_serde(true))
37)]
38pub struct EventId(u64);
39
40impl EventId {
41 pub fn from_name(name: impl AsRef<str>) -> Self {
56 let digest_word = hash_string_to_word(name.as_ref());
57 Self(digest_word[0].as_canonical_u64())
58 }
59
60 pub fn from_felt(event_id: Felt) -> Self {
62 Self(event_id.as_canonical_u64())
63 }
64
65 pub const fn from_u64(event_id: u64) -> Self {
67 Self(event_id % Felt::ORDER_U64)
68 }
69
70 pub const fn as_felt(&self) -> Felt {
72 Felt::new(self.0)
73 }
74
75 pub const fn as_u64(&self) -> u64 {
77 self.0
78 }
79}
80
81impl Display for EventId {
82 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
83 core::fmt::Display::fmt(&self.0, f)
84 }
85}
86
87#[derive(Debug, Clone, PartialEq, Eq)]
102#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
103#[cfg_attr(feature = "serde", serde(transparent))]
104#[cfg_attr(
105 all(feature = "arbitrary", test),
106 miden_test_serde_macros::serde_test(binary_serde(true))
107)]
108pub struct EventName(Cow<'static, str>);
109
110impl EventName {
111 pub const fn new(name: &'static str) -> Self {
115 Self(Cow::Borrowed(name))
116 }
117
118 pub fn from_string(name: String) -> Self {
122 Self(Cow::Owned(name))
123 }
124
125 pub fn as_str(&self) -> &str {
127 self.0.as_ref()
128 }
129
130 pub fn to_event_id(&self) -> EventId {
134 EventId::from_name(self.as_str())
135 }
136}
137
138impl Display for EventName {
139 fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
140 write!(f, "{}", self.0)
141 }
142}
143
144impl AsRef<str> for EventName {
145 fn as_ref(&self) -> &str {
146 self.0.as_ref()
147 }
148}
149
150impl Serializable for EventId {
154 fn write_into<W: ByteWriter>(&self, target: &mut W) {
155 self.as_felt().write_into(target);
156 }
157}
158
159impl Deserializable for EventId {
160 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
161 Ok(Self(Felt::read_from(source)?.as_canonical_u64()))
162 }
163}
164
165impl Serializable for EventName {
166 fn write_into<W: ByteWriter>(&self, target: &mut W) {
167 self.0.as_ref().write_into(target)
169 }
170}
171
172impl Deserializable for EventName {
173 fn read_from<R: ByteReader>(source: &mut R) -> Result<Self, DeserializationError> {
174 let name = String::read_from(source)?;
175 Ok(Self::from_string(name))
176 }
177}
178
179#[cfg(all(feature = "arbitrary", test))]
183impl proptest::prelude::Arbitrary for EventId {
184 type Parameters = ();
185
186 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
187 use proptest::prelude::*;
188 any::<u64>().prop_map(EventId::from_u64).boxed()
189 }
190
191 type Strategy = proptest::prelude::BoxedStrategy<Self>;
192}
193
194#[cfg(all(feature = "arbitrary", test))]
195impl proptest::prelude::Arbitrary for EventName {
196 type Parameters = ();
197
198 fn arbitrary_with(_args: Self::Parameters) -> Self::Strategy {
199 use proptest::prelude::*;
200
201 prop_oneof![
203 Just(EventName::new("test::static::event")),
205 Just(EventName::new("core::handler::example")),
206 Just(EventName::new("user::custom::event")),
207 any::<(u32, u32)>()
209 .prop_map(|(a, b)| EventName::from_string(format!("dynamic::event::{}::{}", a, b))),
210 ]
211 .boxed()
212 }
213
214 type Strategy = proptest::prelude::BoxedStrategy<Self>;
215}
216
217#[cfg(test)]
221mod tests {
222 use alloc::string::ToString;
223
224 use super::*;
225
226 #[test]
227 fn event_basics() {
228 let id1 = EventId::from_u64(100);
230 assert_eq!(id1.as_u64(), 100);
231 assert_eq!(id1.as_felt(), Felt::new(100));
232
233 let id2 = EventId::from_felt(Felt::new(200));
234 assert_eq!(id2.as_u64(), 200);
235
236 let id3 = EventId::from_name("test::event");
238 let id4 = EventId::from_name("test::event");
239 assert_eq!(id3, id4);
240
241 let name1 = EventName::new("static::event");
243 assert_eq!(name1.as_str(), "static::event");
244 assert_eq!(format!("{}", name1), "static::event");
245
246 let name2 = EventName::from_string("dynamic::event".to_string());
247 assert_eq!(name2.as_str(), "dynamic::event");
248
249 assert_eq!(name1.to_event_id(), EventId::from_name("static::event"));
251 }
252}