use serde::Serialize;
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FlagKind {
Positional,
Value(&'static str),
Repeated(&'static str),
Switch(&'static str),
KeyValue(&'static str),
}
impl FlagKind {
#[must_use]
pub const fn flag(self) -> Option<&'static str> {
match self {
FlagKind::Positional => None,
FlagKind::Value(flag)
| FlagKind::Repeated(flag)
| FlagKind::Switch(flag)
| FlagKind::KeyValue(flag) => Some(flag),
}
}
#[must_use]
pub const fn wire_name(self) -> &'static str {
match self {
FlagKind::Positional => "positional",
FlagKind::Value(_) => "value",
FlagKind::Repeated(_) => "repeated",
FlagKind::Switch(_) => "switch",
FlagKind::KeyValue(_) => "key-value",
}
}
}
impl Serialize for FlagKind {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_str(self.wire_name())
}
}
#[derive(Debug, Clone, Copy)]
pub struct OptionBinding {
pub option: &'static str,
pub kind: FlagKind,
}
impl Serialize for OptionBinding {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
use serde::ser::SerializeStruct;
let mut out = serializer.serialize_struct("OptionBinding", 3)?;
out.serialize_field("option", self.option)?;
out.serialize_field("flag", &self.kind.flag().unwrap_or(""))?;
out.serialize_field("kind", &self.kind)?;
out.end()
}
}
#[derive(Debug, Clone, Copy, Serialize)]
pub struct UncoveredFlag {
pub flag: &'static str,
pub reason: &'static str,
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum StdoutShape {
Json(&'static str),
Jsonl(&'static str),
Text,
}
impl StdoutShape {
#[must_use]
pub const fn output(self) -> Option<&'static str> {
match self {
StdoutShape::Json(root) | StdoutShape::Jsonl(root) => Some(root),
StdoutShape::Text => None,
}
}
#[must_use]
pub const fn wire_name(self) -> &'static str {
match self {
StdoutShape::Json(_) => "json",
StdoutShape::Jsonl(_) => "jsonl",
StdoutShape::Text => "text",
}
}
}
impl Serialize for StdoutShape {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
serializer.serialize_str(self.wire_name())
}
}
#[derive(Debug, Clone, Copy)]
pub struct Capability {
pub method: &'static str,
pub verb: &'static [&'static str],
pub options: Option<&'static str>,
pub stdout: StdoutShape,
pub stdin: bool,
pub library_entry: &'static str,
pub bindings: &'static [OptionBinding],
pub uncovered: &'static [UncoveredFlag],
}
impl Capability {
#[must_use]
pub const fn output(&self) -> Option<&'static str> {
self.stdout.output()
}
#[must_use]
pub fn python_method(&self) -> String {
let mut out = String::with_capacity(self.method.len() + 2);
for ch in self.method.chars() {
if ch.is_ascii_uppercase() {
out.push('_');
out.push(ch.to_ascii_lowercase());
} else {
out.push(ch);
}
}
out
}
}
impl Serialize for Capability {
fn serialize<S: serde::Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
use serde::ser::SerializeStruct;
let mut out = serializer.serialize_struct("Capability", 9)?;
out.serialize_field("method", self.method)?;
out.serialize_field("verb", self.verb)?;
out.serialize_field("options", &self.options)?;
out.serialize_field("output", &self.output())?;
out.serialize_field("stdout", &self.stdout)?;
out.serialize_field("stdin", &self.stdin)?;
out.serialize_field("library_entry", self.library_entry)?;
out.serialize_field("bindings", self.bindings)?;
out.serialize_field("uncovered", self.uncovered)?;
out.end()
}
}
const fn bind(option: &'static str, kind: FlagKind) -> OptionBinding {
OptionBinding { option, kind }
}
const REGISTRY: OptionBinding = bind("registry", FlagKind::Value("--registry"));
pub const CAPABILITIES: &[Capability] = &[
Capability {
method: "schemaList",
verb: &["schema", "list"],
options: Some("schema_list_options"),
stdout: StdoutShape::Json("schema_list"),
stdin: false,
library_entry: "onemessagebus::Registry::ids",
bindings: &[REGISTRY, bind("format", FlagKind::Value("--format"))],
uncovered: &[],
},
Capability {
method: "schemaCheck",
verb: &["schema", "check"],
options: Some("schema_check_options"),
stdout: StdoutShape::Text,
stdin: true,
library_entry: "onemessagebus::Registry::check",
bindings: &[
bind("id", FlagKind::Positional),
bind("file", FlagKind::Value("--file")),
REGISTRY,
],
uncovered: &[],
},
Capability {
method: "schemaGen",
verb: &["schema", "gen"],
options: Some("schema_gen_options"),
stdout: StdoutShape::Text,
stdin: false,
library_entry: "onemessagebus::sdk_schema::generate",
bindings: &[
bind("id", FlagKind::Positional),
bind("lang", FlagKind::Value("--lang")),
REGISTRY,
],
uncovered: &[],
},
Capability {
method: "schemaRegister",
verb: &["schema", "register"],
options: Some("schema_register_options"),
stdout: StdoutShape::Text,
stdin: false,
library_entry: "onemessagebus::Registry::register_schema",
bindings: &[
bind("id", FlagKind::Positional),
bind("file", FlagKind::Value("--file")),
REGISTRY,
],
uncovered: &[],
},
Capability {
method: "eventsMerge",
verb: &["events", "merge"],
options: Some("events_merge_options"),
stdout: StdoutShape::Jsonl("envelope"),
stdin: false,
library_entry: "onemessagebus::Merge::open",
bindings: &[
bind("files", FlagKind::Positional),
bind("filter", FlagKind::Value("--filter")),
bind("profile", FlagKind::Value("--profile")),
bind("format", FlagKind::Value("--format")),
],
uncovered: &[],
},
Capability {
method: "eventsEmit",
verb: &["events", "emit"],
options: Some("events_emit_options"),
stdout: StdoutShape::Json("envelope"),
stdin: true,
library_entry: "onemessagebus::Emitter::shared",
bindings: &[
bind("path", FlagKind::Positional),
bind("kind", FlagKind::Value("--kind")),
bind("stream", FlagKind::Value("--stream")),
bind("source", FlagKind::Value("--source")),
bind("profile", FlagKind::Value("--profile")),
bind("labels", FlagKind::KeyValue("--label")),
bind("file", FlagKind::Value("--file")),
bind("format", FlagKind::Value("--format")),
],
uncovered: &[],
},
];