gaia_assembler/config/
mod.rs

1//! 配置管理模块
2//!
3//! 本模块负责加载和管理Gaia汇编器的配置,包括平台映射、适配器配置等。
4//! 支持从TOML配置文件动态加载配置信息。
5
6use 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/// 函数映射配置
14///
15/// 定义了通用函数名到平台特定函数名的映射关系
16#[derive(Debug, Clone, Serialize, Deserialize)]
17pub struct FunctionMapping {
18    /// 通用函数名
19    pub common_name: String,
20    /// 平台特定映射
21    pub platform_mappings: HashMap<String, String>,
22    /// 函数描述
23    pub description: Option<String>,
24}
25
26/// 平台配置
27///
28/// 包含特定平台的配置信息
29#[derive(Debug, Clone, Serialize, Deserialize)]
30pub struct PlatformConfig {
31    /// 编译目标
32    pub target: CompilationTarget,
33    /// 平台描述
34    pub description: Option<String>,
35    /// 支持的架构
36    pub supported_architectures: Vec<String>,
37    /// 默认文件扩展名
38    pub default_extension: String,
39    /// 平台特定参数
40    pub parameters: HashMap<String, String>,
41}
42
43/// 适配器配置
44///
45/// 包含适配器的配置信息
46#[derive(Debug, Clone, Serialize, Deserialize)]
47pub struct AdapterConfigEntry {
48    /// 适配器名称
49    pub name: String,
50    /// 适配器类型 (export/import)
51    pub adapter_type: String,
52    /// 编译目标
53    pub compilation_target: CompilationTarget,
54    /// 是否启用
55    pub enabled: bool,
56    /// 适配器参数
57    pub parameters: HashMap<String, String>,
58}
59
60/// 全局配置
61///
62/// 包含全局设置参数
63#[derive(Debug, Clone, Serialize, Deserialize)]
64pub struct GlobalConfig {
65    /// 默认输出目录
66    pub default_output_dir: String,
67    /// 是否启用调试模式
68    pub debug_mode: bool,
69    /// 全局参数
70    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    /// static part when load
81    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/// Gaia汇编器主配置
100#[derive(Debug, Clone, Serialize, Deserialize)]
101pub struct GaiaSettings {
102    /// 配置版本
103    pub version: String,
104    /// 全局设置
105    pub global: GlobalConfig,
106    /// 平台配置映射
107    pub platforms: HashMap<CompilationTarget, PlatformConfig>,
108    /// 函数映射列表
109    pub function_mappings: Vec<FunctionMapping>,
110    /// 适配器配置列表
111    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
163/// 配置管理器
164///
165/// 负责加载、保存和管理配置信息
166pub struct ConfigManager {
167    /// 当前配置
168    config: GaiaSettings,
169    /// 配置文件路径
170    config_path: Option<String>,
171}
172
173impl ConfigManager {
174    /// 创建新的配置管理器
175    pub fn new() -> Self {
176        Self { config: GaiaSettings::default(), config_path: None }
177    }
178
179    /// 从文件加载配置
180    ///
181    /// # 参数
182    /// * `path` - 配置文件路径
183    ///
184    /// # 返回值
185    /// 加载成功返回Ok(()),失败返回错误信息
186    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    /// 保存配置到文件
199    ///
200    /// # 参数
201    /// * `path` - 配置文件路径,如果为None则使用当前路径
202    ///
203    /// # 返回值
204    /// 保存成功返回Ok(()),失败返回错误信息
205    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    /// 获取当前配置
226    pub fn config(&self) -> &GaiaSettings {
227        &self.config
228    }
229
230    /// 获取可变配置
231    pub fn config_mut(&mut self) -> &mut GaiaSettings {
232        &mut self.config
233    }
234
235    /// 获取函数映射
236    ///
237    /// # 参数
238    /// * `common_name` - 通用函数名
239    /// * `platform` - 目标平台
240    ///
241    /// # 返回值
242    /// 找到返回平台特定函数名,未找到返回None
243    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    /// 添加函数映射
253    ///
254    /// # 参数
255    /// * `mapping` - 函数映射配置
256    pub fn add_function_mapping(&mut self, mapping: FunctionMapping) {
257        // 检查是否已存在同名映射
258        if let Some(existing) = self.config.function_mappings.iter_mut().find(|m| m.common_name == mapping.common_name) {
259            // 合并平台映射
260            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    /// 获取平台配置
271    ///
272    /// # 参数
273    /// * `platform_name` - 平台名称
274    ///
275    /// # 返回值
276    /// 找到返回平台配置,未找到返回None
277    pub fn get_platform_config(&self, target: &CompilationTarget) -> Option<&PlatformConfig> {
278        self.config.platforms.get(target)
279    }
280
281    /// 添加平台配置
282    ///
283    /// # 参数
284    /// * `target` - 编译目标
285    /// * `platform` - 平台配置
286    pub fn add_platform_config(&mut self, target: CompilationTarget, platform: PlatformConfig) {
287        self.config.platforms.insert(target, platform);
288    }
289
290    /// 获取适配器配置
291    ///
292    /// # 参数
293    /// * `adapter_name` - 适配器名称
294    ///
295    /// # 返回值
296    /// 找到返回适配器配置,未找到返回None
297    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    /// 添加适配器配置
302    ///
303    /// # 参数
304    /// * `adapter` - 适配器配置
305    pub fn add_adapter_config(&mut self, adapter: AdapterConfigEntry) {
306        // 检查是否已存在同名适配器
307        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    /// 获取全局设置
316    ///
317    /// # 参数
318    /// * `key` - 设置键
319    ///
320    /// # 返回值
321    /// 找到返回设置值,未找到返回None
322    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    /// 设置全局设置
327    ///
328    /// # 参数
329    /// * `key` - 设置键
330    /// * `value` - 设置值
331    pub fn set_global_setting(&mut self, key: String, value: String) {
332        self.config.global.parameters.insert(key, value);
333    }
334
335    /// 验证配置
336    ///
337    /// # 返回值
338    /// 配置有效返回Ok(()),无效返回错误信息
339    pub fn validate(&self) -> Result<()> {
340        // 验证平台配置
341        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        // 验证适配器配置
351        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            // 验证目标平台是否存在
362            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}