2023-01-31 15:45:14 +00:00
|
|
|
use fnv::FnvHashSet;
|
|
|
|
use std::borrow::Cow;
|
|
|
|
use std::collections::hash_set::Iter;
|
|
|
|
use std::fmt::{Debug, Display, Formatter};
|
|
|
|
|
2023-01-31 16:45:49 +00:00
|
|
|
#[cfg(feature = "known_stubs")]
|
|
|
|
#[linkme::distributed_slice]
|
|
|
|
pub static KNOWN_STUBS: [Stub] = [..];
|
|
|
|
|
2023-01-31 15:45:14 +00:00
|
|
|
#[derive(Ord, PartialOrd, Eq, PartialEq, Hash, Debug, Clone)]
|
|
|
|
pub enum Stub {
|
|
|
|
Avm1Method {
|
|
|
|
class: &'static str,
|
|
|
|
method: &'static str,
|
2023-01-31 16:45:49 +00:00
|
|
|
specifics: Option<&'static str>,
|
2023-01-31 15:45:14 +00:00
|
|
|
},
|
2023-01-31 17:20:20 +00:00
|
|
|
Avm2Method {
|
|
|
|
class: &'static str,
|
|
|
|
method: &'static str,
|
|
|
|
specifics: Option<&'static str>,
|
|
|
|
},
|
2023-01-31 17:09:42 +00:00
|
|
|
Avm2Getter {
|
|
|
|
class: &'static str,
|
2023-01-31 17:15:56 +00:00
|
|
|
property: &'static str,
|
2023-01-31 17:09:42 +00:00
|
|
|
},
|
|
|
|
Avm2Setter {
|
|
|
|
class: &'static str,
|
2023-01-31 17:15:56 +00:00
|
|
|
property: &'static str,
|
|
|
|
},
|
|
|
|
Avm2Constructor {
|
|
|
|
class: &'static str,
|
2023-01-31 17:09:42 +00:00
|
|
|
},
|
2023-01-31 15:45:14 +00:00
|
|
|
Other(Cow<'static, str>),
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Display for Stub {
|
|
|
|
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
|
|
|
|
match self {
|
|
|
|
Stub::Avm1Method {
|
|
|
|
class,
|
|
|
|
method,
|
|
|
|
specifics: None,
|
|
|
|
} => {
|
2023-01-31 17:09:42 +00:00
|
|
|
write!(f, "AVM1 {class}.{method}()")
|
2023-01-31 15:45:14 +00:00
|
|
|
}
|
|
|
|
Stub::Avm1Method {
|
|
|
|
class,
|
|
|
|
method,
|
|
|
|
specifics: Some(specifics),
|
|
|
|
} => {
|
2023-01-31 17:09:42 +00:00
|
|
|
write!(f, "AVM1 {class}.{method}() {specifics}")
|
2023-01-31 17:20:20 +00:00
|
|
|
}
|
|
|
|
Stub::Avm2Method {
|
|
|
|
class,
|
|
|
|
method,
|
|
|
|
specifics: None,
|
|
|
|
} => {
|
|
|
|
write!(f, "AVM2 {class}.{method}()")
|
|
|
|
}
|
|
|
|
Stub::Avm2Method {
|
|
|
|
class,
|
|
|
|
method,
|
|
|
|
specifics: Some(specifics),
|
|
|
|
} => {
|
|
|
|
write!(f, "AVM2 {class}.{method}() {specifics}")
|
2023-01-31 17:09:42 +00:00
|
|
|
}
|
2023-01-31 17:15:56 +00:00
|
|
|
Stub::Avm2Getter {
|
|
|
|
class,
|
|
|
|
property: field,
|
|
|
|
} => {
|
2023-01-31 17:09:42 +00:00
|
|
|
write!(f, "AVM2 {class}.{field} getter")
|
|
|
|
}
|
2023-01-31 17:15:56 +00:00
|
|
|
Stub::Avm2Setter {
|
|
|
|
class,
|
|
|
|
property: field,
|
|
|
|
} => {
|
2023-01-31 17:09:42 +00:00
|
|
|
write!(f, "AVM2 {class}.{field} setter")
|
2023-01-31 15:45:14 +00:00
|
|
|
}
|
2023-01-31 17:15:56 +00:00
|
|
|
Stub::Avm2Constructor { class } => {
|
|
|
|
write!(f, "AVM2 {class} constructor")
|
|
|
|
}
|
2023-01-31 15:45:14 +00:00
|
|
|
Stub::Other(text) => write!(f, "{text}"),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#[derive(Debug, Default)]
|
|
|
|
pub struct StubCollection {
|
|
|
|
inner: FnvHashSet<Stub>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl StubCollection {
|
|
|
|
pub fn new() -> Self {
|
|
|
|
Self::default()
|
|
|
|
}
|
|
|
|
|
2023-01-31 16:45:49 +00:00
|
|
|
pub fn encounter(&mut self, stub: &Stub) {
|
|
|
|
if !self.inner.contains(stub) {
|
2023-01-31 15:45:14 +00:00
|
|
|
tracing::warn!("Encountered stub: {stub}");
|
2023-01-31 16:45:49 +00:00
|
|
|
self.inner.insert(stub.clone());
|
2023-01-31 15:45:14 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
pub fn iter(&self) -> Iter<Stub> {
|
|
|
|
self.inner.iter()
|
|
|
|
}
|
|
|
|
}
|