Skip to main content

lash_core/provider/
spec.rs

1use super::support::*;
2
3/// Serialised form of a provider's configuration. Round-trips with
4/// [`ProviderHandle`] via `ProviderHandle::to_spec` / `build_provider`.
5///
6/// Wire shape is a flat JSON object: a `type` field plus the
7/// provider-specific config keys. This matches the legacy
8/// `~/.lash/config.json` shape so old configs load without migration.
9#[derive(Clone, Debug, PartialEq, Eq)]
10pub struct ProviderSpec {
11    pub kind: String,
12    pub config: serde_json::Value,
13}
14
15impl Serialize for ProviderSpec {
16    fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
17        let mut value = match &self.config {
18            serde_json::Value::Object(map) => serde_json::Value::Object(map.clone()),
19            serde_json::Value::Null => serde_json::Value::Object(serde_json::Map::new()),
20            other => {
21                return Err(serde::ser::Error::custom(format!(
22                    "ProviderSpec.config must serialize to a JSON object, got {}",
23                    other
24                )));
25            }
26        };
27        if let serde_json::Value::Object(ref mut map) = value {
28            map.insert(
29                "type".to_string(),
30                serde_json::Value::String(self.kind.clone()),
31            );
32        }
33        value.serialize(serializer)
34    }
35}
36
37impl<'de> Deserialize<'de> for ProviderSpec {
38    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
39        let mut value = serde_json::Value::deserialize(deserializer)?;
40        let kind = if let serde_json::Value::Object(ref mut map) = value {
41            let raw = map
42                .remove("type")
43                .ok_or_else(|| serde::de::Error::missing_field("type"))?;
44            raw.as_str()
45                .ok_or_else(|| serde::de::Error::custom("provider `type` must be a string"))?
46                .to_string()
47        } else {
48            return Err(serde::de::Error::custom(
49                "provider spec must be a JSON object",
50            ));
51        };
52        Ok(Self {
53            kind,
54            config: value,
55        })
56    }
57}