use std::marker::PhantomData; /// A `Layer` wraps `M`-typed `Stack` to produce a `Stack` /// /// Some `Stack` types are dependendent on and generic over an inner `Stack`. For /// example, a load balancer may implement `Stack` and be /// configured with a `Stack` that is used to build a service for /// each enpdoint. Such a load balancer would provide a signature like: /// /// ```ignore /// impl> Layer for BalanceLayer { ... } /// ``` pub trait Layer> { type Value; type Error; type Stack: super::Stack; /// Produces a `Stack` value from a `M` value. fn bind(&self, next: S) -> Self::Stack; /// Produces a new Layer with this layer wrapping the provided inner layer. fn and_then(self, inner: L) -> AndThen where N: super::Stack, L: Layer, Self: Layer + Sized, { AndThen { outer: self, inner, _p: PhantomData, } } /// Produces a new Layer with another layer wrapping this one. fn push(self, outer: L) -> AndThen where L: Layer, Self: Sized, { AndThen { outer, inner: self, _p: PhantomData, } } /// Wraps this layer such that stack errors are modified by `map_err`. fn map_err(self, map_err: M) -> AndThen, Self> where Self: Sized, M: super::map_err::MapErr, super::map_err::Layer: Layer, { super::map_err::layer(map_err).and_then(self) } } /// The identity layer. impl> Layer for () { type Value = M::Value; type Error = M::Error; type Stack = M; fn bind(&self, inner: M) -> M { inner } } /// Combines two `Layers` as one. /// /// Given an `Outer: Layer` and an `Inner: Layer`, producesa /// `Layer`, encapsulating the logic of the Outer and Inner layers. #[derive(Debug, Clone)] pub struct AndThen { outer: Outer, inner: Inner, // `AndThen` should be Send/Sync independently of U`. _p: PhantomData U>, } impl Layer for AndThen where Outer: Layer, Inner: Layer, M: super::Stack, { type Value = Outer::Value; type Error = Outer::Error; type Stack = Outer::Stack; fn bind(&self, next: M) -> Self::Stack { self.outer.bind(self.inner.bind(next)) } }