espforge_lib/parse/
mod.rs1use anyhow::{Context, Result};
2use espforge_common::EspforgeConfiguration;
3use serde_yaml_ng::Value;
4
5use crate::parse::{
6 processor::SectionProcessor,
7};
8
9pub mod components;
10pub mod devices;
11pub mod esp32;
12pub mod model;
13pub mod processor;
14pub mod project;
15
16
17pub struct ConfigParser {
18 processors: Vec<Box<dyn SectionProcessor>>,
19}
20
21impl ConfigParser {
22 pub fn builder() -> ConfigParserBuilder {
24 ConfigParserBuilder::default()
25 }
26
27 pub fn new() -> Self {
29 ConfigParserBuilder::default_processors().build()
30 }
31
32 pub fn parse(&self, yaml_text: &str) -> Result<EspforgeConfiguration> {
34 let raw_yaml: Value = serde_yaml_ng::from_str(yaml_text)?;
35 let root_map = raw_yaml
36 .as_mapping()
37 .ok_or_else(|| anyhow::anyhow!("Config must be a map"))?;
38
39 let mut model = EspforgeConfiguration::default();
40
41 for processor in &self.processors {
42 let key = processor.section_key();
43 if let Some(section_content) = root_map.get(Value::String(key.to_string())) {
44 processor
45 .process(section_content, &mut model)
46 .with_context(|| format!("Error processing configuration section '{}'", key))?;
47 }
48 }
49
50 if model.chip.is_empty() {
51 return Err(anyhow::anyhow!(
52 "Project configuration missing required 'espforge.chip' or 'espforge.platform'"
53 ));
54 }
55
56 Ok(model)
57 }
58}
59
60
61pub struct ConfigParserBuilder {
62 processors: Vec<Box<dyn SectionProcessor>>,
63}
64
65impl Default for ConfigParserBuilder {
66 fn default() -> Self {
67 Self::new()
68 }
69}
70
71impl ConfigParserBuilder {
72 pub fn new() -> Self {
73 Self {
74 processors: Vec::new(),
75 }
76 }
77
78 pub fn default_processors() -> Self {
79 Self::new()
80 .with_processor(Box::new(project::ProjectInfoProvisioner))
81 .with_processor(Box::new(esp32::PlatformProvisioner))
82 .with_processor(Box::new(components::ComponentProvisioner))
83 .with_processor(Box::new(devices::DeviceProvisioner))
84 }
85
86 pub fn with_processor(mut self, processor: Box<dyn SectionProcessor>) -> Self {
87 self.processors.push(processor);
88 self
89 }
90
91 pub fn build(mut self) -> ConfigParser {
93 self.processors.sort_by_key(|p| std::cmp::Reverse(p.priority()));
94
95 ConfigParser {
96 processors: self.processors,
97 }
98 }
99}