Skip to main content

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}