espforge_lib/resolver/actions/
mod.rs1use crate::config::EspforgeConfiguration;
2use crate::manifest::ComponentManifest;
3use anyhow::{Result, anyhow};
4use inventory;
5use serde_yaml_ng::Value;
6use std::collections::HashMap;
7use tera::Tera;
8
9pub mod component;
10pub mod global;
11pub mod logic;
12
13#[derive(Debug)]
15pub enum ValidationResult {
16 Ok(String),
18 Error(String),
20 Warning(String),
22 Ignored,
24}
25
26pub trait ActionStrategy: Send + Sync {
28 fn can_handle(&self, key: &str) -> bool;
30
31 fn validate(
34 &self,
35 key: &str,
36 _value: &Value,
37 config: &EspforgeConfiguration,
38 manifests: &HashMap<String, ComponentManifest>,
39 ) -> ValidationResult;
40
41 fn render(
44 &self,
45 key: &str,
46 value: &Value,
47 config: &EspforgeConfiguration,
48 manifests: &HashMap<String, ComponentManifest>,
49 tera: &mut Tera,
50 ) -> Result<String>;
51}
52
53pub type ActionStrategyFactory = fn() -> Box<dyn ActionStrategy>;
56
57pub struct ActionStrategyRegistration {
58 pub factory: ActionStrategyFactory,
59}
60
61inventory::collect!(ActionStrategyRegistration);
62
63#[macro_export]
64macro_rules! register_action_strategy {
65 ($strategy:ty) => {
66 inventory::submit! {
67 $crate::resolver::actions::ActionStrategyRegistration {
68 factory: || Box::new(<$strategy>::default())
69 }
70 }
71 };
72}
73
74pub struct ActionResolver {
77 strategies: Vec<Box<dyn ActionStrategy>>,
78}
79
80impl Default for ActionResolver {
81 fn default() -> Self {
82 Self::new()
83 }
84}
85
86impl ActionResolver {
87 pub fn new() -> Self {
88 let mut strategies = Vec::new();
89 for registration in inventory::iter::<ActionStrategyRegistration> {
90 strategies.push((registration.factory)());
91 }
92 Self { strategies }
93 }
94
95 pub fn validate(
97 &self,
98 key: &str,
99 value: &Value,
100 config: &EspforgeConfiguration,
101 manifests: &HashMap<String, ComponentManifest>,
102 ) -> ValidationResult {
103 for strategy in &self.strategies {
104 if strategy.can_handle(key) {
105 return strategy.validate(key, value, config, manifests);
106 }
107 }
108 ValidationResult::Warning(format!(
109 "Unknown action format '{}'. No strategy found.",
110 key
111 ))
112 }
113
114 pub fn resolve(
116 &self,
117 key: &str,
118 value: &Value,
119 config: &EspforgeConfiguration,
120 manifests: &HashMap<String, ComponentManifest>,
121 tera: &mut Tera,
122 ) -> Result<String> {
123 for strategy in &self.strategies {
124 if strategy.can_handle(key) {
125 return strategy.render(key, value, config, manifests, tera);
126 }
127 }
128 Err(anyhow!("No strategy found to resolve action '{}'", key))
129 }
130}