1use gaia_types::{
7 helpers::{AbiCompatible, ApiCompatible, Architecture, CompilationTarget},
8 GaiaError, Result,
9};
10use serde::{Deserialize, Serialize};
11use std::{collections::HashMap, fs, path::Path};
12
13#[derive(Debug, Clone, Serialize, Deserialize)]
17pub struct FunctionMapping {
18 pub common_name: String,
20 pub platform_mappings: HashMap<String, String>,
22 pub description: Option<String>,
24}
25
26#[derive(Debug, Clone, Serialize, Deserialize)]
30pub struct PlatformConfig {
31 pub target: CompilationTarget,
33 pub description: Option<String>,
35 pub supported_architectures: Vec<String>,
37 pub default_extension: String,
39 pub parameters: HashMap<String, String>,
41}
42
43#[derive(Debug, Clone, Serialize, Deserialize)]
47pub struct AdapterConfigEntry {
48 pub name: String,
50 pub adapter_type: String,
52 pub compilation_target: CompilationTarget,
54 pub enabled: bool,
56 pub parameters: HashMap<String, String>,
58}
59
60#[derive(Debug, Clone, Serialize, Deserialize)]
64pub struct GlobalConfig {
65 pub default_output_dir: String,
67 pub debug_mode: bool,
69 pub parameters: HashMap<String, String>,
71}
72
73impl Default for GlobalConfig {
74 fn default() -> Self {
75 Self { default_output_dir: "./output".to_string(), debug_mode: false, parameters: HashMap::new() }
76 }
77}
78
79pub struct GaiaConfig {
80 pub setting: GaiaSettings,
82
83 pub target: CompilationTarget,
84}
85
86impl Default for GaiaConfig {
87 fn default() -> Self {
88 Self {
89 setting: GaiaSettings::default(),
90 target: CompilationTarget {
91 build: Architecture::Unknown,
92 host: AbiCompatible::Unknown,
93 target: ApiCompatible::Unknown,
94 },
95 }
96 }
97}
98
99#[derive(Debug, Clone, Serialize, Deserialize)]
101pub struct GaiaSettings {
102 pub version: String,
104 pub global: GlobalConfig,
106 pub platforms: HashMap<CompilationTarget, PlatformConfig>,
108 pub function_mappings: Vec<FunctionMapping>,
110 pub adapters: Vec<AdapterConfigEntry>,
112}
113
114impl Default for GaiaSettings {
115 fn default() -> Self {
116 Self {
117 version: "1.0.0".to_string(),
118 global: GlobalConfig::default(),
119 platforms: HashMap::new(),
120 function_mappings: vec![
121 FunctionMapping {
122 common_name: "__builtin_print".to_string(),
123 platform_mappings: [
124 ("PE".to_string(), "printf".to_string()),
125 ("IL".to_string(), "System.Console.WriteLine".to_string()),
126 ("JVM".to_string(), "java.lang.System.out.println".to_string()),
127 ("WASI".to_string(), "fd_write".to_string()),
128 ]
129 .into_iter()
130 .collect(),
131 description: Some("标准输出函数".to_string()),
132 },
133 FunctionMapping {
134 common_name: "malloc".to_string(),
135 platform_mappings: [
136 ("PE".to_string(), "malloc".to_string()),
137 ("IL".to_string(), "System.Runtime.InteropServices.Marshal.AllocHGlobal".to_string()),
138 ("JVM".to_string(), "java.nio.ByteBuffer.allocate".to_string()),
139 ("WASI".to_string(), "memory.grow".to_string()),
140 ]
141 .into_iter()
142 .collect(),
143 description: Some("内存分配函数".to_string()),
144 },
145 FunctionMapping {
146 common_name: "free".to_string(),
147 platform_mappings: [
148 ("PE".to_string(), "free".to_string()),
149 ("IL".to_string(), "System.Runtime.InteropServices.Marshal.FreeHGlobal".to_string()),
150 ("JVM".to_string(), "System.gc".to_string()),
151 ("WASI".to_string(), "memory.shrink".to_string()),
152 ]
153 .into_iter()
154 .collect(),
155 description: Some("内存释放函数".to_string()),
156 },
157 ],
158 adapters: vec![],
159 }
160 }
161}
162
163pub struct ConfigManager {
167 config: GaiaSettings,
169 config_path: Option<String>,
171}
172
173impl ConfigManager {
174 pub fn new() -> Self {
176 Self { config: GaiaSettings::default(), config_path: None }
177 }
178
179 pub fn load_from_file<P: AsRef<Path>>(&mut self, path: P) -> Result<()> {
187 let path = path.as_ref();
188 let content = fs::read_to_string(path)
189 .map_err(|e| GaiaError::config_error(Some(path.to_string_lossy()), format!("读取配置文件失败: {}", e)))?;
190
191 self.config = toml::from_str(&content)
192 .map_err(|e| GaiaError::config_error(Some(path.to_string_lossy()), format!("解析配置文件失败: {}", e)))?;
193
194 self.config_path = Some(path.to_string_lossy().to_string());
195 Ok(())
196 }
197
198 pub fn save_to_file<P: AsRef<Path>>(&self, path: Option<P>) -> Result<()> {
206 let target_path = if let Some(path) = path {
207 path.as_ref().to_string_lossy().to_string()
208 }
209 else if let Some(ref current_path) = self.config_path {
210 current_path.clone()
211 }
212 else {
213 return Err(GaiaError::config_error(None::<String>, "未指定配置文件路径"));
214 };
215
216 let content = toml::to_string_pretty(&self.config)
217 .map_err(|e| GaiaError::config_error(Some(&target_path), format!("序列化配置失败: {}", e)))?;
218
219 fs::write(&target_path, content)
220 .map_err(|e| GaiaError::config_error(Some(&target_path), format!("写入配置文件失败: {}", e)))?;
221
222 Ok(())
223 }
224
225 pub fn config(&self) -> &GaiaSettings {
227 &self.config
228 }
229
230 pub fn config_mut(&mut self) -> &mut GaiaSettings {
232 &mut self.config
233 }
234
235 pub fn get_function_mapping(&self, common_name: &str, platform: &str) -> Option<&str> {
244 self.config
245 .function_mappings
246 .iter()
247 .find(|mapping| mapping.common_name == common_name)
248 .and_then(|mapping| mapping.platform_mappings.get(platform))
249 .map(|s| s.as_str())
250 }
251
252 pub fn add_function_mapping(&mut self, mapping: FunctionMapping) {
257 if let Some(existing) = self.config.function_mappings.iter_mut().find(|m| m.common_name == mapping.common_name) {
259 existing.platform_mappings.extend(mapping.platform_mappings);
261 if mapping.description.is_some() {
262 existing.description = mapping.description;
263 }
264 }
265 else {
266 self.config.function_mappings.push(mapping);
267 }
268 }
269
270 pub fn get_platform_config(&self, target: &CompilationTarget) -> Option<&PlatformConfig> {
278 self.config.platforms.get(target)
279 }
280
281 pub fn add_platform_config(&mut self, target: CompilationTarget, platform: PlatformConfig) {
287 self.config.platforms.insert(target, platform);
288 }
289
290 pub fn get_adapter_config(&self, adapter_name: &str) -> Option<&AdapterConfigEntry> {
298 self.config.adapters.iter().find(|adapter| adapter.name == adapter_name)
299 }
300
301 pub fn add_adapter_config(&mut self, adapter: AdapterConfigEntry) {
306 if let Some(existing) = self.config.adapters.iter_mut().find(|a| a.name == adapter.name) {
308 *existing = adapter;
309 }
310 else {
311 self.config.adapters.push(adapter);
312 }
313 }
314
315 pub fn get_global_setting(&self, key: &str) -> Option<&str> {
323 self.config.global.parameters.get(key).map(|s| s.as_str())
324 }
325
326 pub fn set_global_setting(&mut self, key: String, value: String) {
332 self.config.global.parameters.insert(key, value);
333 }
334
335 pub fn validate(&self) -> Result<()> {
340 for (target, platform) in &self.config.platforms {
342 if platform.supported_architectures.is_empty() {
343 return Err(GaiaError::config_error(
344 self.config_path.as_ref(),
345 format!("平台 '{:?}' 必须支持至少一种架构", target),
346 ));
347 }
348 }
349
350 for adapter in &self.config.adapters {
352 if adapter.name.is_empty() {
353 return Err(GaiaError::config_error(self.config_path.as_ref(), "适配器名称不能为空"));
354 }
355 if !["export", "import"].contains(&adapter.adapter_type.as_str()) {
356 return Err(GaiaError::config_error(
357 self.config_path.as_ref(),
358 format!("适配器 '{}' 的类型必须是 'export' 或 'import'", adapter.name),
359 ));
360 }
361 if !self.config.platforms.contains_key(&adapter.compilation_target) {
363 return Err(GaiaError::config_error(
364 self.config_path.as_ref(),
365 format!("适配器 '{}' 的目标平台 '{:?}' 不存在", adapter.name, adapter.compilation_target),
366 ));
367 }
368 }
369
370 Ok(())
371 }
372}
373
374impl Default for ConfigManager {
375 fn default() -> Self {
376 Self::new()
377 }
378}