arc-isle 0.1.2

The Interface Specification Language for the Arc project: design and implementation
Documentation
use crate::parser::utils::{as_str_or, read_yaml, YamlHash};
use crate::schema::ImportError;
use std::fmt::{Debug, Display, Formatter};
use yaml_rust::Yaml;

#[derive(Debug)]
pub struct SourceImport {
    pub key: String,
    pub imported_source: Yaml,
}

pub fn detect(
    source: &YamlHash,
    parent_path: &str,
) -> Vec<Result<Yaml, ImportError>> {
    let import_key = Yaml::String("_import".to_string());
    let is_import = source.contains_key(&import_key);
    if !is_import {
        return Vec::new();
    }
    let mut found_imports = Vec::new();
    match &source[&import_key] {
        Yaml::String(file_path) => {
            let file_path = parent_path.to_string() + "/" + &file_path;
            match read_yaml(&file_path) {
                Ok(imported_yaml) => {
                    for e in imported_yaml {
                        found_imports.push(Ok(e));
                    }
                }
                Err(err) => found_imports.push(Err(ImportError::IOError(err))),
            }
        }
        Yaml::Array(file_paths) => {
            for file_path in file_paths {
                match as_str_or(&file_path, ImportError::InvalidImportValue) {
                    Ok(file_path) => {
                        let file_path = parent_path.to_string() + "/" + &file_path;
                        match read_yaml(&file_path) {
                            Ok(imported_yaml) => {
                                for e in imported_yaml {
                                    found_imports.push(Ok(e));
                                }
                            }
                            Err(err) => found_imports.push(Err(ImportError::IOError(err))),
                        }
                    }
                    Err(err) => found_imports.push(Err(err)),
                }
            }
        }
        _ => found_imports.push(Err(ImportError::InvalidImportValue)),
    }
    found_imports
}

impl ImportError {
    fn default_fmt(&self, f: &mut Formatter) -> std::fmt::Result {
        match self {
            ImportError::IOError(err) => {
                write!(f, "I/O error while loading imports: {}", err.to_string())
            }
            ImportError::InvalidInputSource => write!(f, "Input source should be a hashmap"),
            ImportError::InvalidImportValue => write!(f, "Import statement should be string"),
        }
    }
}

impl std::error::Error for ImportError {}

impl Display for ImportError {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        self.default_fmt(f)
    }
}

impl Debug for ImportError {
    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
        self.default_fmt(f)
    }
}