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