use tower::{
ServiceBuilder,
layer::util::{Identity, Stack},
};
#[derive(Clone, Copy, Debug, Default)]
pub struct StandardResponses;
#[doc(hidden)]
pub struct LayeredResponses<L>(pub(crate) ServiceBuilder<L>);
#[doc(hidden)]
pub struct FactoryResponses<F>(pub(crate) F);
pub struct Responses<S = StandardResponses> {
pub(crate) websocket_url: Option<String>,
pub(crate) api_base_url: Option<String>,
pub(crate) service: S,
}
impl Default for Responses<StandardResponses> {
fn default() -> Self {
Self {
websocket_url: None,
api_base_url: None,
service: StandardResponses,
}
}
}
impl Responses<StandardResponses> {
#[must_use]
pub fn builder() -> ResponsesBuilder<StandardResponses> {
ResponsesBuilder {
responses: Self::default(),
}
}
}
impl ResponsesBuilder<StandardResponses> {
#[must_use]
pub fn layer<L>(self, layer: L) -> ResponsesBuilder<LayeredResponses<Stack<L, Identity>>> {
ResponsesBuilder {
responses: Responses {
websocket_url: self.responses.websocket_url,
api_base_url: self.responses.api_base_url,
service: LayeredResponses(ServiceBuilder::new().layer(layer)),
},
}
}
#[must_use]
pub fn service<F, S>(self, factory: F) -> ResponsesBuilder<FactoryResponses<F>>
where
F: Fn() -> S,
{
ResponsesBuilder {
responses: Responses {
websocket_url: self.responses.websocket_url,
api_base_url: self.responses.api_base_url,
service: FactoryResponses(factory),
},
}
}
}
impl<L> ResponsesBuilder<LayeredResponses<L>> {
#[must_use]
pub fn layer<T>(self, layer: T) -> ResponsesBuilder<LayeredResponses<Stack<T, L>>> {
ResponsesBuilder {
responses: Responses {
websocket_url: self.responses.websocket_url,
api_base_url: self.responses.api_base_url,
service: LayeredResponses(self.responses.service.0.layer(layer)),
},
}
}
}
pub struct ResponsesBuilder<S> {
responses: Responses<S>,
}
impl<S> ResponsesBuilder<S> {
#[must_use]
pub fn websocket_url(mut self, url: impl Into<String>) -> Self {
self.responses.websocket_url = Some(url.into());
self
}
#[must_use]
pub fn api_base_url(mut self, url: impl Into<String>) -> Self {
self.responses.api_base_url = Some(url.into());
self
}
#[must_use]
pub fn build(self) -> Responses<S> {
self.responses
}
}