use wasmi::Module;
pub const IMPLEMENTED: &[&str] = &[
"proxy_log",
"proxy_get_buffer_bytes",
"proxy_get_header_map_pairs",
"proxy_get_header_map_value",
"proxy_get_property",
"proxy_send_local_response",
"proxy_get_current_time_nanoseconds",
"proxy_set_tick_period_milliseconds",
];
pub const SEMANTIC: &[&str] = &[
"proxy_http_call",
"proxy_dispatch_http_call",
"proxy_get_shared_data",
"proxy_set_shared_data",
"proxy_register_shared_queue",
"proxy_resolve_shared_queue",
"proxy_enqueue_shared_queue",
"proxy_dequeue_shared_queue",
"proxy_set_header_map_pairs",
"proxy_replace_header_map_value",
"proxy_add_header_map_value",
"proxy_remove_header_map_value",
"proxy_set_property",
"proxy_set_buffer_bytes",
"proxy_call_foreign_function",
"proxy_grpc_call",
"proxy_grpc_stream",
"proxy_grpc_send",
"proxy_grpc_cancel",
"proxy_grpc_close",
];
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum StubClass {
Cosmetic,
Semantic,
}
#[derive(Debug, Clone, Default)]
pub struct ImportReport {
pub stubbed: Vec<(String, StubClass)>,
pub implemented_used: Vec<String>,
}
impl ImportReport {
pub fn semantic_linked(&self) -> usize {
self.stubbed.iter().filter(|(_, c)| *c == StubClass::Semantic).count()
}
pub fn semantic_stubs(&self) -> Vec<&str> {
self.stubbed
.iter()
.filter(|(_, c)| *c == StubClass::Semantic)
.map(|(n, _)| n.as_str())
.collect()
}
pub fn summary(&self) -> String {
let semantic = self.semantic_linked();
let cosmetic = self.stubbed.len() - semantic;
format!(
"WASM import: {} implemented, {} stubbed ({} semantic-capable, {} cosmetic); \
semantic host calls return Unimplemented IF the plugin invokes them at runtime",
self.implemented_used.len(),
self.stubbed.len(),
semantic,
cosmetic,
)
}
}
pub fn classify(module: &Module) -> ImportReport {
let mut report = ImportReport::default();
for import in module.imports() {
if import.ty().func().is_none() {
continue;
}
let name = import.name();
if IMPLEMENTED.contains(&name) {
report.implemented_used.push(name.to_string());
} else if SEMANTIC.contains(&name) {
report.stubbed.push((name.to_string(), StubClass::Semantic));
} else {
report.stubbed.push((name.to_string(), StubClass::Cosmetic));
}
}
report
}