Skip to main content

squid/
event.rs

1//! Contains the [`EventPool`] and other helper structs.
2
3use std::collections::HashMap;
4
5/// The ID of the syscall event is always the same: this value
6pub const EVENT_SYSCALL: usize = 0;
7
8/// The ID of the breakpint event is always the same: this value
9pub const EVENT_BREAKPOINT: usize = 1;
10
11/// The ID of an event in the [`EventPool`]
12#[derive(Copy, Clone, Debug, PartialEq, PartialOrd, Eq, Ord, Hash)]
13pub struct EventId(usize);
14
15impl EventId {
16    fn new(id: usize) -> Self {
17        EventId(id)
18    }
19
20    /// Get the ID as a usize
21    pub fn id(&self) -> usize {
22        self.0
23    }
24}
25
26/// The EventPool manages all events that might be thrown during emulation of the target program.
27#[derive(Debug)]
28pub struct EventPool {
29    events: HashMap<String, EventId>,
30    cursor: usize,
31}
32
33impl EventPool {
34    pub(crate) fn new() -> Self {
35        Self {
36            events: HashMap::new(),
37            cursor: 0,
38        }
39    }
40
41    fn next_event(&mut self) -> EventId {
42        let cursor = self.cursor;
43        self.cursor = cursor.checked_add(1).expect("Ran out of possible event ids");
44        EventId::new(cursor)
45    }
46
47    /// Given an event name, create a new event ID and return it.
48    /// If the event name already exists, the corresponding ID is returned.
49    pub fn add_event<S: Into<String> + AsRef<str>>(&mut self, name: S) -> EventId {
50        if let Some(id) = self.get_event(name.as_ref()) {
51            id
52        } else {
53            let id = self.next_event();
54            self.events.insert(name.into(), id);
55            id
56        }
57    }
58
59    /// Given an event name, return the corresponding event ID
60    pub fn get_event<S: AsRef<str>>(&self, name: S) -> Option<EventId> {
61        self.events.get(name.as_ref()).copied()
62    }
63
64    /// Delete an event from the event pool
65    pub fn remove_event<S: AsRef<str>>(&mut self, name: S) -> Option<EventId> {
66        self.events.remove(name.as_ref())
67    }
68
69    /// Return the total number of events
70    pub fn len(&self) -> usize {
71        self.events.len()
72    }
73
74    /// Return whether any events have been created
75    pub fn is_empty(&self) -> bool {
76        self.events.is_empty()
77    }
78}