1use crate::{config::GaiaSettings, instruction::GaiaInstruction, program::GaiaModule};
8use gaia_types::{
9 helpers::{AbiCompatible, ApiCompatible, Architecture, CompilationTarget},
10 GaiaError, Result,
11};
12use serde::{Deserialize, Serialize};
13use std::collections::HashMap;
14
15#[derive(Debug, Clone, Serialize, Deserialize)]
19pub struct AdapterConfig {
20 pub name: String,
22 pub compilation_target: CompilationTarget,
24 pub parameters: HashMap<String, String>,
26 pub enabled: bool,
28}
29
30#[derive(Debug, Clone)]
34pub struct AdapterMetadata {
35 pub name: String,
37 pub version: String,
39 pub compilation_target: CompilationTarget,
41 pub description: String,
43 pub supported_instructions: Vec<String>,
45}
46
47#[derive(Debug)]
49pub struct FunctionMapper {
50 mappings: HashMap<CompilationTarget, HashMap<String, String>>,
52}
53
54impl FunctionMapper {
55 pub fn new() -> Self {
57 Self::from_settings(&GaiaSettings::default())
60 }
61
62 pub fn from_config(config: &GaiaSettings) -> Result<Self> {
64 Ok(Self::from_settings(config))
65 }
66
67 fn from_settings(settings: &GaiaSettings) -> Self {
69 let mut mapper = Self { mappings: HashMap::new() };
70
71 let il_target = CompilationTarget {
73 build: Architecture::CLR,
74 host: AbiCompatible::MicrosoftIntermediateLanguage,
75 target: ApiCompatible::ClrRuntime(4),
76 };
77 let jvm_target = CompilationTarget {
78 build: Architecture::JVM,
79 host: AbiCompatible::JavaAssembly,
80 target: ApiCompatible::JvmRuntime(8),
81 };
82 let pe_target =
83 CompilationTarget { build: Architecture::X86_64, host: AbiCompatible::PE, target: ApiCompatible::MicrosoftVisualC };
84 let wasi_target = CompilationTarget {
85 build: Architecture::WASM32,
86 host: AbiCompatible::WebAssemblyTextFormat,
87 target: ApiCompatible::WASI,
88 };
89
90 let mut platform_index: HashMap<String, CompilationTarget> = HashMap::new();
91 platform_index.insert("IL".to_string(), il_target.clone());
92 platform_index.insert("JVM".to_string(), jvm_target.clone());
93 platform_index.insert("PE".to_string(), pe_target.clone());
94 platform_index.insert("WASI".to_string(), wasi_target.clone());
95
96 mapper.add_mapping(&il_target, "console.log", "void [mscorlib]System.Console::WriteLine(string)");
99 mapper.add_mapping(&il_target, "console.write", "void [mscorlib]System.Console::WriteLine(string)");
100 mapper.add_mapping(&il_target, "conosole.read", "string [mscorlib]System.Console::ReadLine()");
101 mapper.add_mapping(&il_target, "malloc", "System.Runtime.InteropServices.Marshal.AllocHGlobal");
102 mapper.add_mapping(&il_target, "free", "System.Runtime.InteropServices.Marshal.FreeHGlobal");
103 mapper.add_mapping(&il_target, "print", "void [mscorlib]System.Console::WriteLine(string)");
104 mapper.add_mapping(&il_target, "println", "void [mscorlib]System.Console::WriteLine(string)");
105
106 mapper.add_mapping(&jvm_target, "console.log", "java.lang.System.out.println");
108 mapper.add_mapping(&jvm_target, "console.write", "java.lang.System.out.println");
109 mapper.add_mapping(&jvm_target, "console.read", "java.util.Scanner.nextLine");
110 mapper.add_mapping(&jvm_target, "malloc", "java.nio.ByteBuffer.allocateDirect");
111 mapper.add_mapping(&jvm_target, "free", "System.gc");
112 mapper.add_mapping(&jvm_target, "print", "java.lang.System.out.println");
113 mapper.add_mapping(&jvm_target, "println", "java.lang.System.out.println");
114
115 mapper.add_mapping(&pe_target, "console.log", "puts");
117 mapper.add_mapping(&pe_target, "console.write", "printf");
118 mapper.add_mapping(&pe_target, "console.read", "gets_s");
119 mapper.add_mapping(&pe_target, "malloc", "HeapAlloc");
120 mapper.add_mapping(&pe_target, "free", "HeapFree");
121 mapper.add_mapping(&pe_target, "print", "puts");
122 mapper.add_mapping(&pe_target, "println", "puts");
123
124 mapper.add_mapping(&wasi_target, "console.log", "wasi_println");
126 mapper.add_mapping(&wasi_target, "console.write", "wasi_print");
127 mapper.add_mapping(&wasi_target, "console.read", "wasi_read");
128 mapper.add_mapping(&wasi_target, "malloc", "malloc");
129 mapper.add_mapping(&wasi_target, "free", "free");
130 mapper.add_mapping(&wasi_target, "print", "wasi_println");
131 mapper.add_mapping(&wasi_target, "println", "wasi_println");
132
133 for fm in &settings.function_mappings {
135 for (platform_name, target_func) in &fm.platform_mappings {
136 let key = platform_name.to_ascii_uppercase();
137 if let Some(platform_target) = platform_index.get(&key) {
138 mapper.add_mapping(platform_target, &fm.common_name, target_func);
140
141 if fm.common_name == "__builtin_print" {
143 let is_il = matches!(platform_target.host, AbiCompatible::MicrosoftIntermediateLanguage);
144 if !is_il {
146 mapper.add_mapping(platform_target, "print", target_func);
147 }
148 mapper.add_mapping(platform_target, "console.log", target_func);
149 mapper.add_mapping(platform_target, "console.write", target_func);
150 }
151 }
152 }
153 }
154
155 mapper
156 }
157
158 pub fn add_mapping(&mut self, target: &CompilationTarget, source_func: &str, target_func: &str) {
160 self.mappings
161 .entry(target.clone())
162 .or_insert_with(HashMap::new)
163 .insert(source_func.to_string(), target_func.to_string());
164 }
165
166 pub fn map_function(&self, target: &CompilationTarget, function_name: &str) -> Option<&str> {
168 self.mappings.get(target).and_then(|platform_mappings| platform_mappings.get(function_name)).map(|s| s.as_str())
169 }
170}
171
172impl Default for FunctionMapper {
173 fn default() -> Self {
174 Self::new()
175 }
176}
177
178pub trait ExportAdapter: Send + Sync {
182 fn metadata(&self) -> &AdapterMetadata;
184
185 fn configure(&mut self, config: AdapterConfig) -> Result<()>;
193
194 fn export_instruction(&self, instruction: &GaiaInstruction) -> Result<Vec<u8>>;
202
203 fn export_program(&self, program: &GaiaModule) -> Result<Vec<u8>>;
211
212 fn supports_instruction(&self, instruction: &GaiaInstruction) -> bool;
220
221 fn file_extension(&self) -> &str;
226
227 fn cleanup(&mut self) -> Result<()> {
231 Ok(())
232 }
233}
234
235pub trait ImportAdapter: Send + Sync {
239 fn metadata(&self) -> &AdapterMetadata;
241
242 fn configure(&mut self, config: AdapterConfig) -> Result<()>;
250
251 fn import_instruction(&self, data: &[u8]) -> Result<GaiaInstruction>;
259
260 fn import_program(&self, data: &[u8]) -> Result<GaiaModule>;
268
269 fn validate_format(&self, data: &[u8]) -> bool;
277
278 fn supported_extensions(&self) -> Vec<&str>;
283
284 fn cleanup(&mut self) -> Result<()> {
288 Ok(())
289 }
290}
291
292pub struct AdapterManager {
294 export_adapters: HashMap<CompilationTarget, Box<dyn ExportAdapter>>,
296 import_adapters: HashMap<CompilationTarget, Box<dyn ImportAdapter>>,
298}
299
300impl AdapterManager {
301 pub fn new() -> Self {
303 Self { export_adapters: HashMap::new(), import_adapters: HashMap::new() }
304 }
305
306 pub fn register_export_adapter(&mut self, target: CompilationTarget, adapter: Box<dyn ExportAdapter>) -> Result<()> {
315 if self.export_adapters.contains_key(&target) {
316 return Err(GaiaError::adapter_error(&format!("{:?}", target), "Export adapter already exists", None));
317 }
318 self.export_adapters.insert(target, adapter);
319 Ok(())
320 }
321
322 pub fn register_import_adapter(&mut self, target: CompilationTarget, adapter: Box<dyn ImportAdapter>) -> Result<()> {
331 if self.import_adapters.contains_key(&target) {
332 return Err(GaiaError::adapter_error(&format!("{:?}", target), "Import adapter already exists", None));
333 }
334 self.import_adapters.insert(target, adapter);
335 Ok(())
336 }
337
338 pub fn get_export_adapter(&self, target: &CompilationTarget) -> Result<&dyn ExportAdapter> {
346 self.export_adapters
347 .get(target)
348 .map(|adapter| adapter.as_ref())
349 .ok_or_else(|| GaiaError::adapter_error(&format!("{:?}", target), "Export adapter not found", None))
350 }
351
352 pub fn get_export_adapter_mut(&mut self, target: &CompilationTarget) -> Result<&mut (dyn ExportAdapter + '_)> {
360 match self.export_adapters.get_mut(target) {
361 Some(adapter) => Ok(adapter.as_mut()),
362 None => Err(GaiaError::adapter_error(&format!("{:?}", target), "Export adapter not found", None)),
363 }
364 }
365
366 pub fn get_import_adapter(&self, target: &CompilationTarget) -> Result<&dyn ImportAdapter> {
374 self.import_adapters
375 .get(target)
376 .map(|adapter| adapter.as_ref())
377 .ok_or_else(|| GaiaError::adapter_error(&format!("{:?}", target), "Import adapter not found", None))
378 }
379
380 pub fn get_import_adapter_mut(&mut self, target: &CompilationTarget) -> Result<&mut (dyn ImportAdapter + '_)> {
388 match self.import_adapters.get_mut(target) {
389 Some(adapter) => Ok(adapter.as_mut()),
390 None => Err(GaiaError::adapter_error(&format!("{:?}", target), "Import adapter not found", None)),
391 }
392 }
393
394 pub fn list_supported_targets(&self) -> Vec<CompilationTarget> {
399 let mut targets = Vec::new();
400 targets.extend(self.export_adapters.keys().cloned());
401 targets.extend(self.import_adapters.keys().cloned());
402 targets.sort_by_key(|t| format!("{:?}", t));
403 targets.dedup();
404 targets
405 }
406
407 pub fn cleanup_all(&mut self) -> Result<()> {
412 for (target, adapter) in &mut self.export_adapters {
413 if let Err(e) = adapter.cleanup() {
414 return Err(GaiaError::adapter_error(
415 &format!("{:?}", target),
416 "Failed to clean up export adapter",
417 Some(Box::new(e)),
418 ));
419 }
420 }
421
422 for (target, adapter) in &mut self.import_adapters {
423 if let Err(e) = adapter.cleanup() {
424 return Err(GaiaError::adapter_error(
425 &format!("{:?}", target),
426 "Failed to clean up import adapter",
427 Some(Box::new(e)),
428 ));
429 }
430 }
431
432 Ok(())
433 }
434}
435
436impl Default for AdapterManager {
437 fn default() -> Self {
438 Self::new()
439 }
440}