use std::{
cell::RefCell,
collections::{BTreeMap, BinaryHeap, HashMap, HashSet, LinkedList, VecDeque},
hash::Hash,
num::{
NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroU128, NonZeroU16,
NonZeroU32, NonZeroU64, NonZeroU8,
},
sync::{
atomic::{
AtomicBool, AtomicI16, AtomicI32, AtomicI64, AtomicI8, AtomicIsize, AtomicU16,
AtomicU32, AtomicU64, AtomicU8, AtomicUsize,
},
Mutex, RwLock,
},
};
use super::{Json, Response};
use crate::error::{BoxError, ServerError};
use http::{header, response::Parts, HeaderMap, StatusCode};
use serde::{de::DeserializeOwned, Serialize};
pub trait IntoJsonResponse {
type Data: Serialize + DeserializeOwned;
fn into_json_response(self) -> crate::Result<Response<Self::Data>>;
}
impl IntoJsonResponse for () {
type Data = ();
fn into_json_response(self) -> crate::Result<Response<Self::Data>> {
Ok(make_json_response(()))
}
}
pub struct ResultResponse<T>(pub crate::Result<Response<T>>);
impl<T> IntoJsonResponse for ResultResponse<T>
where
T: Serialize + DeserializeOwned,
{
type Data = T;
fn into_json_response(self) -> crate::Result<Response<Self::Data>> {
self.0
}
}
impl<T> IntoJsonResponse for Response<T>
where
T: Serialize + DeserializeOwned,
{
type Data = T;
fn into_json_response(self) -> crate::Result<Response<Self::Data>> {
Ok(self)
}
}
impl<T> IntoJsonResponse for Json<T>
where
T: Serialize + DeserializeOwned,
{
type Data = T;
fn into_json_response(self) -> crate::Result<Response<Self::Data>> {
Ok(make_json_response(self.into_inner()))
}
}
impl<T> IntoJsonResponse for Option<T>
where
T: IntoJsonResponse,
{
type Data = T::Data;
fn into_json_response(self) -> crate::Result<Response<Self::Data>> {
match self {
Some(x) => x.into_json_response(),
None => Err(ServerError::from(StatusCode::NOT_FOUND).into()),
}
}
}
impl<T, E> IntoJsonResponse for Result<T, E>
where
T: IntoJsonResponse,
E: Into<BoxError>,
{
type Data = T::Data;
fn into_json_response(self) -> crate::Result<Response<Self::Data>> {
match self {
Ok(x) => x.into_json_response(),
Err(err) => Err(err.into()),
}
}
}
impl IntoJsonResponse for serde_json::Value {
type Data = serde_json::Value;
fn into_json_response(self) -> crate::Result<Response<Self::Data>> {
Ok(make_json_response(self))
}
}
macro_rules! impl_into_json_response {
($($ty:ty),*) => {
$(
impl IntoJsonResponse for $ty {
type Data = $ty;
fn into_json_response(self) -> crate::Result<Response<Self::Data>> {
Ok(make_json_response(self))
}
}
)*
};
}
impl_into_json_response! {
char, bool, String,
u8, u16, u32, u64, u128,
i8, i16, i32, i64, i128,
f32, f64,
AtomicBool,
AtomicI8, AtomicI16, AtomicI32, AtomicI64, AtomicIsize,
AtomicU8, AtomicU16, AtomicU32, AtomicU64, AtomicUsize,
NonZeroU8, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU128,
NonZeroI8, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI128
}
macro_rules! impl_generic_into_response {
($($ty:ty),*) => {
$(
impl<T> IntoJsonResponse for $ty
where T: Serialize + DeserializeOwned
{
type Data = $ty;
fn into_json_response(self) -> crate::Result<Response<Self::Data>> {
Ok(make_json_response(self))
}
}
)*
};
}
impl_generic_into_response! {
Vec<T>, VecDeque<T>, LinkedList<T>,
RefCell<T>, Mutex<T>, RwLock<T>
}
impl<T> IntoJsonResponse for HashSet<T>
where
T: Serialize + DeserializeOwned,
T: Eq + Hash,
{
type Data = HashSet<T>;
fn into_json_response(self) -> crate::Result<Response<Self::Data>> {
Ok(make_json_response(self))
}
}
impl<T> IntoJsonResponse for BinaryHeap<T>
where
T: Serialize + DeserializeOwned + Ord,
{
type Data = BinaryHeap<T>;
fn into_json_response(self) -> crate::Result<Response<Self::Data>> {
Ok(make_json_response(self))
}
}
impl<K, V> IntoJsonResponse for HashMap<K, V>
where
K: Serialize + DeserializeOwned + Eq + Hash,
V: Serialize + DeserializeOwned,
{
type Data = HashMap<K, V>;
fn into_json_response(self) -> crate::Result<Response<Self::Data>> {
Ok(make_json_response(self))
}
}
impl<K, V> IntoJsonResponse for BTreeMap<K, V>
where
K: Serialize + DeserializeOwned + Ord,
V: Serialize + DeserializeOwned,
{
type Data = BTreeMap<K, V>;
fn into_json_response(self) -> crate::Result<Response<Self::Data>> {
Ok(make_json_response(self))
}
}
impl<T> IntoJsonResponse for (Parts, T)
where
T: Serialize + DeserializeOwned,
{
type Data = T;
fn into_json_response(self) -> crate::Result<Response<Self::Data>> {
let (mut parts, body) = self;
parts
.headers
.insert(
header::CONTENT_TYPE,
header::HeaderValue::from_str(mime::APPLICATION_JSON.essence_str()).unwrap(),
)
.unwrap();
Ok(Response::from_parts(parts, body))
}
}
impl<T> IntoJsonResponse for (Response<()>, T)
where
T: Serialize + DeserializeOwned,
{
type Data = T;
fn into_json_response(self) -> crate::Result<Response<Self::Data>> {
let (mut res, body) = self;
res.headers_mut().insert(
header::CONTENT_TYPE,
header::HeaderValue::from_str(mime::APPLICATION_JSON.essence_str()).unwrap(),
);
Ok(res.map(|_| body))
}
}
impl<T> IntoJsonResponse for (HeaderMap, T)
where
T: Serialize + DeserializeOwned,
{
type Data = T;
fn into_json_response(self) -> crate::Result<Response<Self::Data>> {
let (mut headers, body) = self;
headers.insert(
header::CONTENT_TYPE,
header::HeaderValue::from_str(mime::APPLICATION_JSON.essence_str()).unwrap(),
);
let mut res = Response::new(body);
*res.headers_mut() = headers;
Ok(res)
}
}
#[inline]
fn make_json_response<T: Serialize + DeserializeOwned>(value: T) -> Response<T> {
Response::builder()
.header(header::CONTENT_TYPE, mime::APPLICATION_JSON.essence_str())
.body(value)
.unwrap()
}