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: "./target".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 #[serde(with = "target_map_serde")]
108 pub platforms: HashMap<CompilationTarget, PlatformConfig>,
109 pub function_mappings: Vec<FunctionMapping>,
111 pub adapters: Vec<AdapterConfigEntry>,
113}
114
115mod target_map_serde {
116 use super::*;
117 use serde::{Deserializer, Serializer};
118 use std::str::FromStr;
119
120 pub fn serialize<S>(map: &HashMap<CompilationTarget, PlatformConfig>, serializer: S) -> std::result::Result<S::Ok, S::Error>
121 where
122 S: Serializer,
123 {
124 let string_map: HashMap<String, PlatformConfig> = map.iter().map(|(k, v)| (k.to_string(), v.clone())).collect();
125 string_map.serialize(serializer)
126 }
127
128 pub fn deserialize<'de, D>(deserializer: D) -> std::result::Result<HashMap<CompilationTarget, PlatformConfig>, D::Error>
129 where
130 D: Deserializer<'de>,
131 {
132 let string_map: HashMap<String, PlatformConfig> = HashMap::deserialize(deserializer)?;
133 let mut map = HashMap::new();
134 for (k, v) in string_map {
135 let target = parse_target(&k).map_err(serde::de::Error::custom)?;
139 map.insert(target, v);
140 }
141 Ok(map)
142 }
143
144 fn parse_target(s: &str) -> std::result::Result<CompilationTarget, String> {
145 let parts: Vec<&str> = s.split('-').collect();
146 if parts.len() != 3 {
147 return Err(format!("Invalid compilation target string: {}", s));
148 }
149
150 let build = Architecture::from_str(parts[0])?;
151 let host = AbiCompatible::from_str(parts[1])?;
152 let target = ApiCompatible::from_str(parts[2])?;
153
154 Ok(CompilationTarget { build, host, target })
155 }
156}
157
158impl Default for GaiaSettings {
159 fn default() -> Self {
160 Self {
161 version: "1.0.0".to_string(),
162 global: GlobalConfig::default(),
163 platforms: {
164 let mut platforms = HashMap::new();
165 let x64_target = CompilationTarget {
166 build: Architecture::X86_64,
167 host: AbiCompatible::PE,
168 target: ApiCompatible::MicrosoftVisualC,
169 };
170 platforms.insert(
171 x64_target.clone(),
172 PlatformConfig {
173 target: x64_target,
174 description: Some("Windows x64 Native".to_string()),
175 supported_architectures: vec!["x86_64".to_string()],
176 default_extension: ".exe".to_string(),
177 parameters: HashMap::new(),
178 },
179 );
180
181 let clr_target = CompilationTarget {
182 build: Architecture::CLR,
183 host: AbiCompatible::PE,
184 target: ApiCompatible::ClrRuntime(4),
185 };
186 platforms.insert(
187 clr_target.clone(),
188 PlatformConfig {
189 target: clr_target,
190 description: Some(".NET CLR v4.0".to_string()),
191 supported_architectures: vec!["msil".to_string()],
192 default_extension: ".exe".to_string(),
193 parameters: HashMap::new(),
194 },
195 );
196 platforms
197 },
198 function_mappings: vec![
199 FunctionMapping {
200 common_name: "__builtin_print".to_string(),
201 platform_mappings: [
202 ("PE".to_string(), "printf".to_string()),
203 ("IL".to_string(), "System.Console.WriteLine".to_string()),
204 ("JVM".to_string(), "java.lang.System.out.println".to_string()),
205 ("WASI".to_string(), "fd_write".to_string()),
206 ]
207 .into_iter()
208 .collect(),
209 description: Some("标准输出函数".to_string()),
210 },
211 FunctionMapping {
212 common_name: "malloc".to_string(),
213 platform_mappings: [
214 ("PE".to_string(), "malloc".to_string()),
215 ("IL".to_string(), "System.Runtime.InteropServices.Marshal.AllocHGlobal".to_string()),
216 ("JVM".to_string(), "java.nio.ByteBuffer.allocate".to_string()),
217 ("WASI".to_string(), "memory.grow".to_string()),
218 ]
219 .into_iter()
220 .collect(),
221 description: Some("内存分配函数".to_string()),
222 },
223 FunctionMapping {
224 common_name: "free".to_string(),
225 platform_mappings: [
226 ("PE".to_string(), "free".to_string()),
227 ("IL".to_string(), "System.Runtime.InteropServices.Marshal.FreeHGlobal".to_string()),
228 ("JVM".to_string(), "System.gc".to_string()),
229 ("WASI".to_string(), "memory.shrink".to_string()),
230 ]
231 .into_iter()
232 .collect(),
233 description: Some("内存释放函数".to_string()),
234 },
235 ],
236 adapters: vec![],
237 }
238 }
239}
240
241pub struct ConfigManager {
245 config: GaiaSettings,
247 config_path: Option<String>,
249}
250
251impl ConfigManager {
252 pub fn new() -> Self {
254 Self { config: GaiaSettings::default(), config_path: None }
255 }
256
257 pub fn load_from_file<P: AsRef<Path>>(&mut self, path: P) -> Result<()> {
265 let path = path.as_ref();
266 let content = fs::read_to_string(path)
267 .map_err(|e| GaiaError::config_error(Some(path.to_string_lossy()), format!("读取配置文件失败: {}", e)))?;
268
269 self.config = toml::from_str(&content)
270 .map_err(|e| GaiaError::config_error(Some(path.to_string_lossy()), format!("解析配置文件失败: {}", e)))?;
271
272 self.config_path = Some(path.to_string_lossy().to_string());
273 Ok(())
274 }
275
276 pub fn save_to_file<P: AsRef<Path>>(&self, path: P) -> Result<()> {
284 let path = path.as_ref();
285 let content = toml::to_string_pretty(&self.config)
286 .map_err(|e| GaiaError::config_error(Some(path.to_string_lossy()), format!("序列化配置失败: {}", e)))?;
287
288 fs::write(path, content)
289 .map_err(|e| GaiaError::config_error(Some(path.to_string_lossy()), format!("写入配置文件失败: {}", e)))?;
290
291 Ok(())
292 }
293
294 pub fn settings(&self) -> &GaiaSettings {
296 &self.config
297 }
298
299 pub fn config(&self) -> &GaiaSettings {
301 &self.config
302 }
303
304 pub fn get_global_setting(&self, key: &str) -> Option<&str> {
306 self.config.global.parameters.get(key).map(|s| s.as_str())
307 }
308
309 pub fn set_global_setting(&mut self, key: String, value: String) {
311 self.config.global.parameters.insert(key, value);
312 }
313
314 pub fn get_platform_config(&self, target: &CompilationTarget) -> Option<&PlatformConfig> {
316 self.config.platforms.get(target)
317 }
318
319 pub fn add_platform_config(&mut self, target: CompilationTarget, config: PlatformConfig) {
321 self.config.platforms.insert(target, config);
322 }
323
324 pub fn add_adapter_config(&mut self, config: AdapterConfigEntry) {
326 self.config.adapters.push(config);
327 }
328
329 pub fn get_adapter_config(&self, name: &str) -> Option<&AdapterConfigEntry> {
331 self.config.adapters.iter().find(|a| a.name == name)
332 }
333
334 pub fn add_function_mapping(&mut self, mapping: FunctionMapping) {
336 self.config.function_mappings.push(mapping);
337 }
338
339 pub fn get_function_mapping(&self, common_name: &str, platform: &str) -> Option<&str> {
341 self.config
342 .function_mappings
343 .iter()
344 .find(|m| m.common_name == common_name)
345 .and_then(|m| m.platform_mappings.get(platform).map(|s| s.as_str()))
346 }
347
348 pub fn validate(&self) -> Result<()> {
350 Ok(())
351 }
352
353 pub fn config_path(&self) -> Option<&str> {
355 self.config_path.as_deref()
356 }
357}