composable_interceptor/
lib.rs1pub(crate) mod builder;
14pub(crate) mod encoder;
15pub(crate) mod extractor;
16pub(crate) mod generator;
17pub(crate) mod matcher;
18pub(crate) mod types;
19
20use std::path::Path;
21
22use anyhow::Result;
23
24use matcher::Pattern;
25use types::*;
26
27pub fn create_from_wit(wit_path: &Path, world: &str, patterns: &[&str]) -> Result<Vec<u8>> {
35 let patterns = parse_patterns(patterns)?;
36 let target = extractor::extract_from_wit(wit_path, world, &patterns)?;
37 create_and_validate(target)
38}
39
40pub fn create_from_component(component: &[u8], patterns: &[&str]) -> Result<Vec<u8>> {
50 let patterns = parse_patterns(patterns)?;
51 let target = extractor::extract_from_wasm(component, &patterns)?;
52 create_and_validate(target)
53}
54
55fn parse_patterns(patterns: &[&str]) -> Result<Vec<Pattern>> {
56 patterns
57 .iter()
58 .map(|s| Pattern::parse(s))
59 .collect::<Result<Vec<_>>>()
60}
61
62fn create_and_validate(target: TargetWorld) -> Result<Vec<u8>> {
63 if target.exports.is_empty() {
64 anyhow::bail!(
65 "No exports found in world '{}'",
66 target.resolve().worlds[target.world_id].name
67 );
68 }
69
70 for we in &target.exports {
71 match we {
72 WorldExport::Interface(ie) => {
73 let intercepted = ie
74 .functions
75 .iter()
76 .filter(|fe| matches!(fe, FunctionExport::Intercepted(_)))
77 .count();
78 let bypassed = ie.functions.len() - intercepted;
79 tracing::info!(
80 "{}: {} intercepted, {} bypassed",
81 ie.full_name,
82 intercepted,
83 bypassed
84 );
85 }
86 WorldExport::Function(fe) => {
87 let status = match fe {
88 FunctionExport::Intercepted(_) => "intercepted",
89 FunctionExport::Bypassed(_) => "bypassed",
90 };
91 tracing::info!("{}: {status}", fe.name());
92 }
93 }
94 }
95
96 let component_bytes = create(&target)?;
97
98 wasmparser::Validator::new_with_features(wasmparser::WasmFeatures::all())
99 .validate_all(&component_bytes)
100 .map_err(|e| anyhow::anyhow!("Validation failed: {e}"))?;
101
102 tracing::info!("Validation passed");
103
104 Ok(component_bytes)
105}
106
107fn create(target: &TargetWorld) -> Result<Vec<u8>> {
109 let (intercepted, core_bytes, shim_bytes, fixup_bytes) = generator::generate_modules(target)?;
110
111 if intercepted.is_empty() {
112 anyhow::bail!("No intercepted functions");
113 }
114
115 builder::build(target, &intercepted, core_bytes, shim_bytes, fixup_bytes)
116}