mf_core/schema_parser/
serializer.rs1use quick_xml::events::{BytesEnd, BytesStart, Event};
2use quick_xml::Writer;
3use std::io::Cursor;
4use std::sync::Arc;
5
6use mf_model::schema::{AttributeSpec, SchemaSpec};
7
8use crate::{
9 mark::Mark,
10 node::Node,
11 types::{Extensions, GlobalAttributeItem},
12};
13
14use super::error::{XmlSchemaError, XmlSchemaResult};
15
16pub struct XmlSchemaSerializer;
18
19impl XmlSchemaSerializer {
20 pub fn schema_spec_to_string(
22 schema: &SchemaSpec
23 ) -> XmlSchemaResult<String> {
24 let mut writer = Writer::new(Cursor::new(Vec::<u8>::new()));
25
26 let mut root = BytesStart::new("schema");
28 if let Some(top) = &schema.top_node {
29 root.push_attribute(("top_node", top.as_str()));
30 }
31 writer.write_event(Event::Start(root)).map_err(map_io)?;
32
33 if !schema.nodes.is_empty() {
35 writer
36 .write_event(Event::Start(BytesStart::new("nodes")))
37 .map_err(map_io)?;
38
39 for (name, spec) in &schema.nodes {
40 let mut el = BytesStart::new("node");
41 el.push_attribute(("name", name.as_str()));
42 if let Some(group) = &spec.group {
43 el.push_attribute(("group", group.as_str()));
44 }
45 if let Some(desc) = &spec.desc {
46 el.push_attribute(("desc", desc.as_str()));
47 }
48 if let Some(content) = &spec.content {
49 el.push_attribute(("content", content.as_str()));
50 }
51 if let Some(marks) = &spec.marks {
52 el.push_attribute(("marks", marks.as_str()));
53 }
54
55 writer.write_event(Event::Start(el)).map_err(map_io)?;
56
57 if let Some(attrs) = &spec.attrs {
58 writer
59 .write_event(Event::Start(BytesStart::new("attrs")))
60 .map_err(map_io)?;
61
62 for (attr_name, attr_spec) in attrs {
63 write_attr_element(&mut writer, attr_name, attr_spec)?;
64 }
65
66 writer
67 .write_event(Event::End(BytesEnd::new("attrs")))
68 .map_err(map_io)?;
69 }
70
71 writer
72 .write_event(Event::End(BytesEnd::new("node")))
73 .map_err(map_io)?;
74 }
75
76 writer
77 .write_event(Event::End(BytesEnd::new("nodes")))
78 .map_err(map_io)?;
79 }
80
81 if !schema.marks.is_empty() {
83 writer
84 .write_event(Event::Start(BytesStart::new("marks")))
85 .map_err(map_io)?;
86
87 for (name, spec) in &schema.marks {
88 let mut el = BytesStart::new("mark");
89 el.push_attribute(("name", name.as_str()));
90 if let Some(group) = &spec.group {
91 el.push_attribute(("group", group.as_str()));
92 }
93 if let Some(desc) = &spec.desc {
94 el.push_attribute(("desc", desc.as_str()));
95 }
96 if let Some(excludes) = &spec.excludes {
97 el.push_attribute(("excludes", excludes.as_str()));
98 }
99 if let Some(spanning) = spec.spanning {
100 if spanning {
101 el.push_attribute(("spanning", "true"));
102 }
103 }
104
105 writer.write_event(Event::Start(el)).map_err(map_io)?;
106
107 if let Some(attrs) = &spec.attrs {
108 writer
109 .write_event(Event::Start(BytesStart::new("attrs")))
110 .map_err(map_io)?;
111
112 for (attr_name, attr_spec) in attrs {
113 write_attr_element(&mut writer, attr_name, attr_spec)?;
114 }
115
116 writer
117 .write_event(Event::End(BytesEnd::new("attrs")))
118 .map_err(map_io)?;
119 }
120
121 writer
122 .write_event(Event::End(BytesEnd::new("mark")))
123 .map_err(map_io)?;
124 }
125
126 writer
127 .write_event(Event::End(BytesEnd::new("marks")))
128 .map_err(map_io)?;
129 }
130
131 writer
133 .write_event(Event::End(BytesEnd::new("schema")))
134 .map_err(map_io)?;
135
136 let buf = writer.into_inner().into_inner();
137 let xml = String::from_utf8(buf).map_err(|e| {
138 XmlSchemaError::XmlParseError(quick_xml::Error::Io(Arc::new(
139 std::io::Error::new(
140 std::io::ErrorKind::InvalidData,
141 e.utf8_error().to_string(),
142 ),
143 )))
144 })?;
145 Ok(xml)
146 }
147
148 pub fn extensions_to_string(
151 extensions: &[Extensions],
152 top_node: Option<&str>,
153 ) -> XmlSchemaResult<String> {
154 let mut writer = Writer::new(Cursor::new(Vec::<u8>::new()));
155
156 let mut root = BytesStart::new("schema");
157 if let Some(top) = top_node {
158 root.push_attribute(("top_node", top));
159 }
160 writer.write_event(Event::Start(root)).map_err(map_io)?;
161
162 let mut nodes: Vec<&Node> = Vec::new();
164 let mut marks: Vec<&Mark> = Vec::new();
165 let mut global_attrs_sets: Vec<&[GlobalAttributeItem]> = Vec::new();
166
167 for ext in extensions {
168 match ext {
169 Extensions::N(n) => nodes.push(n),
170 Extensions::M(m) => marks.push(m),
171 Extensions::E(e) => {
172 global_attrs_sets.push(e.get_global_attributes())
173 },
174 }
175 }
176
177 if !nodes.is_empty() {
178 writer
179 .write_event(Event::Start(BytesStart::new("nodes")))
180 .map_err(map_io)?;
181 for n in nodes {
182 let mut el = BytesStart::new("node");
183 el.push_attribute(("name", n.get_name()));
184 if let Some(group) = &n.r#type.group {
185 el.push_attribute(("group", group.as_str()));
186 }
187 if let Some(desc) = &n.r#type.desc {
188 el.push_attribute(("desc", desc.as_str()));
189 }
190 if let Some(content) = &n.r#type.content {
191 el.push_attribute(("content", content.as_str()));
192 }
193 if let Some(marks_attr) = &n.r#type.marks {
194 el.push_attribute(("marks", marks_attr.as_str()));
195 }
196 writer.write_event(Event::Start(el)).map_err(map_io)?;
197
198 if let Some(attrs) = &n.r#type.attrs {
199 writer
200 .write_event(Event::Start(BytesStart::new("attrs")))
201 .map_err(map_io)?;
202 for (attr_name, attr_spec) in attrs {
203 write_attr_element(&mut writer, attr_name, attr_spec)?;
204 }
205 writer
206 .write_event(Event::End(BytesEnd::new("attrs")))
207 .map_err(map_io)?;
208 }
209
210 writer
211 .write_event(Event::End(BytesEnd::new("node")))
212 .map_err(map_io)?;
213 }
214 writer
215 .write_event(Event::End(BytesEnd::new("nodes")))
216 .map_err(map_io)?;
217 }
218
219 if !marks.is_empty() {
220 writer
221 .write_event(Event::Start(BytesStart::new("marks")))
222 .map_err(map_io)?;
223 for m in marks {
224 let mut el = BytesStart::new("mark");
225 el.push_attribute(("name", m.get_name()));
226 if let Some(group) = &m.r#type.group {
227 el.push_attribute(("group", group.as_str()));
228 }
229 if let Some(desc) = &m.r#type.desc {
230 el.push_attribute(("desc", desc.as_str()));
231 }
232 if let Some(excludes) = &m.r#type.excludes {
233 el.push_attribute(("excludes", excludes.as_str()));
234 }
235 if let Some(spanning) = m.r#type.spanning {
236 if spanning {
237 el.push_attribute(("spanning", "true"));
238 }
239 }
240 writer.write_event(Event::Start(el)).map_err(map_io)?;
241
242 if let Some(attrs) = &m.r#type.attrs {
243 writer
244 .write_event(Event::Start(BytesStart::new("attrs")))
245 .map_err(map_io)?;
246 for (attr_name, attr_spec) in attrs {
247 write_attr_element(&mut writer, attr_name, attr_spec)?;
248 }
249 writer
250 .write_event(Event::End(BytesEnd::new("attrs")))
251 .map_err(map_io)?;
252 }
253
254 writer
255 .write_event(Event::End(BytesEnd::new("mark")))
256 .map_err(map_io)?;
257 }
258 writer
259 .write_event(Event::End(BytesEnd::new("marks")))
260 .map_err(map_io)?;
261 }
262
263 let mut wrote_global = false;
265 for set in global_attrs_sets {
266 if set.is_empty() {
267 continue;
268 }
269 if !wrote_global {
270 writer
271 .write_event(Event::Start(BytesStart::new(
272 "global_attributes",
273 )))
274 .map_err(map_io)?;
275 wrote_global = true;
276 }
277 for item in set.iter() {
278 write_global_attribute(&mut writer, item)?;
279 }
280 }
281 if wrote_global {
282 writer
283 .write_event(Event::End(BytesEnd::new("global_attributes")))
284 .map_err(map_io)?;
285 }
286
287 writer
288 .write_event(Event::End(BytesEnd::new("schema")))
289 .map_err(map_io)?;
290
291 let buf = writer.into_inner().into_inner();
292 let xml = String::from_utf8(buf).map_err(|e| {
293 XmlSchemaError::XmlParseError(quick_xml::Error::Io(Arc::new(
294 std::io::Error::new(
295 std::io::ErrorKind::InvalidData,
296 e.utf8_error().to_string(),
297 ),
298 )))
299 })?;
300 Ok(xml)
301 }
302}
303
304fn write_attr_element(
305 writer: &mut Writer<Cursor<Vec<u8>>>,
306 name: &str,
307 attr: &AttributeSpec,
308) -> XmlSchemaResult<()> {
309 let mut el = BytesStart::new("attr");
310 el.push_attribute(("name", name));
311 if let Some(default) = &attr.default {
312 let s = value_to_attr_string(default);
313 el.push_attribute(("default", s.as_str()));
314 }
315 writer.write_event(Event::Empty(el)).map_err(map_io)?;
316 Ok(())
317}
318
319fn write_global_attribute(
320 writer: &mut Writer<Cursor<Vec<u8>>>,
321 item: &GlobalAttributeItem,
322) -> XmlSchemaResult<()> {
323 let mut el = BytesStart::new("global_attribute");
324 let types_value = if item.types.len() == 1 && item.types[0] == "*" {
325 "*".to_string()
326 } else {
327 item.types.join(" ")
328 };
329 el.push_attribute(("types", types_value.as_str()));
330 writer.write_event(Event::Start(el)).map_err(map_io)?;
331
332 if !item.attributes.is_empty() {
333 for (name, spec) in &item.attributes {
334 write_attr_element(writer, name, spec)?;
335 }
336 }
337
338 writer
339 .write_event(Event::End(BytesEnd::new("global_attribute")))
340 .map_err(map_io)?;
341 Ok(())
342}
343
344fn value_to_attr_string(value: &serde_json::Value) -> String {
345 match value {
346 serde_json::Value::Null => "null".to_string(),
347 serde_json::Value::Bool(b) => {
348 if *b { "true" } else { "false" }.to_string()
349 },
350 serde_json::Value::Number(n) => n.to_string(),
351 serde_json::Value::String(s) => s.clone(),
352 other => serde_json::to_string(other).unwrap_or_default(),
353 }
354}
355
356fn map_io(err: quick_xml::Error) -> XmlSchemaError {
357 XmlSchemaError::XmlParseError(err)
358}