use std::{cell::Cell, rc::Rc};
use bytes::Bytes;
use crate::{
body::Body,
headers::{HeaderName, HeaderValue, Headers},
response::Response,
status::StatusCode,
};
#[derive(Default, Clone)]
pub struct Then(Rc<Cell<Response>>);
impl Then {
pub fn new() -> Self {
Self(Rc::new(Cell::new(Response::default())))
}
pub fn into_inner(self) -> Response {
self.0.take()
}
fn update<F: FnOnce(&mut Response)>(&self, f: F) {
let mut r = self.0.take();
f(&mut r);
self.0.set(r);
}
pub fn status(self, status: impl Into<StatusCode>) -> Self {
self.update(|r| {
r.status = status.into();
});
self
}
pub fn headers<T, U>(self, headers: impl IntoIterator<Item = (T, U)>) -> Self
where
T: Into<HeaderName>,
U: Into<HeaderValue>,
{
self.update(|r| {
r.headers = Headers::from_iter(headers);
});
self
}
pub fn body(self, body: Body) -> Self {
self.update(|r| {
r.body = body;
});
self
}
pub fn message(self, message: impl Into<String>) -> Self {
self.update(|r| {
r.message = Some(message.into());
});
self
}
}
impl Then {
pub fn empty(self) -> Self {
self.update(|r| {
r.body = Body::empty();
});
self
}
pub fn bytes(self, body: Vec<u8>) -> Self {
self.update(|r| {
r.body = Body::bytes(body);
});
self
}
pub fn bytes_stream(self, messages: impl IntoIterator<Item = impl Into<Bytes>>) -> Self {
self.update(|r| {
r.body = Body::bytes_stream(messages);
});
self
}
pub fn text(self, body: impl Into<String>) -> Self {
let body: String = body.into();
self.update(|r| {
r.body = Body::bytes(body);
});
self
}
pub fn text_stream(self, messages: impl IntoIterator<Item = impl Into<String>>) -> Self {
let messages = messages.into_iter().map(|msg| {
let msg: String = msg.into();
msg
});
self.update(|r| {
r.body = Body::bytes_stream(messages);
});
self
}
pub fn json(self, body: impl serde::Serialize) -> Self {
self.update(|r| {
r.headers.insert("content-type", "application/json");
r.body = Body::json(body);
});
self
}
pub fn json_lines_stream(
self,
messages: impl IntoIterator<Item = impl serde::Serialize>,
) -> Self {
self.update(|r| {
r.headers.insert("content-type", "application/x-ndjson");
r.body = Body::json_lines_stream(messages);
});
self
}
pub fn pb(self, body: impl prost::Message) -> Self {
self.update(|r| {
r.body = Body::pb(body);
});
self
}
pub fn pb_stream(self, messages: impl IntoIterator<Item = impl prost::Message>) -> Self {
self.update(|r| {
r.body = Body::pb_stream(messages);
});
self
}
}
impl Then {
pub fn error(self, status: StatusCode, message: impl Into<String>) -> Self {
self.update(|r| {
r.status = status;
r.message = Some(message.into());
});
self
}
pub fn ok(self) -> Self {
self.update(|r| {
r.status = StatusCode::OK;
});
self
}
pub fn bad_request(self) -> Self {
self.update(|r| {
r.status = StatusCode::BAD_REQUEST;
});
self
}
pub fn unauthorized(self) -> Self {
self.update(|r| {
r.status = StatusCode::UNAUTHORIZED;
});
self
}
pub fn forbidden(self) -> Self {
self.update(|r| {
r.status = StatusCode::FORBIDDEN;
});
self
}
pub fn not_found(self) -> Self {
self.update(|r| {
r.status = StatusCode::NOT_FOUND;
});
self
}
pub fn unsupported_media_type(self) -> Self {
self.update(|r| {
r.status = StatusCode::UNSUPPORTED_MEDIA_TYPE;
});
self
}
pub fn unprocessable_content(self) -> Self {
self.update(|r| {
r.status = StatusCode::UNPROCESSABLE_ENTITY;
});
self
}
pub fn internal_server_error(self) -> Self {
self.update(|r| {
r.status = StatusCode::INTERNAL_SERVER_ERROR;
});
self
}
pub fn not_implemented(self) -> Self {
self.update(|r| {
r.status = StatusCode::NOT_IMPLEMENTED;
});
self
}
pub fn bad_gateway(self) -> Self {
self.update(|r| {
r.status = StatusCode::BAD_GATEWAY;
});
self
}
pub fn service_unavailable(self) -> Self {
self.update(|r| {
r.status = StatusCode::SERVICE_UNAVAILABLE;
});
self
}
pub fn gateway_timeout(self) -> Self {
self.update(|r| {
r.status = StatusCode::GATEWAY_TIMEOUT;
});
self
}
}