Skip to main content

ados_protocol/
dispatch.rs

1// @generated by ados-capabilities-codegen from capabilities.toml. Do not edit by hand.
2//! Generated plugin RPC dispatch table.
3//!
4//! Maps every wire method to the dispatch-level capability the plugin IPC
5//! server requires before routing it. The source of truth is the
6//! `[[method]]` section of `capabilities.toml`; regenerate with
7//! `cargo run -p ados-capabilities-codegen`.
8//!
9//! `required_cap` is `None` for the ungated methods (the event surface and
10//! `ping`) and for the methods gated inline by their handler from the
11//! request payload; `inline` distinguishes the two so an open method cannot
12//! be mistaken for an inline-gated one.
13
14/// One row of the dispatch table: a wire method and its dispatch-level gate.
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub struct DispatchMethod {
17    pub method: &'static str,
18    pub required_cap: Option<&'static str>,
19    pub inline: bool,
20}
21
22/// Every plugin RPC method, with the capability the dispatch loop requires
23/// before routing it.
24#[rustfmt::skip]
25pub const DISPATCH_METHODS: &[DispatchMethod] = &[
26    DispatchMethod { method: "event.publish", required_cap: None, inline: false },
27    DispatchMethod { method: "event.subscribe", required_cap: None, inline: false },
28    DispatchMethod { method: "ping", required_cap: None, inline: false },
29    DispatchMethod { method: "tool.invoke", required_cap: Some("mcp.expose"), inline: false },
30    DispatchMethod { method: "telemetry.subscribe", required_cap: Some("telemetry.read"), inline: false },
31    DispatchMethod { method: "telemetry.extend", required_cap: Some("telemetry.extend"), inline: false },
32    DispatchMethod { method: "mission.read", required_cap: Some("mission.read"), inline: false },
33    DispatchMethod { method: "mission.write", required_cap: Some("mission.write"), inline: false },
34    DispatchMethod { method: "recording.start", required_cap: Some("recording.write"), inline: false },
35    DispatchMethod { method: "recording.stop", required_cap: Some("recording.write"), inline: false },
36    DispatchMethod { method: "mavlink.subscribe", required_cap: Some("mavlink.read"), inline: false },
37    DispatchMethod { method: "mavlink.send", required_cap: Some("mavlink.write"), inline: false },
38    DispatchMethod { method: "msp.subscribe", required_cap: Some("msp.read"), inline: false },
39    DispatchMethod { method: "msp.send", required_cap: Some("msp.write"), inline: false },
40    DispatchMethod { method: "mavlink.tunnel.send", required_cap: Some("mavlink.tunnel"), inline: false },
41    DispatchMethod { method: "mavlink.register_component", required_cap: None, inline: true },
42    DispatchMethod { method: "peripheral.register_driver", required_cap: None, inline: true },
43    DispatchMethod { method: "peripheral.unregister_driver", required_cap: None, inline: true },
44    DispatchMethod { method: "camera.claim", required_cap: Some("sensor.camera.register"), inline: false },
45    DispatchMethod { method: "camera.release", required_cap: Some("sensor.camera.register"), inline: false },
46    DispatchMethod { method: "camera.get_frame", required_cap: Some("sensor.camera.register"), inline: false },
47    DispatchMethod { method: "video.source.set", required_cap: Some("video.source.set"), inline: false },
48    DispatchMethod { method: "video.whep.offer", required_cap: Some("video.whep.relay"), inline: false },
49    DispatchMethod { method: "video.whep.close", required_cap: Some("video.whep.relay"), inline: false },
50    DispatchMethod { method: "sensors.rig.write", required_cap: Some("sensors.rig.write"), inline: false },
51    DispatchMethod { method: "camera.control.set", required_cap: Some("camera.control.write"), inline: false },
52    DispatchMethod { method: "config.get", required_cap: None, inline: false },
53    DispatchMethod { method: "config.set", required_cap: None, inline: false },
54    DispatchMethod { method: "process.spawn", required_cap: Some("process.spawn"), inline: false },
55    DispatchMethod { method: "vision.subscribe_frames", required_cap: Some("vision.frame.read"), inline: false },
56    DispatchMethod { method: "vision.register_model", required_cap: Some("vision.model.register"), inline: false },
57    DispatchMethod { method: "vision.read_model", required_cap: Some("vision.model.read"), inline: false },
58    DispatchMethod { method: "vision.infer", required_cap: Some("vision.model.register"), inline: false },
59    DispatchMethod { method: "vision.publish_detection", required_cap: Some("vision.detection.publish"), inline: false },
60    DispatchMethod { method: "vision.subscribe_detections", required_cap: Some("vision.detection.subscribe"), inline: false },
61    DispatchMethod { method: "vision.designate_track", required_cap: Some("vision.track.designate"), inline: false },
62    DispatchMethod { method: "display.page.set", required_cap: Some("display.oled.page"), inline: false },
63    DispatchMethod { method: "display.zone.subscribe", required_cap: Some("display.oled.page"), inline: false },
64    DispatchMethod { method: "button.subscribe", required_cap: Some("button.subscribe"), inline: false },
65    DispatchMethod { method: "gpio.output.set", required_cap: Some("hardware.gpio_out"), inline: false },
66    DispatchMethod { method: "gpio.buzzer.beep", required_cap: Some("hardware.gpio_out"), inline: false },
67    DispatchMethod { method: "flight.guided_setpoint.send", required_cap: Some("flight.guided_setpoint"), inline: false },
68    DispatchMethod { method: "flight.rate_setpoint.send", required_cap: Some("flight.rate_setpoint"), inline: false },
69    DispatchMethod { method: "radio.aux_stream.open", required_cap: Some("radio.aux_stream"), inline: false },
70    DispatchMethod { method: "radio.aux_stream.close", required_cap: Some("radio.aux_stream"), inline: false },
71    DispatchMethod { method: "radio.aux_stream.send", required_cap: Some("radio.aux_stream"), inline: false },
72    DispatchMethod { method: "radio.aux_stream.subscribe", required_cap: Some("radio.aux_stream"), inline: false },
73    DispatchMethod { method: "cloud.publish", required_cap: Some("cloud.publish"), inline: false },
74    DispatchMethod { method: "cloud.records.put", required_cap: Some("cloud.records"), inline: false },
75    DispatchMethod { method: "offload.advertise", required_cap: Some("vision.offload.advertise"), inline: false },
76    DispatchMethod { method: "node.info", required_cap: Some("node.info.read"), inline: false },
77    DispatchMethod { method: "mdns.advertise", required_cap: Some("network.listen"), inline: false },
78    DispatchMethod { method: "mdns.browse", required_cap: Some("network.outbound"), inline: false },
79];
80
81/// Look up the dispatch-level required capability for a wire method.
82/// Returns `Some(None)` for a known ungated/inline method and `None` for an
83/// unknown method, so a caller can tell the two apart.
84pub fn required_cap_for(method: &str) -> Option<Option<&'static str>> {
85    DISPATCH_METHODS
86        .iter()
87        .find(|m| m.method == method)
88        .map(|m| m.required_cap)
89}
90
91/// True if `method` is a known dispatch method.
92pub fn is_known_method(method: &str) -> bool {
93    DISPATCH_METHODS.iter().any(|m| m.method == method)
94}