Struct Extensions
pub struct Extensions { /* private fields */ }Expand description
A type map of protocol extensions.
Extensions are internally stored in a type erased Arc. Since values
are stored in an Arc there are extra methods exposed that build on top
of this and leverage characteristics of an Arc to expose things like
cheap cloning of the Arc.
Extensions may have an optional parent: the
Extensions this one was forked from. Lookups walk the parent chain when
the local Extensions don’t have the requested type. The parent relationship is
best described as “I’m layered on top of that, but I’m not exactly the same”:
- Retry attempts fork from the original request (dont leak failed extensions)
- Responses fork the request (response != request)
- H2 streams fork from underlying H2 connection (nested connection with isolated properties)
Connection’s who logically map one-to-one we don’t fork and we just pass the Extensions
up, examples are:
- TLS layered on top of TCP
- HTTP layered on top of TLS
- …
Implementations§
§impl Extensions
impl Extensions
pub fn new() -> Extensions
pub fn new() -> Extensions
Create an empty Extensions store with no parent.
pub fn fork(&self) -> Extensions
pub fn fork(&self) -> Extensions
Create a fresh child Extensions whose parent is this Extensions store.
The child has its own empty top-level storage. Lookups that miss locally walk into the parent (and recursively up the chain). Inserts land on this child only, parents are never mutated through the child.
pub fn parent(&self) -> Option<&Extensions>
pub fn parent(&self) -> Option<&Extensions>
The parent Extensions this blob was forked from, if any.
pub fn insert<T>(&self, val: T) -> &Twhere
T: Extension,
pub fn insert<T>(&self, val: T) -> &Twhere
T: Extension,
Insert a type T into this Extensions store.
This method returns a reference to the just inserted value.
If the value you are inserting is an Arc<T>, prefer using
Self::insert_arc to prevent the double indirection of storing
an Arc<Arc<T>>.
pub fn insert_arc<T>(&self, val: Arc<T>) -> Arc<T> ⓘwhere
T: Extension,
pub fn insert_arc<T>(&self, val: Arc<T>) -> Arc<T> ⓘwhere
T: Extension,
Insert a type Arc<T> into this [Extensions] store.
This method returns a a cloned Arc of the value just inserted
If the value you are inserting is not an Arc<T> or you don’t
need a cloned Arc<T> prefer using Self::insert()
pub fn extend(&self, other: &Extensions)
pub fn extend(&self, other: &Extensions)
Extend this Extensions store with the other Extensions.
The other Extensionss will be appended behind the current ones
pub fn contains<T>(&self) -> boolwhere
T: Extension,
pub fn contains<T>(&self) -> boolwhere
T: Extension,
Returns true if the Extensions store contains the given type.
This function is recursive and will traverse multiple nested Extensions
stores to find the correct item. See Extensions::get_ref() for how this works.
If you don’t want any of this special logic and you just want to check this
Extensions store, use Extensions::self_contains() instead.
pub fn self_contains<T>(&self) -> boolwhere
T: Extension,
pub fn self_contains<T>(&self) -> boolwhere
T: Extension,
Returns true if this Extensions store contains the given type
This only checks this Extensions store
pub fn get_ref<T>(&self) -> Option<&T>where
T: Extension,
pub fn get_ref<T>(&self) -> Option<&T>where
T: Extension,
Get a reference to T. Walks the parent chain and the connection
wrappers (Egress / Ingress) if not found locally.
Search rule (single pass, newest insertion wins):
- Iterate local entries newest -> oldest. For each entry:
- if its type matches
T, return it, - if it is an
Egress<Extensions>orIngress<Extensions>wrapper, recurse into the wrapped blob with the same rule (its own local first, then its wrappers, then its parent) and return any match found, - otherwise skip.
- if its type matches
- If still not found, recurse into the parent (same rule applied).
Wrappers are spliced into the local scan in insertion order, so a
connection-pointer detour inserted on this blob is treated as part of
“local” for ordering purposes: a directly-inserted T and a wrapper
containing T both compete by insertion time, newest wins. Parent is
only consulted after the entire local scan (including wrapper
recursion) finishes empty. The wrappers themselves can still be
retrieved directly (or via Self::egress / Self::ingress).
For a raw flat lookup, use Self::self_get_ref.
Returns the most recently inserted match, for the oldest, see Self::self_first_ref.
pub fn self_get_ref<T>(&self) -> Option<&T>where
T: Extension,
pub fn self_get_ref<T>(&self) -> Option<&T>where
T: Extension,
Raw flat Self::get_ref: returns the most recently inserted T, for the oldest, see Self::self_first_ref.
This only checks this Extensions store
pub fn get_arc<T>(&self) -> Option<Arc<T>>where
T: Extension,
pub fn get_arc<T>(&self) -> Option<Arc<T>>where
T: Extension,
Get an owned Arc<T>. Walks the parent chain and the structural
connection wrappers if not found locally.
See Self::get_ref for the search order.
For a raw flat lookup (top-level only), use Self::self_get_arc.
pub fn self_get_arc<T>(&self) -> Option<Arc<T>>where
T: Extension,
pub fn self_get_arc<T>(&self) -> Option<Arc<T>>where
T: Extension,
Raw flat Self::get_arc: returns the most recently inserted T
This only checks this Extensions store
pub fn get_ref_or_insert<T, F>(&self, create_fn: F) -> &T
pub fn get_ref_or_insert<T, F>(&self, create_fn: F) -> &T
Recursive find-or-create: return &T if one exists anywhere in this
this Extensions store (using Self::get_ref dispatch), otherwise
insert the value produced by create_fn at the top level and return
a reference to it.
Useful when a type conceptually belongs to the scope (e.g. ConnectionHealth
on a connection chain) and you want to reuse an existing instance rather
than create a duplicate at every layer. For strict “ensure local exists”,
use Self::self_get_ref_or_insert.
pub fn get_arc_or_insert<T, F>(&self, create_fn: F) -> Arc<T> ⓘ
pub fn get_arc_or_insert<T, F>(&self, create_fn: F) -> Arc<T> ⓘ
Recursive find-or-create returning an Arc<T>: see Self::get_ref_or_insert.
pub fn self_get_ref_or_insert<T, F>(&self, create_fn: F) -> &T
pub fn self_get_ref_or_insert<T, F>(&self, create_fn: F) -> &T
Raw flat find-or-create: return &T if one exists at the top level of
this Extensions store, otherwise insert the value produced by
create_fn at the top level and return a reference to it.
Does not follow the parent chain. Useful when you want strict “ensure T
exists on THIS blob” (e.g. materializing a direction wrapper
like Ingress<Connection<Extensions>> at the outer blob).
pub fn self_get_arc_or_insert<T, F>(&self, create_fn: F) -> Arc<T> ⓘ
pub fn self_get_arc_or_insert<T, F>(&self, create_fn: F) -> Arc<T> ⓘ
Raw flat find-or-create returning an Arc<T>: see Self::self_get_ref_or_insert.
pub fn self_first_ref<T>(&self) -> Option<&T>where
T: Extension,
pub fn self_first_ref<T>(&self) -> Option<&T>where
T: Extension,
Raw flat reference to the oldest inserted T at the top level of this
Extensions store, does not walk structural wrappers.
In most cases you want Self::get_ref (newest, scope-aware). Use this
only when you specifically need insertion order access inside this Extensions
store.
Currently we dont provide a recursive variant of this method since we don’t have a use case for it, and it’s not exactly clear what would be considered “first”.
pub fn self_first_arc<T>(&self) -> Option<Arc<T>>where
T: Extension,
pub fn self_first_arc<T>(&self) -> Option<Arc<T>>where
T: Extension,
Raw flat Arc<T> to the oldest inserted T at the top level, see
Self::self_first_ref for caveats.
pub fn self_iter_ref<T>(&self) -> impl Iterator<Item = &T>where
T: Extension,
pub fn self_iter_ref<T>(&self) -> impl Iterator<Item = &T>where
T: Extension,
Raw flat iteration over all inserted items of type T at the top level
of this Extensions store, newest to oldest.
The order matches Self::self_get_ref (newest-first), so
self_iter_ref::<T>().next() == self_get_ref::<T>().
pub fn self_iter_arc<T>(&self) -> impl Iterator<Item = Arc<T>>where
T: Extension,
pub fn self_iter_arc<T>(&self) -> impl Iterator<Item = Arc<T>>where
T: Extension,
Raw flat iteration over all inserted items of type T at the top level
as cloned Arc values, newest to oldest.
The order matches Self::self_get_arc (newest-first), so
self_iter_arc::<T>().next() == self_get_arc::<T>().
pub fn self_iter_all(&self) -> impl Iterator<Item = &TypeErasedExtension>
pub fn self_iter_all(&self) -> impl Iterator<Item = &TypeErasedExtension>
Raw flat iteration over all TypeErasedExtension entries at the top
level of this Extensions store.
Use to efficiently combine different types of Extensions in a single
iteration. TypeErasedExtension exposes methods to convert back to
type T when it matches the erased type.
pub fn iter_ref<T>(&self) -> impl Iterator<Item = &T>where
T: Extension,
pub fn iter_ref<T>(&self) -> impl Iterator<Item = &T>where
T: Extension,
Iterate over all inserted items of type T, walking the parent chain
and the structural Egress / Ingress connection wrappers.
Yield order matches Self::get_ref preference (so
iter_ref::<T>().next() == get_ref::<T>()):
At each level, iterate the local entries newest -> oldest. For each
entry: yield it if its type matches T, if it is an
Egress<Extensions> or Ingress<Extensions> wrapper, recurse into
the wrapped blob (same rule applied) and yield its results inline. Then
recurse into the parent.
For a flat top-level-only iteration use Self::self_iter_ref.
The iterator type is left opaque (impl Iterator) so the internal
representation can change without breaking callers.
pub fn iter_arc<T>(&self) -> impl Iterator<Item = Arc<T>>where
T: Extension,
pub fn iter_arc<T>(&self) -> impl Iterator<Item = Arc<T>>where
T: Extension,
Iteration yielding cloned Arc<T> values, see Self::iter_ref.
pub fn ingress(&self) -> Option<&Ingress<Extensions>>
pub fn ingress(&self) -> Option<&Ingress<Extensions>>
Get a reference to the Ingress<Extensions> wrapper if one exists
on this blob or anywhere reachable through the parent chain.
Returns None when no ingress wrapper has been set up. For correctly
constructed server-side requests this is always Some, server
stacks insert the wrapper at the boundary where the connection becomes
visible to a request, so a None here is almost always a framework
setup bug rather than a normal state.
This is just a shortcut for extensions.get_ref::<Ingress<Extensions>>()
pub fn egress(&self) -> Option<&Egress<Extensions>>
pub fn egress(&self) -> Option<&Egress<Extensions>>
Get a reference to the Egress<Extensions> wrapper if one exists
on this blob or anywhere reachable through the parent chain.
See Self::ingress for semantics.
This is just a shortcut for extensions.get_ref::<Egress<Extensions>>()
Trait Implementations§
§impl Clone for Extensions
impl Clone for Extensions
§fn clone(&self) -> Extensions
fn clone(&self) -> Extensions
1.0.0 (const: unstable) · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source. Read more§impl Debug for Extensions
impl Debug for Extensions
§impl Default for Extensions
impl Default for Extensions
§fn default() -> Extensions
fn default() -> Extensions
§impl ExtensionsRef for Extensions
impl ExtensionsRef for Extensions
§fn extensions(&self) -> &Extensions
fn extensions(&self) -> &Extensions
Extensions store§impl FromRequest for Extensions
impl FromRequest for Extensions
§type Rejection = Infallible
type Rejection = Infallible
§async fn from_request(
req: Request,
) -> Result<Extensions, <Extensions as FromRequest>::Rejection>
async fn from_request( req: Request, ) -> Result<Extensions, <Extensions as FromRequest>::Rejection>
§impl IntoResponse for Extensions
impl IntoResponse for Extensions
§fn into_response(self) -> Response
fn into_response(self) -> Response
§impl IntoResponseParts for Extensions
impl IntoResponseParts for Extensions
§type Error = Infallible
type Error = Infallible
§fn into_response_parts(
self,
res: ResponseParts,
) -> Result<ResponseParts, <Extensions as IntoResponseParts>::Error>
fn into_response_parts( self, res: ResponseParts, ) -> Result<ResponseParts, <Extensions as IntoResponseParts>::Error>
Auto Trait Implementations§
impl Freeze for Extensions
impl RefUnwindSafe for Extensions
impl Send for Extensions
impl Sync for Extensions
impl Unpin for Extensions
impl UnsafeUnpin for Extensions
impl UnwindSafe for Extensions
Blanket Implementations§
§impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedExplicit<'a, E> for Twhere
T: 'a,
§impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
impl<'a, T, E> AsTaggedImplicit<'a, E> for Twhere
T: 'a,
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
§impl<T> FutureExt for T
impl<T> FutureExt for T
§fn with_context(self, otel_cx: Context) -> WithContext<Self> ⓘ
fn with_context(self, otel_cx: Context) -> WithContext<Self> ⓘ
§fn with_current_context(self) -> WithContext<Self> ⓘ
fn with_current_context(self) -> WithContext<Self> ⓘ
§impl<T> Instrument for T
impl<T> Instrument for T
§fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
fn instrument(self, span: Span) -> Instrumented<Self> ⓘ
§fn in_current_span(self) -> Instrumented<Self> ⓘ
fn in_current_span(self) -> Instrumented<Self> ⓘ
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
fn into_either(self, into_left: bool) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self> ⓘ
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more§impl<R> IntoEndpointService<()> for R
impl<R> IntoEndpointService<()> for R
type Service = StaticService<R>
§fn into_endpoint_service(self) -> <R as IntoEndpointService<()>>::Service
fn into_endpoint_service(self) -> <R as IntoEndpointService<()>>::Service
rama_core::Service.§impl<R, State> IntoEndpointServiceWithState<(), State> for R
impl<R, State> IntoEndpointServiceWithState<(), State> for R
type Service = StaticService<R>
§fn into_endpoint_service_with_state(
self,
_state: State,
) -> <R as IntoEndpointServiceWithState<(), State>>::Service
fn into_endpoint_service_with_state( self, _state: State, ) -> <R as IntoEndpointServiceWithState<(), State>>::Service
rama_core::Service with state.§impl<T> IntoRequest<T> for T
impl<T> IntoRequest<T> for T
§fn into_request(self) -> Request<T>
fn into_request(self) -> Request<T>
T in a rama_grpc::Request§impl<T> Pointable for T
impl<T> Pointable for T
§impl<T> PolicyExt for Twhere
T: ?Sized,
impl<T> PolicyExt for Twhere
T: ?Sized,
§fn and<P, B, E>(self, other: P) -> And<T, P>
fn and<P, B, E>(self, other: P) -> And<T, P>
Policy that returns Action::Follow only if self and other return
Action::Follow. Read more§impl<T, U> RamaTryFrom<T> for Uwhere
U: TryFrom<T>,
impl<T, U> RamaTryFrom<T> for Uwhere
U: TryFrom<T>,
type Error = <U as TryFrom<T>>::Error
fn rama_try_from(value: T) -> Result<U, <U as RamaTryFrom<T>>::Error>
§impl<T, U, CrateMarker> RamaTryInto<U, CrateMarker> for Twhere
U: RamaTryFrom<T, CrateMarker>,
impl<T, U, CrateMarker> RamaTryInto<U, CrateMarker> for Twhere
U: RamaTryFrom<T, CrateMarker>,
type Error = <U as RamaTryFrom<T, CrateMarker>>::Error
fn rama_try_into(self) -> Result<U, <U as RamaTryFrom<T, CrateMarker>>::Error>
§impl<V, F> ValueFormatter<&V> for F
impl<V, F> ValueFormatter<&V> for F
§fn format_value(writer: impl ValueWriter, value: &&V)
fn format_value(writer: impl ValueWriter, value: &&V)
value to writer§impl<V, F> ValueFormatter<Arc<V>> for F
impl<V, F> ValueFormatter<Arc<V>> for F
§fn format_value(writer: impl ValueWriter, value: &Arc<V>)
fn format_value(writer: impl ValueWriter, value: &Arc<V>)
value to writer§impl<V, F> ValueFormatter<Box<V>> for F
impl<V, F> ValueFormatter<Box<V>> for F
§fn format_value(writer: impl ValueWriter, value: &Box<V>)
fn format_value(writer: impl ValueWriter, value: &Box<V>)
value to writer§impl<V, F> ValueFormatter<Cow<'_, V>> for F
impl<V, F> ValueFormatter<Cow<'_, V>> for F
§fn format_value(writer: impl ValueWriter, value: &Cow<'_, V>)
fn format_value(writer: impl ValueWriter, value: &Cow<'_, V>)
value to writer§impl<V, F> ValueFormatter<Option<V>> for Fwhere
F: ValueFormatter<V> + ?Sized,
impl<V, F> ValueFormatter<Option<V>> for Fwhere
F: ValueFormatter<V> + ?Sized,
§fn format_value(writer: impl ValueWriter, value: &Option<V>)
fn format_value(writer: impl ValueWriter, value: &Option<V>)
value to writer