flymcprust_core/
context.rs1use std::any::{Any, TypeId, type_name};
5use std::collections::HashMap;
6use std::fmt;
7use std::ops::Deref;
8use std::sync::Arc;
9
10use tokio_util::sync::CancellationToken;
11
12use crate::mrtr::Round;
13use crate::notify::Notifier;
14use crate::spec::{self, RequestId};
15
16#[derive(Clone, Default)]
18pub(crate) struct TypeMap {
19 values: HashMap<TypeId, (Arc<dyn Any + Send + Sync>, &'static str)>,
20}
21
22impl TypeMap {
23 pub(crate) fn insert<T: Send + Sync + 'static>(&mut self, value: Arc<T>) {
24 self.values
25 .insert(TypeId::of::<T>(), (value, type_name::<T>()));
26 }
27
28 pub(crate) fn get<T: Send + Sync + 'static>(&self) -> Option<Arc<T>> {
29 let (value, _) = self.values.get(&TypeId::of::<T>())?;
30 Arc::clone(value).downcast::<T>().ok()
31 }
32
33 pub(crate) fn contains(&self, id: TypeId) -> bool {
34 self.values.contains_key(&id)
35 }
36}
37
38impl fmt::Debug for TypeMap {
39 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
40 f.debug_set()
41 .entries(self.values.values().map(|(_, name)| name))
42 .finish()
43 }
44}
45
46#[derive(Clone, Default, Debug)]
50pub struct TransportContext {
51 values: TypeMap,
52}
53
54impl TransportContext {
55 #[must_use]
57 pub fn new() -> Self {
58 Self::default()
59 }
60
61 pub fn insert<T: Send + Sync + 'static>(&mut self, value: T) {
63 self.values.insert(Arc::new(value));
64 }
65
66 #[must_use]
68 pub fn get<T: Send + Sync + 'static>(&self) -> Option<Arc<T>> {
69 self.values.get::<T>()
70 }
71}
72
73#[derive(Debug, Clone)]
75pub(crate) struct RequestMeta {
76 pub(crate) protocol_version: String,
77 pub(crate) client_capabilities: spec::ClientCapabilities,
78 pub(crate) client_info: Option<spec::Implementation>,
79 pub(crate) progress_token: Option<spec::ProgressToken>,
80 #[allow(deprecated)]
82 pub(crate) log_level: Option<spec::LoggingLevel>,
83}
84
85#[derive(Clone)]
90pub struct Ctx {
91 inner: Arc<CtxInner>,
92}
93
94struct CtxInner {
95 request_id: RequestId,
96 meta: RequestMeta,
97 cancellation: CancellationToken,
98 transport: TransportContext,
99 state: Arc<TypeMap>,
100 round: Option<Arc<Round>>,
101 notifier: Option<Arc<Notifier>>,
102}
103
104impl Ctx {
105 pub(crate) fn new(
106 request_id: RequestId,
107 meta: RequestMeta,
108 cancellation: CancellationToken,
109 transport: TransportContext,
110 state: Arc<TypeMap>,
111 round: Option<Arc<Round>>,
112 notifier: Option<Arc<Notifier>>,
113 ) -> Self {
114 Self {
115 inner: Arc::new(CtxInner {
116 request_id,
117 meta,
118 cancellation,
119 transport,
120 state,
121 round,
122 notifier,
123 }),
124 }
125 }
126
127 pub(crate) fn notifier(&self) -> Option<&Notifier> {
129 self.inner.notifier.as_deref()
130 }
131
132 pub(crate) fn notifier_handle(&self) -> Option<Arc<Notifier>> {
133 self.inner.notifier.clone()
134 }
135
136 pub(crate) fn round(&self) -> Option<&Round> {
138 self.inner.round.as_deref()
139 }
140
141 #[must_use]
143 pub fn request_id(&self) -> &RequestId {
144 &self.inner.request_id
145 }
146
147 #[must_use]
149 pub fn protocol_version(&self) -> &str {
150 &self.inner.meta.protocol_version
151 }
152
153 #[must_use]
155 pub fn client_capabilities(&self) -> &spec::ClientCapabilities {
156 &self.inner.meta.client_capabilities
157 }
158
159 #[must_use]
162 pub fn client_info(&self) -> Option<&spec::Implementation> {
163 self.inner.meta.client_info.as_ref()
164 }
165
166 #[must_use]
168 pub fn progress_token(&self) -> Option<&spec::ProgressToken> {
169 self.inner.meta.progress_token.as_ref()
170 }
171
172 #[must_use]
174 pub fn client_supports_extension(&self, id: &str) -> bool {
175 self.inner
176 .meta
177 .client_capabilities
178 .extensions
179 .as_ref()
180 .is_some_and(|e| e.contains_key(id))
181 }
182
183 #[must_use]
187 pub fn cancellation(&self) -> &CancellationToken {
188 &self.inner.cancellation
189 }
190
191 #[must_use]
193 pub fn is_cancelled(&self) -> bool {
194 self.inner.cancellation.is_cancelled()
195 }
196
197 #[must_use]
199 pub fn transport(&self) -> &TransportContext {
200 &self.inner.transport
201 }
202
203 #[must_use]
206 pub fn state<T: Send + Sync + 'static>(&self) -> Option<State<T>> {
207 self.inner.state.get::<T>().map(State)
208 }
209}
210
211impl fmt::Debug for Ctx {
212 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
213 f.debug_struct("Ctx")
214 .field("request_id", &self.inner.request_id)
215 .field("protocol_version", &self.inner.meta.protocol_version)
216 .field("cancelled", &self.is_cancelled())
217 .finish_non_exhaustive()
218 }
219}
220
221pub struct State<T: ?Sized>(Arc<T>);
227
228impl<T: ?Sized> State<T> {
229 #[must_use]
231 pub fn arc(&self) -> &Arc<T> {
232 &self.0
233 }
234
235 #[must_use]
237 pub fn into_arc(self) -> Arc<T> {
238 self.0
239 }
240}
241
242impl<T: ?Sized> Clone for State<T> {
243 fn clone(&self) -> Self {
244 Self(Arc::clone(&self.0))
245 }
246}
247
248impl<T: ?Sized> Deref for State<T> {
249 type Target = T;
250 fn deref(&self) -> &T {
251 &self.0
252 }
253}
254
255impl<T: ?Sized + fmt::Debug> fmt::Debug for State<T> {
256 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
257 f.debug_tuple("State").field(&self.0).finish()
258 }
259}