1use gaia_types::{
8 helpers::{AbiCompatible, ApiCompatible, Architecture, CompilationTarget},
9 GaiaError, Result,
10};
11use serde::{Deserialize, Serialize};
12use std::{collections::HashMap, fs, path::Path};
13
14#[derive(Debug, Clone, Serialize, Deserialize)]
18pub struct FunctionMapping {
19 pub common_name: String,
21 pub platform_mappings: HashMap<String, String>,
23 pub description: Option<String>,
25}
26
27#[derive(Debug, Clone, Serialize, Deserialize)]
31pub struct PlatformConfig {
32 pub target: CompilationTarget,
34 pub description: Option<String>,
36 pub supported_architectures: Vec<String>,
38 pub default_extension: String,
40 pub parameters: HashMap<String, String>,
42}
43
44#[derive(Debug, Clone, Serialize, Deserialize)]
48pub struct AdapterConfigEntry {
49 pub name: String,
51 pub adapter_type: String,
53 pub compilation_target: CompilationTarget,
55 pub enabled: bool,
57 pub parameters: HashMap<String, String>,
59}
60
61#[derive(Debug, Clone, Serialize, Deserialize)]
65pub struct GlobalConfig {
66 pub default_output_dir: String,
68 pub debug_mode: bool,
70 pub parameters: HashMap<String, String>,
72}
73
74impl Default for GlobalConfig {
75 fn default() -> Self {
76 Self { default_output_dir: "./target".to_string(), debug_mode: false, parameters: HashMap::new() }
77 }
78}
79
80#[derive(Debug, Clone)]
82pub struct GaiaConfig {
83 pub setting: GaiaSettings,
85 pub target: CompilationTarget,
87}
88
89impl Default for GaiaConfig {
90 fn default() -> Self {
91 Self {
92 setting: GaiaSettings::default(),
93 target: CompilationTarget {
94 build: Architecture::Unknown,
95 host: AbiCompatible::Unknown,
96 target: ApiCompatible::Unknown,
97 },
98 }
99 }
100}
101
102#[derive(Debug, Clone, Serialize, Deserialize)]
104pub struct GaiaSettings {
105 pub version: String,
107 pub global: GlobalConfig,
109 #[serde(with = "target_map_serde")]
111 pub platforms: HashMap<CompilationTarget, PlatformConfig>,
112 pub function_mappings: Vec<FunctionMapping>,
114 pub adapters: Vec<AdapterConfigEntry>,
116}
117
118mod target_map_serde {
119 use super::*;
120 use serde::{Deserializer, Serializer};
121 use std::str::FromStr;
122
123 pub fn serialize<S>(map: &HashMap<CompilationTarget, PlatformConfig>, serializer: S) -> std::result::Result<S::Ok, S::Error>
124 where
125 S: Serializer,
126 {
127 let string_map: HashMap<String, PlatformConfig> = map.iter().map(|(k, v)| (k.to_string(), v.clone())).collect();
128 string_map.serialize(serializer)
129 }
130
131 pub fn deserialize<'de, D>(deserializer: D) -> std::result::Result<HashMap<CompilationTarget, PlatformConfig>, D::Error>
132 where
133 D: Deserializer<'de>,
134 {
135 let string_map: HashMap<String, PlatformConfig> = HashMap::deserialize(deserializer)?;
136 let mut map = HashMap::new();
137 for (k, v) in string_map {
138 let target = parse_target(&k).map_err(serde::de::Error::custom)?;
142 map.insert(target, v);
143 }
144 Ok(map)
145 }
146
147 fn parse_target(s: &str) -> std::result::Result<CompilationTarget, String> {
148 let parts: Vec<&str> = s.split('-').collect();
149 if parts.len() != 3 {
150 return Err(format!("Invalid compilation target string: {}", s));
151 }
152
153 let build = Architecture::from_str(parts[0])?;
154 let host = AbiCompatible::from_str(parts[1])?;
155 let target = ApiCompatible::from_str(parts[2])?;
156
157 Ok(CompilationTarget { build, host, target })
158 }
159}
160
161impl Default for GaiaSettings {
162 fn default() -> Self {
163 Self {
164 version: "1.0.0".to_string(),
165 global: GlobalConfig::default(),
166 platforms: {
167 let mut platforms = HashMap::new();
168 let x64_target = CompilationTarget {
169 build: Architecture::X86_64,
170 host: AbiCompatible::PE,
171 target: ApiCompatible::MicrosoftVisualC,
172 };
173 platforms.insert(
174 x64_target.clone(),
175 PlatformConfig {
176 target: x64_target,
177 description: Some("Windows x64 Native".to_string()),
178 supported_architectures: vec!["x86_64".to_string()],
179 default_extension: ".exe".to_string(),
180 parameters: HashMap::new(),
181 },
182 );
183
184 let clr_target = CompilationTarget {
185 build: Architecture::CLR,
186 host: AbiCompatible::PE,
187 target: ApiCompatible::ClrRuntime(4),
188 };
189 platforms.insert(
190 clr_target.clone(),
191 PlatformConfig {
192 target: clr_target,
193 description: Some(".NET CLR v4.0".to_string()),
194 supported_architectures: vec!["msil".to_string()],
195 default_extension: ".exe".to_string(),
196 parameters: HashMap::new(),
197 },
198 );
199 platforms
200 },
201 function_mappings: vec![
202 FunctionMapping {
203 common_name: "__builtin_print".to_string(),
204 platform_mappings: [
205 ("PE".to_string(), "printf".to_string()),
206 ("IL".to_string(), "System.Console.WriteLine".to_string()),
207 ("JVM".to_string(), "java.lang.System.out.println".to_string()),
208 ("WASI".to_string(), "fd_write".to_string()),
209 ]
210 .into_iter()
211 .collect(),
212 description: Some("Standard output function".to_string()),
213 },
214 FunctionMapping {
215 common_name: "malloc".to_string(),
216 platform_mappings: [
217 ("PE".to_string(), "malloc".to_string()),
218 ("IL".to_string(), "System.Runtime.InteropServices.Marshal.AllocHGlobal".to_string()),
219 ("JVM".to_string(), "java.nio.ByteBuffer.allocate".to_string()),
220 ("WASI".to_string(), "memory.grow".to_string()),
221 ]
222 .into_iter()
223 .collect(),
224 description: Some("Memory allocation function".to_string()),
225 },
226 FunctionMapping {
227 common_name: "free".to_string(),
228 platform_mappings: [
229 ("PE".to_string(), "free".to_string()),
230 ("IL".to_string(), "System.Runtime.InteropServices.Marshal.FreeHGlobal".to_string()),
231 ("JVM".to_string(), "System.gc".to_string()),
232 ("WASI".to_string(), "memory.shrink".to_string()),
233 ]
234 .into_iter()
235 .collect(),
236 description: Some("Memory deallocation function".to_string()),
237 },
238 ],
239 adapters: vec![],
240 }
241 }
242}
243
244pub struct ConfigManager {
248 config: GaiaSettings,
250 config_path: Option<String>,
252}
253
254impl ConfigManager {
255 pub fn new() -> Self {
257 Self { config: GaiaSettings::default(), config_path: None }
258 }
259
260 pub fn load_from_file<P: AsRef<Path>>(&mut self, path: P) -> Result<()> {
268 let path = path.as_ref();
269 let content = fs::read_to_string(path).map_err(|e| {
270 GaiaError::config_error(Some(path.to_string_lossy()), format!("Failed to read configuration file: {}", e))
271 })?;
272
273 self.config = toml::from_str(&content).map_err(|e| {
274 GaiaError::config_error(Some(path.to_string_lossy()), format!("Failed to parse configuration file: {}", e))
275 })?;
276
277 self.config_path = Some(path.to_string_lossy().to_string());
278 Ok(())
279 }
280
281 pub fn save_to_file<P: AsRef<Path>>(&self, path: P) -> Result<()> {
289 let path = path.as_ref();
290 let content = toml::to_string_pretty(&self.config).map_err(|e| {
291 GaiaError::config_error(Some(path.to_string_lossy()), format!("Failed to serialize configuration: {}", e))
292 })?;
293
294 fs::write(path, content).map_err(|e| {
295 GaiaError::config_error(Some(path.to_string_lossy()), format!("Failed to write configuration file: {}", e))
296 })?;
297
298 Ok(())
299 }
300
301 pub fn settings(&self) -> &GaiaSettings {
303 &self.config
304 }
305
306 pub fn config(&self) -> &GaiaSettings {
308 &self.config
309 }
310
311 pub fn get_global_setting(&self, key: &str) -> Option<&str> {
313 self.config.global.parameters.get(key).map(|s| s.as_str())
314 }
315
316 pub fn set_global_setting(&mut self, key: String, value: String) {
318 self.config.global.parameters.insert(key, value);
319 }
320
321 pub fn get_platform_config(&self, target: &CompilationTarget) -> Option<&PlatformConfig> {
323 self.config.platforms.get(target)
324 }
325
326 pub fn add_platform_config(&mut self, target: CompilationTarget, config: PlatformConfig) {
328 self.config.platforms.insert(target, config);
329 }
330
331 pub fn add_adapter_config(&mut self, config: AdapterConfigEntry) {
333 self.config.adapters.push(config);
334 }
335
336 pub fn get_adapter_config(&self, name: &str) -> Option<&AdapterConfigEntry> {
338 self.config.adapters.iter().find(|a| a.name == name)
339 }
340
341 pub fn add_function_mapping(&mut self, mapping: FunctionMapping) {
343 self.config.function_mappings.push(mapping);
344 }
345
346 pub fn get_function_mapping(&self, common_name: &str, platform: &str) -> Option<&str> {
348 self.config
349 .function_mappings
350 .iter()
351 .find(|m| m.common_name == common_name)
352 .and_then(|m| m.platform_mappings.get(platform).map(|s| s.as_str()))
353 }
354
355 pub fn validate(&self) -> Result<()> {
357 Ok(())
358 }
359
360 pub fn config_path(&self) -> Option<&str> {
362 self.config_path.as_deref()
363 }
364}