use serde::{de::DeserializeOwned, Serialize, Serializer};
use std::{
fmt::{Debug, Display, Formatter},
ops::{Deref, DerefMut},
sync::Arc,
};
use utoipa::{
openapi::{RefOr, Schema},
ToSchema,
};
use crate::tina::{
data::AppResult,
server::{
application::{AppConfig, Application},
http::request::RequestAttribute,
session::Session,
},
};
pub struct HttpReqParam<D: DeserializeOwned> {
data: D,
application: Application,
session: Session,
}
impl<D: DeserializeOwned> RequestAttribute for HttpReqParam<D> {
fn application(&self) -> Application {
self.application.to_owned()
}
fn session(&self) -> Session {
self.session.to_owned()
}
}
impl<D: DeserializeOwned> HttpReqParam<D> {
pub fn new(data: D, application: Application, session: Session) -> HttpReqParam<D> {
HttpReqParam {
data,
application,
session,
}
}
pub fn into_inner(self) -> (D, Session) {
(self.data, self.session)
}
pub fn into_data(self) -> D {
self.data
}
pub fn extension<T: Send + Sync + 'static>(&self) -> AppResult<Arc<T>> {
self.application.extension()
}
}
impl<D: DeserializeOwned> From<HttpReqParam<D>> for (D, Session) {
fn from(value: HttpReqParam<D>) -> Self {
(value.data, value.session)
}
}
impl<D: DeserializeOwned> From<HttpReqParam<D>> for (D, Session, Application) {
fn from(value: HttpReqParam<D>) -> Self {
(value.data, value.session, value.application)
}
}
impl<D: DeserializeOwned + Default> Default for HttpReqParam<D> {
fn default() -> Self {
HttpReqParam {
data: D::default(),
application: AppConfig::new().into(),
session: Session::default(),
}
}
}
impl<'a, D: DeserializeOwned + ToSchema<'a>> ToSchema<'a> for HttpReqParam<D> {
fn schema() -> (&'a str, RefOr<Schema>) {
D::schema()
}
}
impl<D: DeserializeOwned> Deref for HttpReqParam<D> {
type Target = D;
fn deref(&self) -> &Self::Target {
&self.data
}
}
impl<D: DeserializeOwned> DerefMut for HttpReqParam<D> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.data
}
}
impl<D: DeserializeOwned + Debug> Debug for HttpReqParam<D> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
self.data.fmt(f)
}
}
impl<D: DeserializeOwned + Display> Display for HttpReqParam<D> {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
self.data.fmt(f)
}
}
impl<D: DeserializeOwned + Serialize> Serialize for HttpReqParam<D> {
fn serialize<S>(&self, serializer: S) -> Result<<S as Serializer>::Ok, <S as Serializer>::Error>
where
S: Serializer,
{
self.data.serialize(serializer)
}
}