moduforge_core/model/
schema.rs

1use super::attrs::Attrs;
2use super::content::ContentMatch;
3use super::mark_type::{MarkSpec, MarkType};
4use super::node_type::{NodeSpec, NodeType};
5use im::HashMap as ImHashMap;
6use serde::Serialize;
7use std::any::Any;
8use std::collections::HashMap;
9use std::error::Error;
10use std::sync::{Arc, Mutex};
11/// 属性定义结构体
12/// 用于定义节点或标记的属性特征
13#[derive(Clone, PartialEq, Eq, Hash, Debug, Serialize)]
14pub struct Attribute {
15    pub has_default: bool,
16    pub default: Option<String>,
17}
18
19impl Attribute {
20    /// 从 AttributeSpec 创建新的 Attribute 实例
21    pub(crate) fn new(options: AttributeSpec) -> Self {
22        Attribute { has_default: options.default.is_some(), default: options.default }
23    }
24    /// 检查属性是否为必需的
25    /// 如果没有默认值,则属性为必需
26    pub fn is_required(&self) -> bool {
27        !self.has_default
28    }
29}
30/// Schema 结构体定义
31/// 用于管理文档模型的整体结构,包括节点和标记的类型定义
32#[derive(Clone, Debug)]
33pub struct Schema {
34    /// Schema 的规范定义
35    pub spec: SchemaSpec,
36    /// 顶级节点类型
37    pub top_node_type: Option<NodeType>,
38    /// 全局缓存
39    pub cached: Arc<Mutex<HashMap<String, Arc<dyn Any + Send + Sync>>>>,
40    /// 节点类型映射表
41    pub nodes: HashMap<String, NodeType>,
42    /// 标记类型映射表
43    pub marks: HashMap<String, MarkType>,
44}
45impl PartialEq for Schema {
46    fn eq(
47        &self,
48        other: &Self,
49    ) -> bool {
50        self.spec == other.spec
51            && self.top_node_type == other.top_node_type
52            && self.nodes == other.nodes
53            && self.marks == other.marks
54    }
55}
56impl Eq for Schema {}
57impl Schema {
58    /// 创建新的 Schema 实例
59    pub fn new(spec: SchemaSpec) -> Self {
60        let mut instance_spec = SchemaSpec { nodes: HashMap::new(), marks: HashMap::new(), top_node: spec.top_node };
61        // 复制 spec 属性
62        for (key, value) in spec.nodes {
63            instance_spec.nodes.insert(key, value);
64        }
65        for (key, value) in spec.marks {
66            instance_spec.marks.insert(key, value);
67        }
68        Schema {
69            spec: instance_spec,
70            top_node_type: None,
71            cached: Arc::new(Mutex::new(HashMap::new())),
72            nodes: HashMap::new(),
73            marks: HashMap::new(),
74        }
75    }
76    /// 编译 Schema 定义
77    /// 处理节点和标记的定义,建立它们之间的关系
78    pub fn compile(instance_spec: SchemaSpec) -> Result<Schema, Box<dyn Error>> {
79        let mut schema: Schema = Schema::new(instance_spec);
80        let nodes: HashMap<String, NodeType> = NodeType::compile(schema.spec.nodes.clone());
81        let marks = MarkType::compile(schema.spec.marks.clone());
82        let mut content_expr_cache = HashMap::new();
83        let mut updated_nodes = HashMap::new();
84        for (prop, type_) in &nodes {
85            if marks.contains_key(prop) {
86                return Err(format!("{} 不能既是节点又是标记", prop).into());
87            }
88
89            let content_expr = type_.spec.content.as_deref().unwrap_or("");
90            let mark_expr = type_.spec.marks.as_deref();
91
92            let content_match = content_expr_cache
93                .entry(content_expr.to_string())
94                .or_insert_with(|| ContentMatch::parse(content_expr.to_string(), &nodes))
95                .clone();
96
97            let mark_set = match mark_expr {
98                Some("_") => None,
99                Some(expr) => {
100                    let marks_result = gather_marks(&schema, expr.split_whitespace().collect());
101                    match marks_result {
102                        Ok(marks) => Some(marks.into_iter().cloned().collect()), // Convert Vec<&MarkType> to Vec<MarkType>
103                        Err(e) => return Err(e.into()),
104                    }
105                },
106                None => None,
107            };
108
109            let mut node = type_.clone();
110            node.content_match = Some(content_match);
111            node.mark_set = mark_set;
112            updated_nodes.insert(prop.clone(), node);
113        }
114        schema.nodes = updated_nodes;
115        schema.marks = marks;
116        schema.top_node_type =
117            schema.nodes.get(&schema.spec.top_node.clone().unwrap_or_else(|| "doc".to_string())).cloned();
118
119        Ok(schema)
120    }
121}
122/// Schema 规范定义
123/// 包含节点和标记的原始定义信息
124#[derive(Clone, PartialEq, Eq, Debug)]
125pub struct SchemaSpec {
126    pub nodes: HashMap<String, NodeSpec>,
127    pub marks: HashMap<String, MarkSpec>,
128    pub top_node: Option<String>,
129}
130
131// 其他辅助函数...
132/// 获取属性的默认值映射
133/// 如果所有属性都有默认值,返回包含所有默认值的映射
134/// 如果任一属性没有默认值,返回 None
135pub fn default_attrs(attrs: &HashMap<String, Attribute>) -> Option<HashMap<String, String>> {
136    let mut defaults = HashMap::new();
137
138    for (attr_name, attr) in attrs {
139        if let Some(default) = &attr.default {
140            defaults.insert(attr_name.clone(), default.clone());
141        } else {
142            return None;
143        }
144    }
145
146    Some(defaults)
147}
148/// 属性规范定义
149#[derive(Clone, PartialEq, Debug, Eq, Hash, Serialize)]
150pub struct AttributeSpec {
151    /// 属性的默认值
152    pub default: Option<String>,
153}
154/// 收集标记类型
155/// 根据给定的标记名称列表,收集对应的标记类型
156fn gather_marks<'a>(
157    schema: &'a Schema,
158    marks: Vec<&'a str>,
159) -> Result<Vec<&'a MarkType>, String> {
160    let mut found = Vec::new();
161
162    for name in marks {
163        if let Some(mark) = schema.marks.get(name) {
164            found.push(mark);
165        } else {
166            let mut ok = None;
167            for mark_ref in schema.marks.values() {
168                if name == "_"
169                    || mark_ref.spec.group.as_ref().is_some_and(|group| group.split_whitespace().any(|g| g == name))
170                {
171                    found.push(mark_ref);
172                    ok = Some(mark_ref);
173                    break;
174                }
175            }
176            if ok.is_none() {
177                return Err(format!("未知的标记类型: '{}'", name));
178            }
179        }
180    }
181    Ok(found)
182}
183/// 计算属性值
184/// 根据属性定义和提供的值计算最终的属性值
185pub fn compute_attrs(
186    attrs: &HashMap<String, Attribute>,
187    value: Option<&HashMap<String, String>>,
188) -> Attrs {
189    let mut built = ImHashMap::new();
190
191    for (name, attr) in attrs {
192        let given = value.and_then(|v| v.get(name));
193
194        let given = match given {
195            Some(val) => val.clone(),
196            None => {
197                if attr.has_default {
198                    attr.default.clone().unwrap_or_else(|| panic!("没有为属性提供默认值 {}", name))
199                } else {
200                    "".to_string()
201                }
202            },
203        };
204
205        built.insert(name.clone(), given);
206    }
207
208    built
209}