espforge_lib/parse/
mod.rs1use anyhow::{Context, Result};
2use serde_yaml_ng::Value;
3
4use crate::parse::{
5 model::EspforgeConfiguration,
6 processor::{ProcessorRegistration, SectionProcessor},
7};
8
9pub mod components;
10pub mod devices;
11pub mod esp32;
12pub mod model;
13pub mod processor;
14pub mod project;
15
16pub struct ConfigurationOrchestrator;
17
18impl Default for ConfigurationOrchestrator {
19 fn default() -> Self {
20 Self::new()
21 }
22}
23
24impl ConfigurationOrchestrator {
25 pub fn new() -> Self {
26 Self {}
27 }
28
29 pub fn compile(&self, yaml_text: &str) -> Result<EspforgeConfiguration> {
30 let raw_yaml: Value = serde_yaml_ng::from_str(yaml_text)?;
31 let root_map = raw_yaml
32 .as_mapping()
33 .ok_or_else(|| anyhow::anyhow!("Config must be a map"))?;
34
35 let mut model = EspforgeConfiguration::default();
36
37 let mut processors: Vec<Box<dyn SectionProcessor>> =
38 inventory::iter::<ProcessorRegistration>
39 .into_iter()
40 .map(|reg| (reg.factory)())
41 .collect();
42
43 processors.sort_by_key(|b| std::cmp::Reverse(b.priority()));
44 for processor in processors {
45 let key = processor.section_key();
46 if let Some(section_content) = root_map.get(Value::String(key.to_string())) {
47 processor
48 .process(section_content, &mut model)
49 .with_context(|| format!("Error processing configuration section '{}'", key))?;
50 }
51 }
52
53 if model.chip.is_empty() {
54 return Err(anyhow::anyhow!(
55 "Project configuration missing required 'espforge.chip' or 'espforge.platform' definition"
56 ));
57 }
58
59 Ok(model)
60 }
61}