moduforge-runtime 0.2.4

插件加载、热更新、依赖管理
Documentation
use std::collections::HashMap;

use moduforge_model::schema::{AttributeSpec, Schema, SchemaSpec};

use crate::types::{Extensions, GlobalAttributeItem};

pub fn get_schema_by_resolved_extensions(
    extensions: &Vec<Extensions>
) -> Result<Schema, Box<dyn std::error::Error>> {
    let mut extension_attributes = vec![];
    for extension in extensions {
        if let Extensions::E(extension) = extension {
            for item in extension.get_global_attributes().iter() {
                extension_attributes.push(item);
            }
        }
    }
    let mut nodes = HashMap::new();
    let mut marks = HashMap::new();
    let mut top_name = "doc".to_string();
    for extension in extensions {
        match extension {
            Extensions::N(node) => {
                let name = node.name.clone();
                if node.is_top_node() {
                    top_name = node.name.clone();
                }
                let mut attrs = get_attr_dfn(name, &extension_attributes);

                let attrs_def = match &node.r#type.attrs {
                    Some(m) => {
                        m.iter().for_each(|e| {
                            attrs.insert(e.0.clone(), e.1.clone());
                        });
                        attrs
                    },
                    None => attrs,
                };
                let mut t = node.r#type.clone();
                t.attrs = Some(attrs_def);
                nodes.insert(node.name.clone(), t);
            },
            Extensions::M(mark) => {
                marks.insert(mark.name.clone(), mark.r#type.clone());
            },
            _ => {},
        }
    }
    let instance_spec = SchemaSpec { nodes, marks, top_node: Some(top_name) };
    let schema = Schema::compile(instance_spec)?;
    Ok(schema)
}

fn get_attr_dfn(
    name: String,
    extension_attributes: &Vec<&GlobalAttributeItem>,
) -> HashMap<String, AttributeSpec> {
    let mut attributes: HashMap<String, AttributeSpec> = HashMap::new();
    for attr in extension_attributes.iter() {
        if attr.types.contains(&name) {
            attr.attributes.iter().for_each(|e| {
                attributes.insert(e.0.clone(), e.1.clone());
            });
        }
    }
    attributes
}