moduforge_runtime/helpers/
get_schema_by_resolved_extensions.rs

1use std::collections::HashMap;
2
3use moduforge_model::schema::{AttributeSpec, Schema, SchemaSpec};
4
5use crate::types::{Extensions, GlobalAttributeItem};
6
7pub fn get_schema_by_resolved_extensions(
8    extensions: &Vec<Extensions>
9) -> Result<Schema, Box<dyn std::error::Error>> {
10    let mut extension_attributes = vec![];
11    for extension in extensions {
12        if let Extensions::E(extension) = extension {
13            for item in extension.get_global_attributes().iter() {
14                extension_attributes.push(item);
15            }
16        }
17    }
18    let mut nodes = HashMap::new();
19    let mut marks = HashMap::new();
20    let mut top_name = "doc".to_string();
21    for extension in extensions {
22        match extension {
23            Extensions::N(node) => {
24                let name = node.name.clone();
25                if node.is_top_node() {
26                    top_name = node.name.clone();
27                }
28                let mut attrs = get_attr_dfn(name, &extension_attributes);
29
30                let attrs_def = match &node.r#type.attrs {
31                    Some(m) => {
32                        m.iter().for_each(|e| {
33                            attrs.insert(e.0.clone(), e.1.clone());
34                        });
35                        attrs
36                    },
37                    None => attrs,
38                };
39                let mut t = node.r#type.clone();
40                t.attrs = Some(attrs_def);
41                nodes.insert(node.name.clone(), t);
42            },
43            Extensions::M(mark) => {
44                marks.insert(mark.name.clone(), mark.r#type.clone());
45            },
46            _ => {},
47        }
48    }
49    let instance_spec = SchemaSpec { nodes, marks, top_node: Some(top_name) };
50    let schema = Schema::compile(instance_spec)?;
51    Ok(schema)
52}
53
54fn get_attr_dfn(
55    name: String,
56    extension_attributes: &Vec<&GlobalAttributeItem>,
57) -> HashMap<String, AttributeSpec> {
58    let mut attributes: HashMap<String, AttributeSpec> = HashMap::new();
59    for attr in extension_attributes.iter() {
60        if attr.types.contains(&name) {
61            attr.attributes.iter().for_each(|e| {
62                attributes.insert(e.0.clone(), e.1.clone());
63            });
64        }
65    }
66    attributes
67}