1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
use crate::internal_prelude::*;
#[non_exhaustive]
#[repr(i32)]
pub enum EventType {
Finished,
Looped,
UserAutomation { param: std::os::raw::c_ulonglong },
}
pub struct Event {
pub source: Handle,
pub context: Option<Context>,
pub r#type: EventType,
}
pub(crate) struct EventIterator<'a> {
pub(crate) context: &'a Context,
pub(crate) errored: bool,
}
impl<'a> EventIterator<'a> {
fn get_next(&self) -> Result<Option<Event>> {
let mut source: Option<Handle> = None;
let mut context: Option<Context> = None;
let mut evt: syz_Event = Default::default();
check_error(unsafe {
syz_contextGetNextEvent(&mut evt as *mut syz_Event, self.context.to_syz_handle(), 0)
})?;
let r#type = match evt.type_ as u32 {
SYZ_EVENT_TYPE_INVALID => {
return Ok(None);
}
SYZ_EVENT_TYPE_FINISHED => EventType::Finished,
SYZ_EVENT_TYPE_LOOPED => EventType::Looped,
SYZ_EVENT_TYPE_USER_AUTOMATION => EventType::UserAutomation {
param: unsafe { evt.payload.user_automation.param },
},
_ => {
unreachable!()
}
};
let inc_ret = check_error(unsafe { syz_handleIncRef(evt.source) })
.and_then(|_| {
source = Some(Handle::new(evt.source));
if evt.context == 0 {
return Ok(());
}
check_error(unsafe { syz_handleIncRef(evt.context) })
})
.map(|_| {
context = Some(Context(Handle::new(evt.context)));
});
unsafe { syz_eventDeinit(&mut evt as *mut syz_Event) };
inc_ret?;
Ok(Some(Event {
source: source.unwrap(),
context,
r#type,
}))
}
}
impl<'a> Iterator for EventIterator<'a> {
type Item = Result<Event>;
fn next(&mut self) -> Option<Result<Event>> {
if self.errored {
return None;
}
match self.get_next() {
Ok(Some(e)) => Some(Ok(e)),
Ok(None) => None,
Err(e) => {
self.errored = true;
Some(Err(e))
}
}
}
}