use std::fmt::Debug;
use std::sync::Arc;
use crate::Service;
use crate::service::DynService;
pub trait DynamicServiceExt<In, Out>: Sized {
fn into_dynamic(self) -> DynamicService<In, Out>;
}
impl<In: Send + 'static, Out: Send + 'static, T> DynamicServiceExt<In, Out> for T
where
T: Service<In, Out = Out> + 'static,
{
fn into_dynamic(self) -> DynamicService<In, Out> {
DynamicService::new(self)
}
}
pub struct DynamicService<In, Out>(Arc<DynService<'static, In, Out>>);
impl<In: Send + 'static, Out: Send + 'static> DynamicService<In, Out> {
pub(crate) fn new<T>(strategy: T) -> Self
where
T: Service<In, Out = Out> + Send + Sync + 'static,
{
Self(DynService::new_arc(strategy))
}
}
impl<In: Send, Out: Send> Service<In> for DynamicService<In, Out> {
type Out = Out;
async fn execute(&self, input: In) -> Self::Out {
self.0.execute(input).await
}
}
impl<In, Out> Debug for DynamicService<In, Out> {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("DynamicService").finish()
}
}
impl<In, Out> Clone for DynamicService<In, Out> {
fn clone(&self) -> Self {
Self(Arc::clone(&self.0))
}
}
#[cfg_attr(coverage_nightly, coverage(off))]
#[cfg(test)]
mod tests {
use std::sync::Mutex;
use futures::executor::block_on;
use static_assertions::assert_impl_all;
use super::*;
use crate::Execute;
#[test]
fn assert_types() {
assert_impl_all!(DynamicService<(), ()>: Send, Sync, Clone, Debug);
assert_impl_all!(DynamicService<Mutex<()>, Mutex<()>>: Send, Sync, Clone, Debug);
}
#[test]
fn into_dynamic() {
let dynamic_service: DynamicService<i32, i32> = Execute::new(|v| async move { v }).into_dynamic();
assert_eq!(block_on(dynamic_service.execute(42)), 42);
}
#[test]
fn clone_and_debug() {
let svc: DynamicService<i32, i32> = Execute::new(|v| async move { v }).into_dynamic();
let cloned = svc.clone();
assert_eq!(block_on(cloned.execute(1)), 1);
assert_eq!(format!("{svc:?}"), "DynamicService");
}
}