hyperlane_core/context/impl.rs
1use super::*;
2
3/// Implementation of `Default` trait for `Context`.
4impl Default for Context {
5 /// Creates a default `Context` instance.
6 ///
7 /// # Returns
8 ///
9 /// - `Context` - A new context with default values and a static default server.
10 #[inline(always)]
11 fn default() -> Self {
12 Self {
13 request: Request::default(),
14 response: Response::default(),
15 route_params: RouteParams::default(),
16 attributes: ThreadSafeAttributeStore::default(),
17 }
18 }
19}
20
21/// Implementation of `PartialEq` trait for `Context`.
22impl PartialEq for Context {
23 /// Compares two `Context` instances for equality.
24 ///
25 /// # Arguments
26 ///
27 /// - `&Self` - The first `Context` instance.
28 /// - `&Self` - The second `Context` instance.
29 ///
30 /// # Returns
31 ///
32 /// - `bool` - True if the instances are equal, otherwise false.
33 #[inline(always)]
34 fn eq(&self, other: &Self) -> bool {
35 self.get_request() == other.get_request()
36 && self.get_response() == other.get_response()
37 && self.get_route_params() == other.get_route_params()
38 && self.get_attributes().len() == other.get_attributes().len()
39 }
40}
41
42/// Implementation of `Eq` trait for `Context`.
43impl Eq for Context {}
44
45/// Implementation of `From` trait for converting `usize` address into `&Context`.
46impl From<usize> for &'static Context {
47 /// Converts a memory address into a reference to `Context`.
48 ///
49 /// # Arguments
50 ///
51 /// - `usize` - The memory address of the `Context` instance.
52 ///
53 /// # Returns
54 ///
55 /// - `&'static Context` - A reference to the `Context` at the given address.
56 ///
57 /// # Safety
58 ///
59 /// - The address is guaranteed to be a valid `Context` instance
60 /// that was previously converted from a reference and is managed by the runtime.
61 #[inline(always)]
62 fn from(address: usize) -> &'static Context {
63 unsafe { &*(address as *const Context) }
64 }
65}
66
67/// Implementation of `From` trait for converting `usize` address into `&mut Context`.
68impl<'a> From<usize> for &'a mut Context {
69 /// Converts a memory address into a mutable reference to `Context`.
70 ///
71 /// # Arguments
72 ///
73 /// - `usize` - The memory address of the `Context` instance.
74 ///
75 /// # Returns
76 ///
77 /// - `&'a mut Context` - A mutable reference to the `Context` at the given address.
78 ///
79 /// # Safety
80 ///
81 /// - The address is guaranteed to be a valid `Context` instance
82 /// that was previously converted from a reference and is managed by the runtime.
83 #[inline(always)]
84 fn from(address: usize) -> &'a mut Context {
85 unsafe { &mut *(address as *mut Context) }
86 }
87}
88
89/// Implementation of `From` trait for converting `&Context` into `usize` address.
90impl From<&Context> for usize {
91 /// Converts a reference to `Context` into its memory address.
92 ///
93 /// # Arguments
94 ///
95 /// - `&Context` - The reference to the `Context` instance.
96 ///
97 /// # Returns
98 ///
99 /// - `usize` - The memory address of the `Context` instance.
100 #[inline(always)]
101 fn from(ctx: &Context) -> Self {
102 ctx as *const Context as usize
103 }
104}
105
106/// Implementation of `From` trait for converting `&mut Context` into `usize` address.
107impl From<&mut Context> for usize {
108 /// Converts a mutable reference to `Context` into its memory address.
109 ///
110 /// # Arguments
111 ///
112 /// - `&mut Context` - The mutable reference to the `Context` instance.
113 ///
114 /// # Returns
115 ///
116 /// - `usize` - The memory address of the `Context` instance.
117 #[inline(always)]
118 fn from(ctx: &mut Context) -> Self {
119 ctx as *mut Context as usize
120 }
121}
122
123/// Implementation of `AsRef` trait for `Context`.
124impl AsRef<Context> for Context {
125 /// Converts `&Context` to `&Context` via memory address conversion.
126 ///
127 /// # Returns
128 ///
129 /// - `&Self` - A reference to the `Context` instance.
130 #[inline(always)]
131 fn as_ref(&self) -> &Self {
132 let address: usize = self.into();
133 address.into()
134 }
135}
136
137/// Implementation of `AsMut` trait for `Context`.
138impl AsMut<Context> for Context {
139 /// Converts `&mut Context` to `&mut Context` via memory address conversion.
140 ///
141 /// # Returns
142 ///
143 /// - `&mut Self` - A mutable reference to the `Context` instance.
144 #[inline(always)]
145 fn as_mut(&mut self) -> &mut Self {
146 let address: usize = self.into();
147 address.into()
148 }
149}
150
151/// Implementation of `Lifetime` trait for `Context`.
152impl Lifetime for Context {
153 /// Converts a reference to the context into a `'static` reference.
154 ///
155 /// # Returns
156 ///
157 /// - `&'static Self` - A reference to the context with a `'static` lifetime.
158 ///
159 /// # Safety
160 ///
161 /// - The address is guaranteed to be a valid `Self` instance
162 /// that was previously converted from a reference and is managed by the runtime.
163 #[inline(always)]
164 unsafe fn leak(&self) -> &'static Self {
165 let address: usize = self.into();
166 address.into()
167 }
168
169 /// Converts a reference to the context into a `'static` mutable reference.
170 ///
171 /// # Returns
172 ///
173 /// - `&'static mut Self` - A mutable reference to the context with a `'static` lifetime.
174 ///
175 /// # Safety
176 ///
177 /// - The address is guaranteed to be a valid `Self` instance
178 /// that was previously converted from a reference and is managed by the runtime.
179 #[inline(always)]
180 unsafe fn leak_mut(&self) -> &'static mut Self {
181 let address: usize = self.into();
182 address.into()
183 }
184}
185
186/// Implementation of methods for `Context` structure.
187impl Context {
188 /// Clears all route parameters while retaining the map's allocated capacity.
189 ///
190 /// Used between keep-alive requests on the same connection to avoid
191 /// reallocating the parameter map for every request.
192 ///
193 /// # Returns
194 ///
195 /// - `&mut Self` - A mutable reference to self for chaining.
196 #[inline(always)]
197 pub(crate) fn clear_route_params(&mut self) -> &mut Self {
198 self.get_mut_route_params().clear();
199 self
200 }
201
202 /// Attempts to retrieve a specific route parameter by its name.
203 ///
204 /// # Arguments
205 ///
206 /// - `T` - The name of the route parameter to retrieve.
207 ///
208 /// # Returns
209 ///
210 /// - `Option<String>` - The value of the route parameter if it exists.
211 #[inline(always)]
212 pub fn try_get_route_param<T>(&self, name: T) -> Option<String>
213 where
214 T: AsRef<str>,
215 {
216 self.get_route_params().get(name.as_ref()).cloned()
217 }
218
219 /// Retrieves a specific route parameter by its name, panicking if not found.
220 ///
221 /// # Arguments
222 ///
223 /// - `T` - The name of the route parameter to retrieve.
224 ///
225 /// # Returns
226 ///
227 /// - `String` - The value of the route parameter if it exists.
228 ///
229 /// # Panics
230 ///
231 /// - If the route parameter is not found.
232 #[inline(always)]
233 pub fn get_route_param<T>(&self, name: T) -> String
234 where
235 T: AsRef<str>,
236 {
237 self.try_get_route_param(name).unwrap()
238 }
239
240 /// Returns the original wire request target before routing or query-map conversion.
241 ///
242 /// # Returns
243 ///
244 /// - `Option<String>` - The unchanged path and query, or none for a manually constructed context.
245 pub fn get_request_target(&self) -> Option<String> {
246 self.try_get_attribute(REQUEST_TARGET_ATTRIBUTE)
247 }
248
249 /// Stores the original target for the current request before user middleware runs.
250 ///
251 /// # Arguments
252 ///
253 /// - `String` - The unmodified target supplied by the protocol transport.
254 ///
255 /// # Returns
256 ///
257 /// - `&mut Self` - The context retaining its request-local target snapshot.
258 pub(crate) fn set_request_target(&mut self, target: String) -> &mut Self {
259 self.set_attribute(REQUEST_TARGET_ATTRIBUTE, target)
260 }
261
262 /// Attempts to retrieve a specific attribute by its key, casting it to the specified type.
263 ///
264 /// # Arguments
265 ///
266 /// - `K` - The key of the attribute to retrieve.
267 ///
268 /// # Returns
269 ///
270 /// - `Option<V>` - The attribute value if it exists and can be cast to the specified type.
271 #[inline(always)]
272 pub fn try_get_attribute<V, K>(&self, key: K) -> Option<V>
273 where
274 V: AnySendSyncClone,
275 K: AsRef<str>,
276 {
277 self.get_attributes()
278 .get(&Attribute::External(key.as_ref().to_owned()).to_string())
279 .and_then(|arc: &ArcAnySendSync| arc.downcast_ref::<V>())
280 .cloned()
281 }
282
283 /// Retrieves a specific attribute by its key, casting it to the specified type, panicking if not found.
284 ///
285 /// # Arguments
286 ///
287 /// - `K` - The key of the attribute to retrieve.
288 ///
289 /// # Returns
290 ///
291 /// - `V` - The attribute value if it exists and can be cast to the specified type.
292 ///
293 /// # Panics
294 ///
295 /// - If the attribute is not found.
296 #[inline(always)]
297 pub fn get_attribute<V, K>(&self, key: K) -> V
298 where
299 V: AnySendSyncClone,
300 K: AsRef<str>,
301 {
302 self.try_get_attribute(key).unwrap()
303 }
304
305 /// Sets an attribute in the context.
306 ///
307 /// # Arguments
308 ///
309 /// - `K` - The key of the attribute to set.
310 /// - `V` - The value of the attribute.
311 ///
312 /// # Returns
313 ///
314 /// - `&mut Self` - A reference to the modified context.
315 #[inline(always)]
316 pub fn set_attribute<K, V>(&mut self, key: K, value: V) -> &mut Self
317 where
318 K: AsRef<str>,
319 V: AnySendSyncClone,
320 {
321 self.get_mut_attributes().insert(
322 Attribute::External(key.as_ref().to_owned()).to_string(),
323 Arc::new(value),
324 );
325 self
326 }
327
328 /// Removes an attribute from the context.
329 ///
330 /// # Arguments
331 ///
332 /// - `K` - The key of the attribute to remove.
333 ///
334 /// # Returns
335 ///
336 /// - `&mut Self` - A reference to the modified context.
337 #[inline(always)]
338 pub fn remove_attribute<K>(&mut self, key: K) -> &mut Self
339 where
340 K: AsRef<str>,
341 {
342 self.get_mut_attributes()
343 .remove(&Attribute::External(key.as_ref().to_owned()).to_string());
344 self
345 }
346
347 /// Clears all attributes from the context.
348 ///
349 /// # Returns
350 ///
351 /// - `&mut Self` - A reference to the modified context.
352 #[inline(always)]
353 pub fn clear_attribute(&mut self) -> &mut Self {
354 self.get_mut_attributes().clear();
355 self
356 }
357
358 /// Retrieves an internal framework attribute.
359 ///
360 /// # Arguments
361 ///
362 /// - `InternalAttribute` - The internal attribute key to retrieve.
363 ///
364 /// # Returns
365 ///
366 /// - `Option<V>` - The attribute value if it exists and can be cast to the specified type.
367 #[inline(always)]
368 fn try_get_internal_attribute<V>(&self, key: InternalAttribute) -> Option<V>
369 where
370 V: AnySendSyncClone,
371 {
372 self.get_attributes()
373 .get(&Attribute::Internal(key).to_string())
374 .and_then(|arc: &ArcAnySendSync| arc.downcast_ref::<V>())
375 .cloned()
376 }
377
378 /// Retrieves an internal framework attribute.
379 ///
380 /// # Arguments
381 ///
382 /// - `InternalAttribute` - The internal attribute key to retrieve.
383 ///
384 /// # Returns
385 ///
386 /// - `V` - The attribute value if it exists and can be cast to the specified type.
387 ///
388 /// # Panics
389 ///
390 /// - If the attribute is not found.
391 #[inline(always)]
392 fn get_internal_attribute<V>(&self, key: InternalAttribute) -> V
393 where
394 V: AnySendSyncClone,
395 {
396 self.try_get_internal_attribute(key).unwrap()
397 }
398
399 /// Sets an internal framework attribute.
400 ///
401 /// # Arguments
402 ///
403 /// - `InternalAttribute` - The internal attribute key to set.
404 /// - `V` - The value of the attribute.
405 ///
406 /// # Returns
407 ///
408 /// - `&mut Self` - A reference to the modified context.
409 #[inline(always)]
410 fn set_internal_attribute<V>(&mut self, key: InternalAttribute, value: V) -> &mut Self
411 where
412 V: AnySendSyncClone,
413 {
414 self.get_mut_attributes()
415 .insert(Attribute::Internal(key).to_string(), Arc::new(value));
416 self
417 }
418
419 /// Stores panic data for the current task context.
420 ///
421 /// # Arguments
422 ///
423 /// - `PanicData` - The panic data specific to the current task.
424 ///
425 /// # Returns
426 ///
427 /// - `&mut Self` - Reference to the modified context for method chaining.
428 #[inline(always)]
429 pub fn set_task_panic(&mut self, panic_data: PanicData) -> &mut Self {
430 self.set_internal_attribute(InternalAttribute::TaskPanicData, panic_data)
431 }
432
433 /// Retrieves panic data associated with the current task.
434 ///
435 /// # Returns
436 ///
437 /// - `Option<PanicData>` - Task panic data if a panic was caught during execution.
438 #[inline(always)]
439 pub fn try_get_task_panic_data(&self) -> Option<PanicData> {
440 self.try_get_internal_attribute(InternalAttribute::TaskPanicData)
441 }
442
443 /// Retrieves panic data associated with the current task.
444 ///
445 /// # Returns
446 ///
447 /// - `PanicData` - Task panic data if available.
448 ///
449 /// # Panics
450 ///
451 /// - If no task panic data is found.
452 #[inline(always)]
453 pub fn get_task_panic_data(&self) -> PanicData {
454 self.get_internal_attribute(InternalAttribute::TaskPanicData)
455 }
456
457 /// Sets the request error information for the context.
458 ///
459 /// # Arguments
460 ///
461 /// - `RequestError` - The request error information to store.
462 ///
463 /// # Returns
464 ///
465 /// - `&mut Self` - A reference to the modified context.
466 #[inline(always)]
467 pub(crate) fn set_request_error_data(&mut self, request_error: RequestError) -> &mut Self {
468 self.set_internal_attribute(InternalAttribute::RequestErrorData, request_error)
469 }
470
471 /// Retrieves request error information if an error occurred during handling.
472 ///
473 /// # Returns
474 ///
475 /// - `Option<RequestError>` - The request error information if an error was caught.
476 #[inline(always)]
477 pub fn try_get_request_error_data(&self) -> Option<RequestError> {
478 self.try_get_internal_attribute(InternalAttribute::RequestErrorData)
479 }
480
481 /// Retrieves request error information if an error occurred during handling.
482 ///
483 /// # Returns
484 ///
485 /// - `RequestError` - The request error information if an error was caught.
486 ///
487 /// # Panics
488 ///
489 /// - If the request error information is not found.
490 #[inline(always)]
491 pub fn get_request_error_data(&self) -> RequestError {
492 self.get_internal_attribute(InternalAttribute::RequestErrorData)
493 }
494}