1#![doc = include_str!("readme.md")]
2
3use gaia_types::{GaiaError, Result};
4use std::{collections::HashMap, fmt};
5
6#[derive(Debug, Clone)]
10pub struct WasiProgram {
11 pub program_type: WasiProgramType,
13 pub name: Option<String>,
15 pub function_types: Vec<WasiFunctionType>,
17 pub functions: Vec<WasiFunction>,
19 pub exports: Vec<WasiExport>,
21 pub imports: Vec<WasiImport>,
23 pub memories: Vec<WasiMemory>,
25 pub tables: Vec<WasiTable>,
27 pub globals: Vec<WasiGlobal>,
29 pub custom_sections: Vec<WasiCustomSection>,
31 pub start_function: Option<u32>,
33 pub component_items: Vec<WasiComponentItem>,
35 pub core_modules: Vec<WasiCoreModule>,
37 pub instances: Vec<WasiInstance>,
39 pub aliases: Vec<WasiAlias>,
41 pub symbol_table: HashMap<String, WasiSymbol>,
43}
44
45#[derive(Copy, Clone, Debug, Default)]
46pub struct WasmInfo {
47 pub magic_head: [u8; 4],
48}
49
50#[derive(Debug, Clone, Copy, PartialEq)]
52pub enum WasiProgramType {
53 Component,
55 CoreModule,
57}
58
59#[derive(Debug, Clone)]
61pub enum WasiComponentItem {
62 Type(WasiTypeDefinition),
64 Alias(WasiAlias),
66 Instance(WasiInstance),
68 CoreFunc(WasiCoreFunc),
70 CoreInstance(WasiCoreInstance),
72}
73
74#[derive(Debug, Clone)]
76pub struct WasiCoreModule {
77 pub name: Option<String>,
79 pub index: u32,
81 pub function_types: Vec<WasiFunctionType>,
83 pub functions: Vec<WasiFunction>,
85 pub exports: Vec<WasiExport>,
87 pub imports: Vec<WasiImport>,
89 pub memories: Vec<WasiMemory>,
91 pub tables: Vec<WasiTable>,
93 pub globals: Vec<WasiGlobal>,
95 pub data_segments: Vec<WasiDataSegment>,
97 pub element_segments: Vec<WasiElementSegment>,
99 pub start_function: Option<u32>,
101}
102
103#[derive(Debug, Clone)]
105pub struct WasiInstance {
106 pub name: Option<String>,
108 pub index: u32,
110 pub instantiate_target: String,
112 pub args: Vec<WasiInstanceArg>,
114 pub instance_type: WasiInstanceType,
116}
117
118#[derive(Debug, Clone)]
120pub enum WasiInstanceType {
121 CoreModule,
123 Component,
125}
126
127#[derive(Debug, Clone)]
129pub struct WasiInstanceArg {
130 pub name: String,
132 pub value: String,
134}
135
136#[derive(Debug, Clone)]
138pub struct WasiAlias {
139 pub name: Option<String>,
141 pub target: WasiAliasTarget,
143}
144
145#[derive(Debug, Clone)]
147pub enum WasiAliasTarget {
148 Outer {
150 outer_index: u32,
152 item_index: u32,
154 },
155 Core {
157 core_type: WasiCoreType,
159 item_index: u32,
161 },
162 Export {
164 instance: String,
166 name: String,
168 },
169 CoreExport {
171 instance: String,
173 name: String,
175 },
176}
177
178#[derive(Debug, Clone, Copy)]
180pub enum WasiCoreType {
181 Module,
182 Func,
183 Table,
184 Memory,
185 Global,
186}
187
188#[derive(Debug, Clone)]
190pub struct WasiTypeDefinition {
191 pub name: Option<String>,
193 pub index: u32,
195 pub type_content: WasiType,
197}
198
199#[derive(Debug, Clone)]
201pub enum WasiType {
202 Func(WasiFunctionType),
204 Interface(String),
206 Instance(String),
208 Resource(WasiResourceType),
210 Record(Vec<WasiRecordField>),
212 Variant(Vec<WasiVariantCase>),
214 Enum(Vec<String>),
216 Union(Vec<WasiType>),
218 Option(Box<WasiType>),
220 List(Box<WasiType>),
222 Tuple(Vec<WasiType>),
224 Flags(Vec<String>),
226 Future(Option<Box<WasiType>>),
228 Stream(Option<Box<WasiType>>),
230 Primitive(WasiPrimitiveType),
232}
233
234#[derive(Debug, Clone)]
236pub struct WasiResourceType {
237 pub name: String,
239 pub methods: Vec<WasiResourceMethod>,
241}
242
243#[derive(Debug, Clone)]
245pub struct WasiResourceMethod {
246 pub name: String,
248 pub method_type: WasiFunctionType,
250}
251
252#[derive(Debug, Clone)]
254pub struct WasiRecordField {
255 pub name: String,
257 pub field_type: WasiType,
259}
260
261#[derive(Debug, Clone)]
263pub struct WasiVariantCase {
264 pub name: String,
266 pub case_type: Option<WasiType>,
268}
269
270#[derive(Debug, Clone, Copy)]
272pub enum WasiPrimitiveType {
273 Bool,
274 S8,
275 S16,
276 S32,
277 S64,
278 U8,
279 U16,
280 U32,
281 U64,
282 F32,
283 F64,
284 Char,
285 String,
286}
287
288#[derive(Debug, Clone)]
290pub struct WasiCoreFunc {
291 pub name: Option<String>,
293 pub index: u32,
295 pub func_type: WasiFunctionType,
297 pub canon: Option<WasiCanonicalOperation>,
299}
300
301#[derive(Debug, Clone)]
303pub enum WasiCanonicalOperation {
304 Lower {
306 func: String,
308 options: Vec<WasiCanonOption>,
310 },
311 Lift {
313 func: String,
315 options: Vec<WasiCanonOption>,
317 },
318 ResourceNew(String),
320 ResourceDrop(String),
322 ResourceRep(String),
324}
325
326#[derive(Debug, Clone)]
328pub enum WasiCanonOption {
329 StringEncoding(String),
331 Memory(String),
333 Realloc(String),
335 Async,
337 Callback(String),
339}
340
341#[derive(Debug, Clone)]
343pub struct WasiCoreInstance {
344 pub name: Option<String>,
346 pub index: u32,
348 pub instantiate_target: String,
350 pub args: Vec<WasiInstanceArg>,
352}
353
354#[derive(Debug, Clone)]
356pub struct WasiDataSegment {
357 pub name: Option<String>,
359 pub memory_index: Option<u32>,
361 pub offset: Vec<WasiInstruction>,
363 pub data: Vec<u8>,
365}
366
367#[derive(Debug, Clone)]
369pub struct WasiElementSegment {
370 pub name: Option<String>,
372 pub table_index: Option<u32>,
374 pub offset: Vec<WasiInstruction>,
376 pub elements: Vec<u32>,
378}
379
380#[derive(Debug, Clone)]
382pub struct WasiSymbol {
383 pub name: String,
385 pub symbol_type: WasiSymbolType,
387 pub index: u32,
389}
390
391#[derive(Debug, Clone)]
393pub enum WasiSymbolType {
394 Function,
395 Type,
396 Memory,
397 Table,
398 Global,
399 Instance,
400 Module,
401 Component,
402}
403
404#[derive(Debug, Clone, PartialEq)]
406pub struct WasiFunctionType {
407 pub params: Vec<WasmValueType>,
409 pub results: Vec<WasmValueType>,
411}
412
413#[derive(Debug, Clone, Copy, PartialEq)]
415pub enum WasmValueType {
416 I32,
417 I64,
418 F32,
419 F64,
420 V128,
421 Funcref,
422 Externref,
423}
424
425impl TryFrom<u8> for WasmValueType {
426 type Error = GaiaError;
427
428 fn try_from(value: u8) -> std::result::Result<Self, Self::Error> {
429 match value {
430 0x7F => Ok(WasmValueType::I32),
431 0x7E => Ok(WasmValueType::I64),
432 0x7D => Ok(WasmValueType::F32),
433 0x7C => Ok(WasmValueType::F64),
434 0x7B => Ok(WasmValueType::V128),
435 0x70 => Ok(WasmValueType::Funcref),
436 0x6F => Ok(WasmValueType::Externref),
437 _ => Err(GaiaError::invalid_data(&format!("Unknown value type: 0x{:02X}", value))),
438 }
439 }
440}
441
442impl fmt::Display for WasmValueType {
443 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
444 match self {
445 WasmValueType::I32 => write!(f, "i32"),
446 WasmValueType::I64 => write!(f, "i64"),
447 WasmValueType::F32 => write!(f, "f32"),
448 WasmValueType::F64 => write!(f, "f64"),
449 WasmValueType::V128 => write!(f, "v128"),
450 WasmValueType::Funcref => write!(f, "funcref"),
451 WasmValueType::Externref => write!(f, "externref"),
452 }
453 }
454}
455
456#[derive(Debug, Clone)]
458pub struct WasiFunction {
459 pub type_index: u32,
461 pub locals: Vec<WasmLocal>,
463 pub body: Vec<WasiInstruction>,
465}
466
467#[derive(Copy, Debug, Clone)]
469pub struct WasmLocal {
470 pub count: u32,
472 pub value_type: WasmValueType,
474}
475
476#[derive(Copy, Debug, Clone)]
478pub enum WasiInstruction {
479 Nop,
481 Unreachable,
483 Block {
485 block_type: Option<WasmValueType>,
486 },
487 Loop {
489 block_type: Option<WasmValueType>,
490 },
491 If {
493 block_type: Option<WasmValueType>,
494 },
495 Else,
497 End,
499 Br {
501 label_index: u32,
502 },
503 BrIf {
505 label_index: u32,
506 },
507 Return,
509 Call {
511 function_index: u32,
512 },
513 Drop,
515 Select,
517 LocalGet {
519 local_index: u32,
520 },
521 LocalSet {
523 local_index: u32,
524 },
525 I32Load {
527 offset: u32,
528 align: u32,
529 },
530 I64Load {
531 offset: u32,
532 align: u32,
533 },
534 F32Load {
535 offset: u32,
536 align: u32,
537 },
538 F64Load {
539 offset: u32,
540 align: u32,
541 },
542 I32Store {
544 offset: u32,
545 align: u32,
546 },
547 I64Store {
548 offset: u32,
549 align: u32,
550 },
551 F32Store {
552 offset: u32,
553 align: u32,
554 },
555 F64Store {
556 offset: u32,
557 align: u32,
558 },
559 StructNew {
561 type_index: u32,
562 },
563 StructGet {
564 type_index: u32,
565 field_index: u32,
566 },
567 StructSet {
568 type_index: u32,
569 field_index: u32,
570 },
571 I32Const {
573 value: i32,
574 },
575 I64Const {
576 value: i64,
577 },
578 F32Const {
579 value: f32,
580 },
581 F64Const {
582 value: f64,
583 },
584 I32Add,
586 I32Sub,
587 I32Mul,
588 I32DivS,
589 I32DivU,
590 I32RemS,
591 I32RemU,
592 I32And,
593 I32Or,
594 I32Xor,
595 I32Shl,
596 I32ShrS,
597 I32ShrU,
598 I32Rotl,
599 I32Rotr,
600 I32Eqz,
602 I32Eq,
603 I32Ne,
604 I32LtS,
605 I32LtU,
606 I32GtS,
607 I32GtU,
608 I32LeS,
609 I32LeU,
610 I32GeS,
611 I32GeU,
612 TaskBackpressure,
614 TaskReturn,
615 TaskWait,
616 TaskPoll,
617 TaskYield,
618 ErrorContextNew,
620 ErrorContextDebugMessage,
621}
622
623#[derive(Debug, Clone)]
625pub struct WasiExport {
626 pub name: String,
628 pub export_type: WasmExportType,
630}
631
632#[derive(Copy, Debug, Clone)]
634pub enum WasmExportType {
635 Function { function_index: u32 },
636 Table { table_index: u32 },
637 Memory { memory_index: u32 },
638 Global { global_index: u32 },
639}
640
641impl WasmExportType {
642 pub fn function_index(&self) -> Option<u32> {
643 match self {
644 WasmExportType::Function { function_index } => Some(*function_index),
645 _ => None,
646 }
647 }
648}
649
650#[derive(Debug, Clone)]
652pub struct WasiImport {
653 pub module: String,
655 pub field: String,
657 pub import_type: WasmImportType,
659}
660
661#[derive(Copy, Debug, Clone)]
663pub enum WasmImportType {
664 Function { type_index: u32 },
665 Table { table_type: WasmTableType },
666 Memory { memory_type: WasmMemoryType },
667 Global { global_type: WasmGlobalType },
668}
669
670#[derive(Copy, Debug, Clone)]
672pub struct WasiMemory {
673 pub memory_type: WasmMemoryType,
674}
675
676#[derive(Copy, Debug, Clone)]
678pub struct WasmMemoryType {
679 pub min: u32,
681 pub max: Option<u32>,
683}
684
685#[derive(Copy, Debug, Clone)]
687pub struct WasiTable {
688 pub table_type: WasmTableType,
689}
690
691#[derive(Copy, Debug, Clone)]
693pub struct WasmTableType {
694 pub element_type: WasmReferenceType,
696 pub min: u32,
698 pub max: Option<u32>,
700}
701
702#[derive(Copy, Debug, Clone)]
704pub enum WasmReferenceType {
705 FuncRef,
706 ExternRef,
707}
708
709#[derive(Debug, Clone)]
711pub struct WasiGlobal {
712 pub global_type: WasmGlobalType,
713 pub init_expr: Vec<WasiInstruction>,
714}
715
716#[derive(Copy, Debug, Clone)]
718pub struct WasmGlobalType {
719 pub value_type: WasmValueType,
720 pub mutable: bool,
721}
722
723#[derive(Debug, Clone)]
725pub struct WasiCustomSection {
726 pub name: String,
728 pub data: Vec<u8>,
730}
731
732impl WasiProgram {
733 pub fn new(program_type: WasiProgramType) -> Self {
735 Self {
736 program_type,
737 name: None,
738 function_types: Vec::new(),
739 functions: Vec::new(),
740 exports: Vec::new(),
741 imports: Vec::new(),
742 memories: Vec::new(),
743 tables: Vec::new(),
744 globals: Vec::new(),
745 custom_sections: Vec::new(),
746 start_function: None,
747 component_items: Vec::new(),
748 core_modules: Vec::new(),
749 instances: Vec::new(),
750 aliases: Vec::new(),
751 symbol_table: HashMap::new(),
752 }
753 }
754
755 pub fn new_component() -> Self {
757 Self::new(WasiProgramType::Component)
758 }
759
760 pub fn new_core_module() -> Self {
762 Self::new(WasiProgramType::CoreModule)
763 }
764
765 pub fn add_function_type(&mut self, func_type: WasiFunctionType) -> u32 {
767 for (index, existing_type) in self.function_types.iter().enumerate() {
769 if existing_type == &func_type {
770 return index as u32;
771 }
772 }
773
774 let index = self.function_types.len() as u32;
775 self.function_types.push(func_type);
776 index
777 }
778
779 pub fn add_function(&mut self, function: WasiFunction) -> u32 {
781 let index = self.functions.len() as u32;
782 self.functions.push(function);
783 index
784 }
785
786 pub fn add_export(&mut self, export: WasiExport) {
788 self.exports.push(export);
789 }
790
791 pub fn add_import(&mut self, import: WasiImport) {
793 self.imports.push(import);
794 }
795
796 pub fn add_memory(&mut self, memory: WasiMemory) -> u32 {
798 let index = self.memories.len() as u32;
799 self.memories.push(memory);
800 index
801 }
802
803 pub fn add_table(&mut self, table: WasiTable) -> u32 {
805 let index = self.tables.len() as u32;
806 self.tables.push(table);
807 index
808 }
809
810 pub fn add_global(&mut self, global: WasiGlobal) -> u32 {
812 let index = self.globals.len() as u32;
813 self.globals.push(global);
814 index
815 }
816
817 pub fn add_core_module(&mut self, core_module: WasiCoreModule) -> u32 {
819 let index = self.core_modules.len() as u32;
820 self.core_modules.push(core_module);
821 index
822 }
823
824 pub fn add_instance(&mut self, instance: WasiInstance) -> u32 {
826 let index = self.instances.len() as u32;
827 self.instances.push(instance);
828 index
829 }
830
831 pub fn add_alias(&mut self, alias: WasiAlias) {
833 self.aliases.push(alias);
834 }
835
836 pub fn add_symbol(&mut self, name: String, symbol_type: WasiSymbolType, index: u32) {
838 let symbol = WasiSymbol { name: name.clone(), symbol_type, index };
839 self.symbol_table.insert(name, symbol);
840 }
841
842 pub fn find_symbol(&self, name: &str) -> Option<&WasiSymbol> {
844 self.symbol_table.get(name)
845 }
846
847 pub fn validate(&self) -> Result<()> {
849 for function in &self.functions {
851 if function.type_index as usize >= self.function_types.len() {
852 return Err(GaiaError::custom_error(format!(
853 "函数类型索引 {} 超出范围,最大索引为 {}",
854 function.type_index,
855 self.function_types.len().saturating_sub(1)
856 )));
857 }
858 }
859
860 for export in &self.exports {
862 match &export.export_type {
863 WasmExportType::Function { function_index } => {
864 let total_functions =
865 self.imports.iter().filter(|imp| matches!(imp.import_type, WasmImportType::Function { .. })).count()
866 + self.functions.len();
867
868 if *function_index as usize >= total_functions {
869 return Err(GaiaError::custom_error(format!(
870 "导出函数索引 {} 超出范围,最大索引为 {}",
871 function_index,
872 total_functions.saturating_sub(1)
873 )));
874 }
875 }
876 _ => {} }
878 }
879
880 Ok(())
881 }
882
883 #[cfg(feature = "wat")]
885 pub fn to_wat(&self) -> gaia_types::Result<oak_wat::ast::WatRoot> {
886 use oak_wat::ast::{
887 WatExport, WatFunc, WatImport, WatInstruction, WatItem, WatLocal, WatModule, WatModuleField, WatParam, WatResult,
888 WatRoot, WatTypeKind,
889 };
890
891 let mut module_items = Vec::new();
892
893 for (i, import) in self.imports.iter().enumerate() {
895 let kind = match import.import_type {
896 WasmImportType::Function { .. } => "func",
897 WasmImportType::Table { .. } => "table",
898 WasmImportType::Memory { .. } => "memory",
899 WasmImportType::Global { .. } => "global",
900 };
901 let index = match import.import_type {
902 WasmImportType::Function { type_index } => type_index,
903 _ => 0, };
905
906 module_items.push(WatModuleField::Import(WatImport {
907 module: import.module.clone(),
908 name: import.field.clone(),
909 kind: kind.to_string(),
910 }));
911 }
912
913 for (i, func) in self.functions.iter().enumerate() {
915 let func_type = &self.function_types[func.type_index as usize];
916
917 let mut params = Vec::new();
918 for (j, param) in func_type.params.iter().enumerate() {
919 params.push(WatParam {
920 name: Some(format!("$p{}", j)),
921 ty: match param {
922 WasmValueType::I32 => WatTypeKind::I32,
923 WasmValueType::I64 => WatTypeKind::I64,
924 WasmValueType::F32 => WatTypeKind::F32,
925 WasmValueType::F64 => WatTypeKind::F64,
926 _ => WatTypeKind::I32, },
928 });
929 }
930
931 let mut results = Vec::new();
932 for result in &func_type.results {
933 results.push(WatResult {
934 ty: match result {
935 WasmValueType::I32 => WatTypeKind::I32,
936 WasmValueType::I64 => WatTypeKind::I64,
937 WasmValueType::F32 => WatTypeKind::F32,
938 WasmValueType::F64 => WatTypeKind::F64,
939 _ => WatTypeKind::I32, },
941 });
942 }
943
944 let mut locals = Vec::new();
945 let mut local_idx = 0;
946 for local_group in &func.locals {
947 for _ in 0..local_group.count {
948 locals.push(WatLocal {
949 name: Some(format!("$l{}", local_idx)),
950 ty: match local_group.value_type {
951 WasmValueType::I32 => WatTypeKind::I32,
952 WasmValueType::I64 => WatTypeKind::I64,
953 WasmValueType::F32 => WatTypeKind::F32,
954 WasmValueType::F64 => WatTypeKind::F64,
955 _ => WatTypeKind::I32, },
957 });
958 local_idx += 1;
959 }
960 }
961
962 let mut body = Vec::new();
963 for instr in &func.body {
964 let instr_str = match instr {
965 WasiInstruction::Nop => "nop".to_string(),
966 WasiInstruction::Unreachable => "unreachable".to_string(),
967 WasiInstruction::Return => "return".to_string(),
968 WasiInstruction::Drop => "drop".to_string(),
969 WasiInstruction::Select => "select".to_string(),
970 WasiInstruction::I32Add => "i32.add".to_string(),
971 WasiInstruction::I32Sub => "i32.sub".to_string(),
972 WasiInstruction::I32Mul => "i32.mul".to_string(),
973 WasiInstruction::I32DivS => "i32.div_s".to_string(),
974 WasiInstruction::I32DivU => "i32.div_u".to_string(),
975 WasiInstruction::I32RemS => "i32.rem_s".to_string(),
976 WasiInstruction::I32RemU => "i32.rem_u".to_string(),
977 WasiInstruction::I32And => "i32.and".to_string(),
978 WasiInstruction::I32Or => "i32.or".to_string(),
979 WasiInstruction::I32Xor => "i32.xor".to_string(),
980 WasiInstruction::I32Shl => "i32.shl".to_string(),
981 WasiInstruction::I32ShrS => "i32.shr_s".to_string(),
982 WasiInstruction::I32ShrU => "i32.shr_u".to_string(),
983 WasiInstruction::I32Rotl => "i32.rotl".to_string(),
984 WasiInstruction::I32Rotr => "i32.rotr".to_string(),
985 WasiInstruction::I32Eqz => "i32.eqz".to_string(),
986 WasiInstruction::I32Eq => "i32.eq".to_string(),
987 WasiInstruction::I32Ne => "i32.ne".to_string(),
988 WasiInstruction::I32LtS => "i32.lt_s".to_string(),
989 WasiInstruction::I32LtU => "i32.lt_u".to_string(),
990 WasiInstruction::I32GtS => "i32.gt_s".to_string(),
991 WasiInstruction::I32GtU => "i32.gt_u".to_string(),
992 WasiInstruction::I32LeS => "i32.le_s".to_string(),
993 WasiInstruction::I32LeU => "i32.le_u".to_string(),
994 WasiInstruction::I32GeS => "i32.ge_s".to_string(),
995 WasiInstruction::I32GeU => "i32.ge_u".to_string(),
996 WasiInstruction::I32Load { offset, align } => format!("i32.load offset={} align={}", offset, align),
997 WasiInstruction::I64Load { offset, align } => format!("i64.load offset={} align={}", offset, align),
998 WasiInstruction::F32Load { offset, align } => format!("f32.load offset={} align={}", offset, align),
999 WasiInstruction::F64Load { offset, align } => format!("f64.load offset={} align={}", offset, align),
1000 WasiInstruction::I32Store { offset, align } => format!("i32.store offset={} align={}", offset, align),
1001 WasiInstruction::I64Store { offset, align } => format!("i64.store offset={} align={}", offset, align),
1002 WasiInstruction::F32Store { offset, align } => format!("f32.store offset={} align={}", offset, align),
1003 WasiInstruction::F64Store { offset, align } => format!("f64.store offset={} align={}", offset, align),
1004 WasiInstruction::StructNew { type_index } => format!("struct.new {}", type_index),
1005 WasiInstruction::StructGet { type_index, field_index } => {
1006 format!("struct.get {} {}", type_index, field_index)
1007 }
1008 WasiInstruction::StructSet { type_index, field_index } => {
1009 format!("struct.set {} {}", type_index, field_index)
1010 }
1011 WasiInstruction::TaskBackpressure => "task.backpressure".to_string(),
1012 WasiInstruction::TaskReturn => "task.return".to_string(),
1013 WasiInstruction::TaskWait => "task.wait".to_string(),
1014 WasiInstruction::TaskPoll => "task.poll".to_string(),
1015 WasiInstruction::TaskYield => "task.yield".to_string(),
1016 WasiInstruction::ErrorContextNew => "error_context.new".to_string(),
1017 WasiInstruction::ErrorContextDebugMessage => "error_context.debug_message".to_string(),
1018 WasiInstruction::LocalGet { local_index } => format!("local.get {}", local_index),
1019 WasiInstruction::LocalSet { local_index } => format!("local.set {}", local_index),
1020 WasiInstruction::I32Const { value } => format!("i32.const {}", value),
1021 WasiInstruction::I64Const { value } => format!("i64.const {}", value),
1022 WasiInstruction::F32Const { value } => format!("f32.const {}", value),
1023 WasiInstruction::F64Const { value } => format!("f64.const {}", value),
1024 WasiInstruction::Call { function_index } => format!("call {}", function_index),
1025 WasiInstruction::Block { .. } => "block".to_string(),
1026 WasiInstruction::Loop { .. } => "loop".to_string(),
1027 WasiInstruction::If { .. } => "if".to_string(),
1028 WasiInstruction::Else => "else".to_string(),
1029 WasiInstruction::End => "end".to_string(),
1030 WasiInstruction::Br { label_index } => format!("br {}", label_index),
1031 WasiInstruction::BrIf { label_index } => format!("br_if {}", label_index),
1032 _ => format!(";; unknown instruction {:?}", instr),
1033 };
1034 body.push(WatInstruction::Other(instr_str, vec![]));
1035 }
1036
1037 module_items.push(WatModuleField::Func(WatFunc { name: Some(format!("$f{}", i)), params, results, locals, body }));
1038 }
1039
1040 for export in &self.exports {
1042 let (kind, index) = match export.export_type {
1043 WasmExportType::Function { function_index } => ("func", function_index),
1044 WasmExportType::Table { table_index } => ("table", table_index),
1045 WasmExportType::Memory { memory_index } => ("memory", memory_index),
1046 WasmExportType::Global { global_index } => ("global", global_index),
1047 };
1048 module_items.push(WatModuleField::Export(WatExport {
1049 name: export.name.clone(),
1050 kind: kind.to_string(),
1051 id: index.to_string(),
1052 }));
1053 }
1054
1055 let mut items = Vec::new();
1056 if self.program_type == WasiProgramType::CoreModule {
1057 let module = WatModule { name: self.name.clone(), items: module_items };
1058 items.push(WatItem::Module(module));
1059 }
1060
1061 Ok(WatRoot { items })
1062 }
1063
1064 pub fn to_wasm(&self) -> Result<Vec<u8>> {
1066 let mut writer = crate::formats::wasm::writer::WasmWriter::new(Vec::new());
1067 writer.write(self.clone()).result
1068 }
1069}
1070
1071impl Default for WasiProgram {
1072 fn default() -> Self {
1073 Self::new_core_module()
1074 }
1075}
1076
1077pub struct WasiProgramBuilder {
1079 program: WasiProgram,
1080}
1081
1082impl WasiProgramBuilder {
1083 pub fn new(program_type: WasiProgramType) -> Self {
1085 Self { program: WasiProgram::new(program_type) }
1086 }
1087
1088 pub fn with_name(mut self, name: impl Into<String>) -> Self {
1090 self.program.name = Some(name.into());
1091 self
1092 }
1093
1094 pub fn with_function_type(mut self, func_type: WasiFunctionType) -> Self {
1096 self.program.add_function_type(func_type);
1097 self
1098 }
1099
1100 pub fn with_function(mut self, function: WasiFunction) -> Self {
1102 self.program.add_function(function);
1103 self
1104 }
1105
1106 pub fn with_export(mut self, export: WasiExport) -> Self {
1108 self.program.add_export(export);
1109 self
1110 }
1111
1112 pub fn with_import(mut self, import: WasiImport) -> Self {
1114 self.program.add_import(import);
1115 self
1116 }
1117
1118 pub fn with_memory(mut self, memory: WasiMemory) -> Self {
1120 self.program.add_memory(memory);
1121 self
1122 }
1123
1124 pub fn with_table(mut self, table: WasiTable) -> Self {
1126 self.program.add_table(table);
1127 self
1128 }
1129
1130 pub fn with_global(mut self, global: WasiGlobal) -> Self {
1132 self.program.add_global(global);
1133 self
1134 }
1135
1136 pub fn with_custom_section(mut self, custom_section: WasiCustomSection) -> Self {
1138 self.program.custom_sections.push(custom_section);
1139 self
1140 }
1141
1142 pub fn with_start_function(mut self, start_function_index: u32) -> Self {
1144 self.program.start_function = Some(start_function_index);
1145 self
1146 }
1147
1148 pub fn with_component_item(mut self, item: WasiComponentItem) -> Self {
1150 self.program.component_items.push(item);
1151 self
1152 }
1153
1154 pub fn with_core_module(mut self, core_module: WasiCoreModule) -> Self {
1156 self.program.add_core_module(core_module);
1157 self
1158 }
1159
1160 pub fn with_instance(mut self, instance: WasiInstance) -> Self {
1162 self.program.add_instance(instance);
1163 self
1164 }
1165
1166 pub fn with_alias(mut self, alias: WasiAlias) -> Self {
1168 self.program.add_alias(alias);
1169 self
1170 }
1171
1172 pub fn with_symbol(mut self, name: impl Into<String>, symbol_type: WasiSymbolType, index: u32) -> Self {
1174 self.program.add_symbol(name.into(), symbol_type, index);
1175 self
1176 }
1177
1178 pub fn build(self) -> Result<WasiProgram> {
1180 self.program.validate().map(|_| self.program)
1181 }
1182}
1183
1184impl WasiProgram {
1185 pub fn builder(program_type: WasiProgramType) -> WasiProgramBuilder {
1187 WasiProgramBuilder::new(program_type)
1188 }
1189}