use std::collections::HashMap; use futures::{StreamExt, TryStreamExt}; use serde::Deserialize; use tokio_stream::{Stream, StreamMap}; use crate::Status; pub mod command; pub mod http; pub mod tcp; pub type ServiceHandles = HashMap; pub trait IntoService { type Error: std::error::Error + Sync + Send + Sized; fn into_service(self) -> impl Stream> + Send; } pub trait IntoServiceMap { type Error: std::error::Error + Sync + Send + Sized; fn into_service_map(self) -> impl Stream)> + Send; } impl IntoServiceMap for T where T: IntoIterator, V: IntoService, K: std::hash::Hash + std::cmp::Eq + std::clone::Clone + std::marker::Unpin + std::marker::Send, { type Error = V::Error; fn into_service_map(self) -> impl Stream)> + Send { let mut map = StreamMap::new(); for (name, srv) in self.into_iter() { map.insert(name, Box::pin(srv.into_service())); } map } } pub fn default_interval() -> std::time::Duration { std::time::Duration::from_secs(5) } #[derive(Debug, Clone, Deserialize)] #[serde(untagged)] pub enum ServiceConfig { Http(http::Http), Tcp(tcp::Tcp), Command(command::Command), } #[derive(Debug, thiserror::Error)] pub enum ServiceError { #[error(transparent)] Http(#[from] http::Error), #[error(transparent)] Tcp(#[from] tcp::Error), #[error(transparent)] Command(#[from] command::Error), } impl IntoService for ServiceConfig { type Error = ServiceError; fn into_service(self) -> impl Stream> + Send { match self { ServiceConfig::Http(h) => h.into_service().map_err(ServiceError::from).boxed(), ServiceConfig::Tcp(t) => t.into_service().map_err(ServiceError::from).boxed(), ServiceConfig::Command(c) => c.into_service().map_err(ServiceError::from).boxed(), } } }