toolkit_contract/descriptor.rs
1use serde::{Deserialize, Serialize};
2
3use crate::ir::contract::{Idempotency, MethodKind};
4
5/// Operational classification of a contract trait.
6///
7/// Encoded in the trait name suffix per PRD #1536 D2/D6:
8/// - `Api` — module **provides** the contract; remote-capable.
9/// - `Embedded` — module **provides** the contract; always in-process.
10/// - `Backend` — module **requires** the contract; remote-capable.
11/// - `Extension` — module **requires** the contract; always in-process.
12#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize)]
13pub enum ContractKind {
14 /// Provided contract, remote-capable.
15 Api,
16 /// Provided contract, always local.
17 Embedded,
18 /// Required contract (consumed by the module), remote-capable.
19 Backend,
20 /// Required contract (consumed by the module), always local.
21 Extension,
22}
23
24impl ContractKind {
25 /// Whether this kind permits a transport projection (`*Rest`, `*Grpc`).
26 #[must_use]
27 pub const fn is_remote_capable(self) -> bool {
28 matches!(self, ContractKind::Api | ContractKind::Backend)
29 }
30
31 /// Human-readable name suitable for diagnostics and trait-suffix matching.
32 #[must_use]
33 pub const fn suffix(self) -> &'static str {
34 match self {
35 ContractKind::Api => "Api",
36 ContractKind::Embedded => "Embedded",
37 ContractKind::Backend => "Backend",
38 ContractKind::Extension => "Extension",
39 }
40 }
41}
42
43/// Compile-time static metadata for a contract.
44pub struct ContractDescriptor {
45 /// Gear name.
46 pub gear: &'static str,
47 /// Contract name, usually the SDK trait name.
48 pub contract: &'static str,
49 /// Compatibility service name for old service-hub call sites.
50 pub service: &'static str,
51 /// API version.
52 pub version: &'static str,
53 /// Operational classification of this contract.
54 pub kind: ContractKind,
55 /// Method descriptors for all methods in this contract.
56 pub methods: &'static [MethodDescriptor],
57}
58
59impl ContractDescriptor {
60 /// Compatibility accessor for old service-oriented call sites.
61 #[must_use]
62 pub const fn service(&self) -> &'static str {
63 self.service
64 }
65
66 /// Whether the contract permits remote dispatch.
67 #[must_use]
68 pub const fn is_remote_capable(&self) -> bool {
69 self.kind.is_remote_capable()
70 }
71}
72
73/// Static metadata for a single method within a contract.
74pub struct MethodDescriptor {
75 /// Method name.
76 pub name: &'static str,
77 /// Unary or streaming.
78 pub kind: MethodKind,
79 /// Idempotency classification for retry decisions.
80 pub idempotency: Idempotency,
81 /// Input type name for diagnostics and logging.
82 pub input_type: &'static str,
83 /// Output type name for diagnostics and logging.
84 pub output_type: &'static str,
85}
86
87pub type ServiceDescriptor = ContractDescriptor;