allora_runtime/spec/
http_outbound_adapter_spec_yaml.rs

1use crate::error::{Error, Result};
2use crate::spec::http_outbound_adapter_spec::{
3    HttpOutboundAdapterSpec, HttpOutboundAdapterSpecRootV1,
4};
5use serde_yaml::{self, Value as YamlValue};
6
7pub struct HttpOutboundAdapterSpecYamlParser;
8impl HttpOutboundAdapterSpecYamlParser {
9    pub fn parse_value(yaml: &YamlValue) -> Result<HttpOutboundAdapterSpec> {
10        let version_val = yaml
11            .get("version")
12            .and_then(|v| v.as_u64())
13            .ok_or_else(|| Error::serialization("missing or invalid version"))?
14            as u32;
15        if version_val != 1 {
16            return Err(Error::serialization(format!(
17                "unsupported version {} (expected 1)",
18                version_val
19            )));
20        }
21        let root = yaml
22            .get("http-outbound-adapter")
23            .ok_or_else(|| Error::serialization("missing 'http-outbound-adapter'"))?;
24        if !root.is_mapping() {
25            return Err(Error::serialization(
26                "'http-outbound-adapter' must be a mapping",
27            ));
28        }
29        let mut mapping = serde_yaml::Mapping::new();
30        mapping.insert(
31            YamlValue::String("version".into()),
32            YamlValue::Number(serde_yaml::Number::from(version_val)),
33        );
34        mapping.insert(
35            YamlValue::String("http-outbound-adapter".into()),
36            root.clone(),
37        );
38        let synthesized = YamlValue::Mapping(mapping);
39        let root: HttpOutboundAdapterSpecRootV1 = serde_yaml::from_value(synthesized)
40            .map_err(|e| Error::serialization(format!("yaml parse error: {e}")))?;
41        let blk = &root.http_outbound_adapter;
42        if blk.host.is_empty() {
43            return Err(Error::serialization(
44                "http-outbound-adapter.host must not be empty",
45            ));
46        }
47        if blk.port == 0 {
48            return Err(Error::serialization(
49                "http-outbound-adapter.port out of range (1-65535)",
50            ));
51        }
52        if let Some(bp) = &blk.base_path {
53            if bp.is_empty() || !bp.starts_with('/') {
54                return Err(Error::serialization(
55                    "http-outbound-adapter.base-path must start with '/'",
56                ));
57            }
58        }
59        if let Some(p) = &blk.path {
60            if p.is_empty() || !p.starts_with('/') {
61                return Err(Error::serialization(
62                    "http-outbound-adapter.path must start with '/'",
63                ));
64            }
65        }
66        if let Some(idv) = &blk.id {
67            if idv.is_empty() {
68                return Err(Error::serialization(
69                    "http-outbound-adapter.id must not be empty",
70                ));
71            }
72        }
73        Ok(HttpOutboundAdapterSpec::from_block(
74            root.http_outbound_adapter,
75        ))
76    }
77    pub fn parse_str(raw: &str) -> Result<HttpOutboundAdapterSpec> {
78        let yaml: YamlValue = serde_yaml::from_str(raw)
79            .map_err(|e| Error::serialization(format!("yaml parse error: {e}")))?;
80        Self::parse_value(&yaml)
81    }
82}