1use synth_core::{Component, CoreModule, Error, Export, ExportKind, Memory, Result};
4use wasmparser::{Parser, Payload};
5
6pub struct ComponentParser;
8
9impl ComponentParser {
10 pub fn new() -> Self {
12 Self
13 }
14
15 pub fn parse(&self, bytes: &[u8]) -> Result<Component> {
17 let parser = Parser::new(0);
18
19 let mut component = Component::new("main".to_string());
22
23 for payload in parser.parse_all(bytes) {
24 let payload =
25 payload.map_err(|e| Error::parse(format!("WebAssembly parse error: {}", e)))?;
26
27 match payload {
28 Payload::Version { .. } => {
29 }
31 Payload::ModuleSection { .. } => {
32 }
35 Payload::TypeSection(reader) => {
36 for ty in reader {
38 let _ty =
39 ty.map_err(|e| Error::parse(format!("Failed to parse type: {}", e)))?;
40 }
42 }
43 Payload::FunctionSection(reader) => {
44 for func in reader {
46 let _func_type_idx = func.map_err(|e| {
47 Error::parse(format!("Failed to parse function: {}", e))
48 })?;
49 }
51 }
52 Payload::MemorySection(reader) => {
53 let mut memories = Vec::new();
55 for (index, memory) in reader.into_iter().enumerate() {
56 let mem = memory
57 .map_err(|e| Error::parse(format!("Failed to parse memory: {}", e)))?;
58
59 memories.push(Memory {
60 index: index as u32,
61 initial: mem.initial as u32,
62 maximum: mem.maximum.map(|m| m as u32),
63 shared: mem.shared,
64 memory64: mem.memory64,
65 });
66 }
67
68 if component.modules.is_empty() {
70 let module = CoreModule {
71 id: "module0".to_string(),
72 binary: bytes.to_vec(),
73 functions: Vec::new(),
74 memories,
75 tables: Vec::new(),
76 globals: Vec::new(),
77 };
78 component.modules.push(module);
79 } else {
80 component.modules[0].memories.extend(memories);
81 }
82 }
83 Payload::ExportSection(reader) => {
84 for export in reader {
86 let export = export
87 .map_err(|e| Error::parse(format!("Failed to parse export: {}", e)))?;
88
89 let kind = match export.kind {
90 wasmparser::ExternalKind::Func => ExportKind::Function(export.index),
91 wasmparser::ExternalKind::Memory => ExportKind::Memory(export.index),
92 wasmparser::ExternalKind::Table => ExportKind::Table(export.index),
93 wasmparser::ExternalKind::Global => ExportKind::Global(export.index),
94 _ => continue,
95 };
96
97 component.exports.push(Export {
98 name: export.name.to_string(),
99 kind,
100 });
101 }
102 }
103 Payload::CodeSectionEntry(body) => {
104 let _locals = body
107 .get_locals_reader()
108 .map_err(|e| Error::parse(format!("Failed to parse locals: {}", e)))?;
109 }
110 _ => {
111 }
113 }
114 }
115
116 if component.modules.is_empty() {
118 let module = CoreModule {
119 id: "module0".to_string(),
120 binary: bytes.to_vec(),
121 functions: Vec::new(),
122 memories: Vec::new(),
123 tables: Vec::new(),
124 globals: Vec::new(),
125 };
126 component.modules.push(module);
127 }
128
129 Ok(component)
130 }
131}
132
133impl Default for ComponentParser {
134 fn default() -> Self {
135 Self::new()
136 }
137}
138
139#[cfg(test)]
140mod tests {
141 use super::*;
142
143 #[test]
144 fn test_parse_empty_module() {
145 let wasm = vec![
147 0x00, 0x61, 0x73, 0x6D, 0x01, 0x00, 0x00, 0x00, ];
150
151 let parser = ComponentParser::new();
152 let result = parser.parse(&wasm);
153 assert!(result.is_ok());
154 }
155}