allora_runtime/spec/
aggregators_spec_yaml.rs1use crate::error::{Error, Result};
24use crate::spec::aggregators_spec::AggregatorsSpec;
25use crate::spec::version::validate_version;
26use crate::spec::AggregatorSpecYamlParser;
27use serde_yaml::Value as YamlValue;
28
29pub struct AggregatorsSpecYamlParser;
30
31impl AggregatorsSpecYamlParser {
32 pub fn parse_value(yaml: &YamlValue) -> Result<AggregatorsSpec> {
33 let v = validate_version(yaml)?;
34 let aggs_val = yaml
35 .get("aggregators")
36 .ok_or_else(|| Error::serialization("missing 'aggregators'"))?;
37 if !aggs_val.is_sequence() {
38 return Err(Error::serialization("'aggregators' must be a sequence"));
39 }
40 let seq = aggs_val.as_sequence().unwrap();
41 if seq.is_empty() {
42 return Err(Error::serialization(
43 "'aggregators' sequence must not be empty (minItems=1)",
44 ));
45 }
46 let mut spec = AggregatorsSpec::new(v);
47 for item in seq {
48 if !item.is_mapping() {
49 return Err(Error::serialization("aggregator entry must be a mapping"));
50 }
51 let mut obj = serde_yaml::Mapping::new();
53 obj.insert(
54 YamlValue::String("version".into()),
55 YamlValue::Number(serde_yaml::Number::from(v)),
56 );
57 obj.insert(YamlValue::String("aggregator".into()), item.clone());
58 let synthesized = YamlValue::Mapping(obj);
59 spec.push(AggregatorSpecYamlParser::parse_value(&synthesized)?);
60 }
61 Ok(spec)
62 }
63
64 pub fn parse_str(raw: &str) -> Result<AggregatorsSpec> {
65 let val: YamlValue = serde_yaml::from_str(raw)
66 .map_err(|e| Error::serialization(format!("yaml parse error: {e}")))?;
67 Self::parse_value(&val)
68 }
69}