use std::{convert::Infallible, sync::Arc, task::Poll};
use http::{Response, StatusCode};
use http_api_problem::ApiError;
use hyper::Body;
use manas_http::service::BoxHttpResponseFuture;
use manas_repo::service::resource_operator::deleter::ResourceDeleteResponse;
use tower::Service;
use crate::{
service::method::common::snippet::authorization::attach_authorization_context, SolidStorage,
};
#[derive(Debug, Clone, Default)]
pub struct DefaultBaseDeleteResponseMarshallerConfig {
pub dev_mode: bool,
}
#[derive(Debug)]
pub struct DefaultBaseDeleteResponseMarshaller<Storage> {
pub storage: Arc<Storage>,
pub marshal_config: DefaultBaseDeleteResponseMarshallerConfig,
}
impl<Storage: SolidStorage> Clone for DefaultBaseDeleteResponseMarshaller<Storage> {
#[inline]
fn clone(&self) -> Self {
Self {
storage: self.storage.clone(),
marshal_config: self.marshal_config.clone(),
}
}
}
impl<Storage> DefaultBaseDeleteResponseMarshaller<Storage> {
#[inline]
pub fn new(
storage: Arc<Storage>,
marshal_config: DefaultBaseDeleteResponseMarshallerConfig,
) -> Self {
Self {
storage,
marshal_config,
}
}
}
impl<Storage> Service<Result<ResourceDeleteResponse<Storage::Repo>, ApiError>>
for DefaultBaseDeleteResponseMarshaller<Storage>
where
Storage: SolidStorage,
{
type Response = Response<Body>;
type Error = Infallible;
type Future = BoxHttpResponseFuture<Body>;
#[inline]
fn poll_ready(&mut self, _cx: &mut std::task::Context<'_>) -> Poll<Result<(), Self::Error>> {
Poll::Ready(Ok(()))
}
#[inline]
#[tracing::instrument(skip_all, name = "DefaultBaseDeleteResponseMarshaller::call")]
fn call(
&mut self,
req: Result<ResourceDeleteResponse<Storage::Repo>, ApiError>,
) -> Self::Future {
Box::pin(futures::future::ready(Ok(match req {
Ok(resp) => self.marshal_ok(resp),
Err(err) => self.marshal_err(err),
})))
}
}
impl<Storage> DefaultBaseDeleteResponseMarshaller<Storage>
where
Storage: SolidStorage,
{
pub fn marshal_ok(&self, _response: ResourceDeleteResponse<Storage::Repo>) -> Response<Body> {
let builder = Response::builder().status(StatusCode::NO_CONTENT);
builder
.body(Body::empty())
.expect("Must be valid hyper response.")
}
pub fn marshal_err(&self, mut error: ApiError) -> Response<Body> {
if self.marshal_config.dev_mode {
attach_authorization_context::<Storage>(&mut error);
}
error.into_hyper_response()
}
}