1use crate::error::error_helpers::schema_error;
2use crate::error::PoolResult;
3
4use super::attrs::Attrs;
5use super::content::ContentMatch;
6use super::mark_type::{MarkSpec, MarkType};
7use super::node_type::{NodeSpec, NodeType};
8use serde::Serialize;
9use serde_json::Value;
10use std::any::Any;
11use std::collections::HashMap;
12use std::sync::{Arc, Mutex};
13#[derive(Clone, PartialEq, Eq, Hash, Debug, Serialize)]
16pub struct Attribute {
17 pub has_default: bool,
18 pub default: Option<Value>,
19}
20
21impl Attribute {
22 pub(crate) fn new(options: AttributeSpec) -> Self {
24 Attribute {
25 has_default: options.default.is_some(),
26 default: options.default,
27 }
28 }
29 pub fn is_required(&self) -> bool {
32 !self.has_default
33 }
34}
35#[derive(Clone, Debug)]
38pub struct Schema {
39 pub spec: SchemaSpec,
41 pub top_node_type: Option<NodeType>,
43 pub cached: Arc<Mutex<HashMap<String, Arc<dyn Any + Send + Sync>>>>,
45 pub nodes: HashMap<String, NodeType>,
47 pub marks: HashMap<String, MarkType>,
49}
50impl PartialEq for Schema {
51 fn eq(
52 &self,
53 other: &Self,
54 ) -> bool {
55 self.spec == other.spec
56 && self.top_node_type == other.top_node_type
57 && self.nodes == other.nodes
58 && self.marks == other.marks
59 }
60}
61impl Eq for Schema {}
62impl Schema {
63 pub fn new(spec: SchemaSpec) -> Self {
65 let mut instance_spec = SchemaSpec {
66 nodes: HashMap::new(),
67 marks: HashMap::new(),
68 top_node: spec.top_node,
69 };
70 for (key, value) in spec.nodes {
72 instance_spec.nodes.insert(key, value);
73 }
74 for (key, value) in spec.marks {
75 instance_spec.marks.insert(key, value);
76 }
77 Schema {
78 spec: instance_spec,
79 top_node_type: None,
80 cached: Arc::new(Mutex::new(HashMap::new())),
81 nodes: HashMap::new(),
82 marks: HashMap::new(),
83 }
84 }
85 pub fn compile(instance_spec: SchemaSpec) -> PoolResult<Schema> {
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(schema_error(&format!(
97 "{prop} 不能既是节点又是标记"
98 )));
99 }
100
101 let content_expr = type_.spec.content.as_deref().unwrap_or("");
102 let mark_expr = type_.spec.marks.as_deref();
103
104 let content_expr_string = content_expr.to_string();
105 let content_match = content_expr_cache
106 .entry(content_expr_string.clone())
107 .or_insert_with(|| {
108 ContentMatch::parse(content_expr_string, &nodes)
109 })
110 .clone();
111
112 let mark_set = match mark_expr {
113 Some("_") => None,
114 Some(expr) => {
115 let marks_result =
116 gather_marks(&marks, expr.split_whitespace().collect());
117 match marks_result {
118 Ok(marks) => Some(marks.into_iter().cloned().collect()), Err(e) => return Err(schema_error(&e)),
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 = match schema.nodes.get(
133 &schema.spec.top_node.clone().unwrap_or_else(|| "doc".to_string()),
134 ) {
135 Some(node) => Some(node.clone()),
136 None => {
137 return Err(schema_error("未找到顶级节点类型定义"));
138 },
139 };
140
141 Ok(schema)
142 }
143}
144#[derive(Clone, PartialEq, Eq, Debug)]
147pub struct SchemaSpec {
148 pub nodes: HashMap<String, NodeSpec>,
149 pub marks: HashMap<String, MarkSpec>,
150 pub top_node: Option<String>,
151}
152
153pub fn default_attrs(
158 attrs: &HashMap<String, Attribute>
159) -> Option<HashMap<String, Value>> {
160 let mut defaults = HashMap::new();
161
162 for (attr_name, attr) in attrs {
163 if let Some(default) = &attr.default {
164 defaults.insert(attr_name.clone(), default.clone());
165 } else {
166 return None;
167 }
168 }
169
170 Some(defaults)
171}
172#[derive(Clone, PartialEq, Debug, Eq, Hash, Serialize)]
174pub struct AttributeSpec {
175 pub default: Option<Value>,
177}
178fn gather_marks<'a>(
181 marks_map: &'a HashMap<String, MarkType>,
182 marks: Vec<&'a str>,
183) -> Result<Vec<&'a MarkType>, String> {
184 let mut found = Vec::new();
185
186 for name in marks {
187 if let Some(mark) = marks_map.get(name) {
188 found.push(mark);
189 } else if name == "_" {
190 found.extend(marks_map.values());
192 } else {
193 let mut matched = false;
195 for mark_ref in marks_map.values() {
196 if mark_ref.spec.group.as_ref().is_some_and(|group| {
197 group.split_whitespace().any(|g| g == name)
198 }) {
199 found.push(mark_ref);
200 matched = true;
201 break;
202 }
203 }
204 if !matched {
205 return Err(format!("未知的标记类型: '{name}'"));
206 }
207 }
208 }
209 Ok(found)
210}
211pub fn compute_attrs(
214 attrs: &HashMap<String, Attribute>,
215 value: Option<&HashMap<String, Value>>,
216) -> Attrs {
217 let mut built = Attrs::default();
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[name] = given;
236 }
237
238 built
239}