use serde::Serialize;
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
#[serde(rename_all = "snake_case")]
#[non_exhaustive]
pub enum Maturity {
Stable,
Preview,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Serialize)]
#[serde(rename_all = "snake_case")]
#[non_exhaustive]
pub enum Release {
Default,
Full,
Platform,
Source,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
#[serde(rename_all = "snake_case")]
#[non_exhaustive]
pub enum SectionActivity {
EnabledFlag,
NonEmptyDefinitions,
AnyEntryEnabled,
}
impl SectionActivity {
#[must_use]
pub fn is_active(self, value: &serde_json::Value) -> bool {
let enabled = |v: &serde_json::Value| {
v.get("enabled").and_then(serde_json::Value::as_bool).unwrap_or(false)
};
match self {
Self::EnabledFlag => enabled(value),
Self::NonEmptyDefinitions => value
.get("definitions")
.and_then(serde_json::Value::as_array)
.is_some_and(|d| !d.is_empty()),
Self::AnyEntryEnabled => value.as_array().is_some_and(|e| e.iter().any(enabled)),
}
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
pub struct CompiledSection {
pub key: &'static str,
pub activity: SectionActivity,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
#[allow(clippy::struct_excessive_bools)] pub struct EntryPoints {
pub binary: bool,
pub listener: bool,
pub mcp_stdio: bool,
pub run: bool,
}
impl EntryPoints {
pub const ALL: Self = Self {
mcp_stdio: true,
..Self::HTTP
};
pub const HTTP: Self = Self {
binary: true,
listener: true,
mcp_stdio: false,
run: true,
};
pub const NONE: Self = Self {
binary: false,
listener: false,
mcp_stdio: false,
run: false,
};
}
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize)]
pub struct CapabilityMeta {
pub name: &'static str,
pub feature: &'static str,
pub compiled_sections: &'static [CompiledSection],
pub runtime_keys: &'static [&'static str],
pub docs: Option<&'static str>,
pub maturity: Maturity,
pub release: Release,
pub entry_points: EntryPoints,
}
impl CapabilityMeta {
#[must_use]
pub fn remedy(&self) -> String {
let rebuild = format!("rebuild with `--features {}`", self.feature);
match self.release {
Release::Default | Release::Source => rebuild,
Release::Full => format!("pull the `-full` or `-platform` image tag, or {rebuild}"),
Release::Platform => format!("pull the `-platform` image tag, or {rebuild}"),
}
}
}
#[cfg(test)]
mod tests;