moduforge_runtime/helpers/
get_schema_by_resolved_extensions.rs

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