vox_types/
request_context.rs1use std::sync::OnceLock;
2
3use crate::{ConnectionId, Extensions, MetadataEntry, MethodDescriptor, RequestId};
4
5#[derive(Clone, Copy, Debug)]
10pub struct RequestContext<'a> {
11 method: &'static MethodDescriptor,
12 metadata: &'a [MetadataEntry<'static>],
13 request_id: Option<RequestId>,
14 connection_id: Option<ConnectionId>,
15 extensions: &'a Extensions,
16}
17
18impl<'a> RequestContext<'a> {
19 pub fn new(method: &'static MethodDescriptor, metadata: &'a [MetadataEntry<'static>]) -> Self {
21 Self::with_transport(method, metadata, None, None, empty_extensions())
22 }
23
24 pub fn with_extensions(
26 method: &'static MethodDescriptor,
27 metadata: &'a [MetadataEntry<'static>],
28 extensions: &'a Extensions,
29 ) -> Self {
30 Self::with_transport(method, metadata, None, None, extensions)
31 }
32
33 pub fn with_transport(
35 method: &'static MethodDescriptor,
36 metadata: &'a [MetadataEntry<'static>],
37 request_id: Option<RequestId>,
38 connection_id: Option<ConnectionId>,
39 extensions: &'a Extensions,
40 ) -> Self {
41 Self {
42 method,
43 metadata,
44 request_id,
45 connection_id,
46 extensions,
47 }
48 }
49
50 pub fn method(&self) -> &'static MethodDescriptor {
52 self.method
53 }
54
55 pub fn metadata(&self) -> &'a [MetadataEntry<'static>] {
57 self.metadata
58 }
59
60 pub fn request_id(&self) -> Option<RequestId> {
62 self.request_id
63 }
64
65 pub fn connection_id(&self) -> Option<ConnectionId> {
67 self.connection_id
68 }
69
70 pub fn extensions(&self) -> &'a Extensions {
72 self.extensions
73 }
74}
75
76fn empty_extensions() -> &'static Extensions {
77 static EMPTY: OnceLock<Extensions> = OnceLock::new();
78 EMPTY.get_or_init(Extensions::new)
79}
80
81#[cfg(test)]
82mod tests {
83 use crate::{ConnectionId, MetadataEntry, RequestId, method_descriptor};
84
85 use super::RequestContext;
86
87 #[test]
88 fn transport_identifiers_are_exposed_when_present() {
89 let method = method_descriptor::<(), ()>("demo-service", "demo", &[], None);
90 let metadata: [MetadataEntry<'static>; 0] = [];
91
92 let context = RequestContext::with_transport(
93 method,
94 &metadata,
95 Some(RequestId(11)),
96 Some(ConnectionId(13)),
97 super::empty_extensions(),
98 );
99
100 assert_eq!(context.request_id(), Some(RequestId(11)));
101 assert_eq!(context.connection_id(), Some(ConnectionId(13)));
102 assert_eq!(context.method().id, method.id);
103 assert_eq!(context.method().method_name, "demo");
104 }
105}