use core::{fmt, pin::Pin};
use crate::std::{boxed::Box, sync::Arc};
use super::{ServiceMatch, ServiceMatcher};
pub trait DynServiceMatcher<Input>: Send + Sync + 'static {
type Service: Send + 'static;
type Error: Send + 'static;
type ModifiedInput: Send + 'static;
#[expect(clippy::type_complexity)]
fn match_service_box(
&self,
input: Input,
) -> Pin<
Box<
dyn Future<
Output = Result<ServiceMatch<Self::ModifiedInput, Self::Service>, Self::Error>,
> + Send
+ '_,
>,
>;
}
impl<Input, T> DynServiceMatcher<Input> for T
where
T: ServiceMatcher<Input>,
{
type Service = T::Service;
type Error = T::Error;
type ModifiedInput = T::ModifiedInput;
fn match_service_box(
&self,
input: Input,
) -> Pin<
Box<
dyn Future<
Output = Result<ServiceMatch<Self::ModifiedInput, Self::Service>, Self::Error>,
> + Send
+ '_,
>,
> {
Box::pin(self.match_service(input))
}
}
pub struct BoxServiceMatcher<Input, SelectedService, Error, ModifiedInput> {
inner: Arc<
dyn DynServiceMatcher<
Input,
Service = SelectedService,
Error = Error,
ModifiedInput = ModifiedInput,
> + Send
+ Sync
+ 'static,
>,
}
impl<Input, SelectedService, Error, ModifiedInput> Clone
for BoxServiceMatcher<Input, SelectedService, Error, ModifiedInput>
{
fn clone(&self) -> Self {
Self {
inner: self.inner.clone(),
}
}
}
impl<Input, SelectedService, Error, ModifiedInput>
BoxServiceMatcher<Input, SelectedService, Error, ModifiedInput>
{
#[inline]
pub fn new<T>(matcher: T) -> Self
where
T: ServiceMatcher<
Input,
Service = SelectedService,
Error = Error,
ModifiedInput = ModifiedInput,
>,
{
Self {
inner: Arc::new(matcher),
}
}
}
impl<Input, SelectedService, Error, ModifiedInput> fmt::Debug
for BoxServiceMatcher<Input, SelectedService, Error, ModifiedInput>
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("BoxServiceMatcher").finish()
}
}
impl<Input, SelectedService, Error, ModifiedInput> ServiceMatcher<Input>
for BoxServiceMatcher<Input, SelectedService, Error, ModifiedInput>
where
Input: 'static,
SelectedService: Send + 'static,
Error: Send + 'static,
ModifiedInput: Send + 'static,
{
type Service = SelectedService;
type Error = Error;
type ModifiedInput = ModifiedInput;
#[inline]
fn match_service(
&self,
input: Input,
) -> impl Future<Output = Result<ServiceMatch<Self::ModifiedInput, Self::Service>, Self::Error>>
+ Send
+ '_ {
self.inner.match_service_box(input)
}
async fn into_match_service(
self,
input: Input,
) -> Result<ServiceMatch<Self::ModifiedInput, Self::Service>, Self::Error>
where
Self: Sized,
Input: Send,
{
self.inner.match_service_box(input).await
}
#[inline]
fn boxed(self) -> Self {
self
}
}