mf_core/helpers/
runtime_common.rs

1//! 运行时公共辅助函数
2//!
3//! 此模块提供了多个运行时实现之间共享的公共功能,包括:
4//! - 扩展管理器的创建和合并逻辑
5//! - 中间件执行辅助函数
6//!
7//! 这些函数被以下运行时使用:
8//! - ForgeRuntime (runtime.rs)
9//! - ForgeActorRuntime (actor_runtime.rs)
10//! - ForgeAsyncRuntime (async_runtime.rs)
11
12use crate::{
13    config::ForgeConfig, debug::debug, extension_manager::ExtensionManager,
14    types::RuntimeOptions, ForgeResult,
15};
16
17/// 扩展管理器辅助函数
18///
19/// 提供扩展管理器的创建和合并功能,确保所有运行时使用相同的逻辑
20pub struct ExtensionManagerHelper;
21
22impl ExtensionManagerHelper {
23    /// 创建扩展管理器 - 自动处理XML schema配置并合并代码扩展
24    ///
25    /// 优先级顺序:
26    /// 1. 使用 `config.extension.xml_schema_paths` 中配置的路径
27    /// 2. 如果没有配置,尝试加载默认的 `schema/main.xml`
28    /// 3. 如果都没有,使用代码定义的扩展
29    ///
30    /// # 参数
31    /// * `runtime_options` - 运行时选项(包含代码定义的扩展)
32    /// * `forge_config` - Forge配置(包含XML路径配置)
33    ///
34    /// # 返回值
35    /// * `ForgeResult<ExtensionManager>` - 扩展管理器实例或错误
36    pub fn create_extension_manager(
37        runtime_options: &RuntimeOptions,
38        forge_config: &ForgeConfig,
39    ) -> ForgeResult<ExtensionManager> {
40        // 检查是否有配置的XML schema路径
41        if !forge_config.extension.xml_schema_paths.is_empty() {
42            debug!(
43                "使用配置的XML schema路径: {:?}",
44                forge_config.extension.xml_schema_paths
45            );
46
47            // 转换为字符串引用
48            let paths: Vec<&str> = forge_config
49                .extension
50                .xml_schema_paths
51                .iter()
52                .map(|s| s.as_str())
53                .collect();
54            let extension_manager = ExtensionManager::from_xml_files(&paths)?;
55
56            // 合并现有的扩展
57            let merged_extensions = Self::merge_extensions_with_xml(
58                runtime_options,
59                extension_manager,
60            )?;
61            return Ok(merged_extensions);
62        }
63
64        // 检查默认的 schema/main.xml 文件
65        let default_schema_path = "schema/main.xml";
66        if std::path::Path::new(default_schema_path).exists() {
67            debug!("使用默认的 schema 文件: {}", default_schema_path);
68            let extension_manager =
69                ExtensionManager::from_xml_file(default_schema_path)?;
70            let merged_extensions = Self::merge_extensions_with_xml(
71                runtime_options,
72                extension_manager,
73            )?;
74            return Ok(merged_extensions);
75        }
76
77        // 没有找到任何XML schema,使用默认配置
78        debug!("未找到XML schema配置,使用默认扩展");
79        ExtensionManager::new(&runtime_options.get_extensions())
80    }
81
82    /// 合并XML扩展和代码扩展
83    ///
84    /// 合并策略:
85    /// 1. XML扩展优先(节点和标记定义)
86    /// 2. 代码扩展补充(Extension类型,包含插件)
87    /// 3. 避免重复添加相同名称的节点/标记
88    ///
89    /// # 参数
90    /// * `runtime_options` - 运行时选项(包含代码定义的扩展)
91    /// * `xml_extension_manager` - 从XML加载的扩展管理器
92    ///
93    /// # 返回值
94    /// * `ForgeResult<ExtensionManager>` - 合并后的扩展管理器
95    pub fn merge_extensions_with_xml(
96        runtime_options: &RuntimeOptions,
97        xml_extension_manager: ExtensionManager,
98    ) -> ForgeResult<ExtensionManager> {
99        let schema = xml_extension_manager.get_schema();
100        let mut all_extensions = Vec::new();
101
102        // 先添加XML扩展(优先级更高)
103        for (name, node_type) in &schema.nodes {
104            let node = crate::node::Node::create(name, node_type.spec.clone());
105            all_extensions.push(crate::types::Extensions::N(node));
106        }
107
108        for (name, mark_type) in &schema.marks {
109            let mark = crate::mark::Mark::new(name, mark_type.spec.clone());
110            all_extensions.push(crate::types::Extensions::M(mark));
111        }
112
113        // 再添加代码扩展(避免重复)
114        for ext in runtime_options.get_extensions() {
115            let name = match &ext {
116                crate::types::Extensions::N(node) => &node.name,
117                crate::types::Extensions::M(mark) => &mark.name,
118                crate::types::Extensions::E(_) => {
119                    // 直接添加Extension扩展(包含插件),不需要检查重复
120                    all_extensions.push(ext);
121                    continue;
122                },
123            };
124
125            // 检查是否已经存在
126            let exists = match &ext {
127                crate::types::Extensions::N(_) => {
128                    schema.nodes.contains_key(name)
129                },
130                crate::types::Extensions::M(_) => {
131                    schema.marks.contains_key(name)
132                },
133                crate::types::Extensions::E(_) => false, // Extension扩展总是添加
134            };
135
136            if !exists {
137                all_extensions.push(ext);
138            }
139        }
140
141        ExtensionManager::new(&all_extensions)
142    }
143}
144
145#[cfg(test)]
146mod tests {
147    use super::*;
148
149    #[test]
150    fn test_extension_manager_helper_creation() {
151        // 基本创建测试
152        let options = RuntimeOptions::default();
153        let config = ForgeConfig::default();
154
155        // 没有XML文件时应该使用代码扩展
156        let result =
157            ExtensionManagerHelper::create_extension_manager(&options, &config);
158        assert!(result.is_ok());
159    }
160}