1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
//! Procedural macros for [`coralstack-cmd-ipc`].
//!
//! This crate provides four attribute macros that keep command and
//! event definitions concise and colocated with their handlers:
//!
//! - [`macro@command`] — mark one async fn/method as a command.
//! - [`macro@command_service`] — mark an `impl` block; every method
//! inside tagged with `#[command("id")]` becomes a registered command
//! and the block gains a generated `register(self, ®istry)`
//! helper that installs every command in one call.
//! - [`macro@event`] — mark a payload struct as a typed event; emits
//! the `impl Event` and auto-derives `Serialize` / `Deserialize` /
//! `JsonSchema`.
//! - [`macro@payload`] — mark any struct (typically command requests
//! and responses) to auto-derive `Serialize` / `Deserialize` /
//! `JsonSchema` without requiring the user crate to depend on
//! `serde` / `schemars` directly.
//!
//! All four resolve their derives against the `serde` / `schemars`
//! re-exports published by `coralstack-cmd-ipc`, so user crates depend
//! on `coralstack-cmd-ipc` alone.
//!
//! See the `coralstack-cmd-ipc` crate docs for usage examples and
//! end-to-end integration tests.
use TokenStream;
/// Attach to an `async fn` (free-standing or inside a
/// `#[command_service] impl` block) to register it as a typed command.
///
/// Usage inside a `#[command_service] impl Service` block:
///
/// ```ignore
/// #[command_service]
/// impl Service {
/// #[command("math.add", description = "Add two numbers")]
/// async fn add(&self, req: AddReq) -> Result<i64, CommandError> { ... }
/// }
/// ```
///
/// Usage as a free function:
///
/// ```ignore
/// #[command("greet")]
/// async fn greet(name: String) -> Result<String, CommandError> { ... }
/// // Exposes `register_greet(®istry).await?` to install the command.
/// ```
/// Attach to an `impl` block whose methods are tagged with `#[command]`.
///
/// Rewrites the block so every `#[command("id")]` method becomes a typed
/// command wrapper struct implementing `Command`, and adds an inherent
/// `register` async method to the host type that installs every such
/// command on a `&CommandRegistry`.
///
/// ```ignore
/// #[command_service]
/// impl MathService {
/// #[command("math.add")]
/// async fn add(&self, req: AddReq) -> Result<i64, CommandError> { ... }
///
/// #[command("math.sub")]
/// async fn sub(&self, req: SubReq) -> Result<i64, CommandError> { ... }
/// }
///
/// // Registers both commands with one call:
/// MathService.register(®istry).await?;
/// ```
/// Attach to a payload struct to register it as a typed event.
///
/// The macro auto-derives `Serialize`, `Deserialize`, and `JsonSchema`
/// against the `serde` / `schemars` re-exports from `coralstack-cmd-ipc`,
/// so user crates don't need to pull those dependencies into their own
/// `Cargo.toml`. It also emits the `impl Event` for the struct with the
/// id and wire-level schema.
///
/// Unit structs emit no payload on the wire — the natural way to declare
/// a void event.
///
/// ```ignore
/// /// Worker has finished initializing.
/// #[event("worker.ready")]
/// pub struct WorkerReady {
/// pub worker_id: String,
/// pub command_count: u32,
/// }
///
/// // Void event — no payload on the wire.
/// #[event("worker.tick")]
/// pub struct WorkerTick;
///
/// // Emit with full type safety:
/// registry.emit(WorkerReady { worker_id: "w1".into(), command_count: 2 })?;
/// registry.emit(WorkerTick)?;
///
/// // Subscribe — callback receives a deserialized `WorkerReady`:
/// let _unsub = registry.on::<WorkerReady>(|event| {
/// println!("{} ready", event.worker_id);
/// });
/// ```
/// Attach to a plain data struct to auto-derive `Serialize`,
/// `Deserialize`, and `JsonSchema`. Use for command request / response
/// types (and any other struct you want those traits on) so user crates
/// only need to depend on `coralstack-cmd-ipc`.
///
/// ```ignore
/// use coralstack_cmd_ipc::prelude::*;
///
/// #[payload]
/// struct AddReq { a: i64, b: i64 }
///
/// #[payload]
/// struct AddRes { sum: i64 }
/// ```
///
/// Users who need extra derives (`Clone`, `Debug`, `PartialEq`, custom
/// `#[serde(...)]` attributes) add them normally — `#[payload]` is
/// additive.