Skip to main content

vs_daemon/
dispatch.rs

1//! Dispatcher: the single entry point that takes one or more
2//! primitives and returns one rendered wire response per primitive.
3//!
4//! Both the wire server (`server/mod.rs`) and in-process tests funnel
5//! through [`Daemon::dispatch`]. Today the wire delivers exactly one
6//! primitive per frame, so the inbound vec has length 1 and the
7//! response is a single rendered envelope+body. M5.5 PRs 2–6 introduce
8//! composite-flag primitives that internally expand into multiple
9//! sequenced primitives. The wire syntax for explicit pipelines (v2,
10//! see ADR 0007) lands as a parser-only change against this same
11//! dispatcher — no further dispatcher rewrite required.
12//!
13//! ## Why `Primitive = Request` (today)
14//!
15//! `Request` already carries everything the dispatcher needs: the
16//! primitive name, positional args, and a flag map. Composite flags
17//! (`--view`, `--layout=`, `--read=`) are entries in that map, not new
18//! variants. A typed `Primitive` enum may land in a later milestone
19//! once we have evidence that the dispatcher's match-on-name is
20//! genuinely brittle in practice. Until then it would be type-system
21//! ceremony for no payoff.
22
23use vs_protocol::Request;
24
25/// A single primitive in a dispatch sequence. Today this is a
26/// re-export of [`vs_protocol::Request`]; see the module docs.
27pub type Primitive = Request;
28
29/// One rendered response, in the canonical wire shape: warnings (if
30/// any) + envelope + body lines, terminated by a single `\n`. The
31/// dispatcher never inserts the framing blank line — the caller
32/// (`server::handle_connection`) does that between outcomes.
33#[derive(Debug, Clone)]
34pub struct DispatchOutcome {
35    /// Already-formatted wire bytes (warnings + envelope + body).
36    pub wire: String,
37}
38
39impl DispatchOutcome {
40    /// Wrap a pre-rendered wire string.
41    #[must_use]
42    pub fn from_wire(s: String) -> Self {
43        Self { wire: s }
44    }
45}