moduforge_model/
schema.rs

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