espforge_lib/resolver/strategies/
utils.rs1use std::collections::HashMap;
2
3use crate::config::Esp32Config;
4use crate::resolver::strategies::ResolutionContext;
5use anyhow::{Result, anyhow};
6use serde::Serialize;
7use serde_yaml_ng::Value;
8
9pub trait ValueExt {
10 fn as_ref_name(&self) -> Result<&str>;
11}
12
13impl ValueExt for Value {
14 fn as_ref_name(&self) -> Result<&str> {
15 let s = self.as_str()
16 .ok_or_else(|| anyhow!("Reference must be a string"))?;
17
18 s.strip_prefix('$')
19 .ok_or_else(|| anyhow!("Reference must start with '$', got: {}", s))
20 }
21}
22
23impl<'a> ResolutionContext<'a> {
24 pub fn hardware(&self) -> Result<&'a Esp32Config> {
25 self.hardware.ok_or_else(|| {
26 anyhow!("Hardware configuration (esp32) is missing")
27 })
28 }
29}
30
31pub fn resolve_hardware_resource<T, V, MapFn, ViewFn>(
32 value: &Value,
33 ctx: &ResolutionContext,
34 map_selector: MapFn,
35 view_converter: ViewFn,
36) -> Result<Value>
37where
38 MapFn: FnOnce(&Esp32Config) -> &HashMap<String, T>,
39 ViewFn: FnOnce(&T) -> V,
40 V: Serialize,
41{
42 let name = value.as_ref_name()?;
43 let hardware = ctx.hardware()?;
44 let map = map_selector(hardware);
45 let config = map.get(name)
46 .ok_or_else(|| anyhow!("Hardware resource '${}' not found", name))?;
47 let view = view_converter(config);
48 Ok(serde_yaml_ng::to_value(view)?)
49}