Skip to main content

vox_types/
services.rs

1use facet::{Facet, Shape};
2
3/// Static descriptor for a vox RPC service.
4///
5/// Contains the service name and all method descriptors. Built once per service
6/// via OnceLock in macro-generated code.
7pub struct ServiceDescriptor {
8    /// Service name (e.g., "Calculator").
9    pub service_name: &'static str,
10
11    /// All methods in this service.
12    pub methods: &'static [&'static MethodDescriptor],
13
14    /// Documentation string, if any.
15    pub doc: Option<&'static str>,
16}
17
18impl ServiceDescriptor {
19    /// Look up a method descriptor by method ID.
20    pub fn by_id(&self, method_id: MethodId) -> Option<&'static MethodDescriptor> {
21        self.methods.iter().find(|m| m.id == method_id).copied()
22    }
23}
24
25/// Static descriptor for a single RPC method.
26///
27/// Contains static metadata needed for dispatching and calling this method.
28pub struct MethodDescriptor {
29    /// Method ID (hash of service name, method name, arg shapes, return shape).
30    pub id: MethodId,
31
32    /// Service name (e.g., "Calculator").
33    pub service_name: &'static str,
34
35    /// Method name (e.g., "add").
36    pub method_name: &'static str,
37
38    /// Args type shape
39    pub args_shape: &'static Shape,
40
41    /// Arguments in declaration order.
42    pub args: &'static [ArgDescriptor],
43
44    /// Return type shape.
45    pub return_shape: &'static Shape,
46
47    /// Static retry policy for this method.
48    pub retry: RetryPolicy,
49
50    /// Documentation string, if any.
51    pub doc: Option<&'static str>,
52}
53
54impl std::fmt::Debug for MethodDescriptor {
55    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
56        f.debug_struct("MethodDescriptor")
57            .field("id", &self.id)
58            .field("service_name", &self.service_name)
59            .field("method_name", &self.method_name)
60            .field("retry", &self.retry)
61            .finish_non_exhaustive()
62    }
63}
64
65/// Static retry policy for a method.
66#[derive(Clone, Copy, Debug, Default, PartialEq, Eq)]
67pub struct RetryPolicy {
68    /// Whether an admitted operation must persist once started.
69    pub persist: bool,
70
71    /// Whether re-executing the same logical operation is semantically safe.
72    pub idem: bool,
73}
74
75impl RetryPolicy {
76    pub const VOLATILE: Self = Self {
77        persist: false,
78        idem: false,
79    };
80
81    pub const IDEM: Self = Self {
82        persist: false,
83        idem: true,
84    };
85
86    pub const PERSIST: Self = Self {
87        persist: true,
88        idem: false,
89    };
90
91    pub const PERSIST_IDEM: Self = Self {
92        persist: true,
93        idem: true,
94    };
95}
96
97declare_id!(
98    /// A unique method identifier — hash of service name, method name, arg shapes, return shape
99    MethodId, u64
100);
101
102/// Descriptor for a single RPC method argument.
103///
104/// Contains metadata about an argument including its name, shape, and
105/// whether it's a channel type (Rx/Tx).
106#[derive(Debug)]
107pub struct ArgDescriptor {
108    /// Argument name (e.g., "user_id", "stream").
109    pub name: &'static str,
110
111    /// Argument type shape.
112    pub shape: &'static Shape,
113}
114
115impl ServiceDescriptor {
116    /// An empty service descriptor for dispatchers that don't serve any methods.
117    pub const EMPTY: ServiceDescriptor = ServiceDescriptor {
118        service_name: "<Empty>",
119        methods: &[],
120        doc: None,
121    };
122}