1mod hosts;
2mod imports;
3mod interfaces;
4mod types;
5pub(crate) mod utils;
6mod versioning;
7
8use std::collections::HashMap;
9use std::error::Error;
10use std::fmt::Display;
11
12use crate::parser::hosts::HostsParser;
13use crate::parser::imports::detect;
14use crate::parser::types::TypesParser;
15use crate::parser::{utils::read_yaml, versioning::VersioningParser};
16use crate::schema::{ImportError, Schema, TypeUsageMeta, UnknownType};
17
18use self::interfaces::InterfacesParser;
19
20#[derive(Debug)]
21pub struct MissingTypeDeclError {
22 pub list: Vec<UnknownType>
23}
24
25impl Error for MissingTypeDeclError {
26}
27
28impl Display for MissingTypeDeclError {
29 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
30 f.write_str(&format!("{:?}", self.list))
31 }
32}
33
34pub fn parse(parent_path: &str) -> Result<Schema, Box<dyn std::error::Error>> {
35 let file_path = &(parent_path.to_string() + "/main.yaml");
36 let yaml = read_yaml(file_path)?;
37 let main = &yaml[0];
38 let hosts_parser = HostsParser { main };
39 let hosts = hosts_parser.parse()?;
40 let versioning_parser = VersioningParser { main };
41 let versioning = versioning_parser.parse()?;
42 let mut types_usage: HashMap<String, TypeUsageMeta> = HashMap::new();
43 let main_types_hash = main["types"]
44 .as_hash()
45 .ok_or(ImportError::InvalidInputSource)?;
46 let types_imports = detect(&main_types_hash, parent_path);
47 let mut types_parser = TypesParser {
48 parent_path,
49 types_usage: &mut types_usage,
50 };
51 let mut types: Vec<_> = vec![];
52 for import in types_imports {
53 types.extend(types_parser.parse(import?)?);
54 }
55 let main_interfaces_hash = main["interfaces"]
56 .as_hash()
57 .ok_or(ImportError::InvalidInputSource)?;
58 let interfaces_imports = detect(&main_interfaces_hash, parent_path);
59 let mut interfaces_parser = InterfacesParser {
60 parent_path,
61 types_usage: &mut types_usage,
62 types: &types,
63 };
64 let mut interfaces: Vec<_> = vec![];
65 for import in interfaces_imports {
66 interfaces.extend(interfaces_parser.parse(import?)?);
67 }
68 let mut missing_declations: Vec<UnknownType> = Vec::new();
69 for (type_name, unknown) in &types_usage {
70 if let Some(unknown) = unknown {
71 for e in unknown {
72 missing_declations.push(e.clone());
73 match e {
74 UnknownType::InTypeDeclaration(ti, pi) => {
75 println!("Unknown type {} at {} in property at {}", type_name, ti, pi);
76 }
77 UnknownType::InPayload(ii, pi) => {
78 println!("Unknown type {} in interface (#{}) input {}", type_name, ii, pi);
79 }
80 UnknownType::InResponse(ii, code, pi) => {
81 println!(
82 "Unknown type {} in interface (#{}) output status code {} in property at {}",
83 type_name, ii, code, pi
84 );
85 }
86 }
87 }
88 }
89 }
90 if !missing_declations.is_empty() {
91 let err = MissingTypeDeclError{list: missing_declations};
92 return Err(Box::new(err));
93 }
94 let schema = Schema {
95 hosts,
96 versioning,
97 types,
98 interfaces,
99 };
100 Ok(schema)
101}