use crate::component::{body::Body, info::Info, request::MetaRequest, utils};
use crate::plugin::deser::*;
use crate::request::Exts;
use http::{header::HeaderName, Extensions, HeaderMap, HeaderValue, StatusCode, Version};
#[cfg(feature = "xpath")]
use libxml::{tree::Document, xpath::Context};
use std::{convert::TryFrom, fmt};
#[derive(Default)]
pub struct Response {
pub inner: InnerResponse,
pub body: Body,
pub metas: MetaResponse,
#[cfg_attr(docsrs, doc(cfg(feature = "xpath")))]
#[cfg(feature = "xpath")]
pub(crate) context: (Option<Document>, Option<Context>),
}
unsafe impl Send for Response {}
unsafe impl Sync for Response {}
#[derive(Default)]
pub struct InnerResponse {
pub status: StatusCode,
pub version: Version,
pub headers: HeaderMap<HeaderValue>,
pub extensions: Exts,
}
pub struct MetaResponse {
pub info: Info,
pub parser: *const (),
pub err_parser: Option<*const ()>,
pub body_fn: Option<*const ()>,
pub redirected: bool,
pub exts: Exts,
}
unsafe impl Send for MetaResponse {}
unsafe impl Sync for MetaResponse {}
impl Default for MetaResponse {
fn default() -> Self {
Self {
info: Info::default(),
parser: 0 as *const (),
body_fn: None,
err_parser: None,
redirected: false,
exts: Exts::default(),
}
}
}
impl fmt::Debug for MetaResponse {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut parser = "Unknow";
let mut err_parser = None;
let mut body_fn = None;
if let Some((n, _)) = serde_fn::query(None, Some(self.parser)) {
parser = n;
}
if self.err_parser.is_some() {
if let Some((n, _)) = serde_fn::query(None, self.err_parser) {
err_parser = Some(n);
}
}
if self.err_parser.is_some() {
if let Some((n, _)) = serde_fn::query(None, self.body_fn) {
body_fn = Some(n);
}
}
f.debug_struct("MetaTask")
.field("info", &self.info)
.field("parser", &parser)
.field("err_parser", &err_parser)
.field("body_fn", &body_fn)
.field("redirected", &self.redirected)
.field("exts", &self.exts)
.finish()
}
}
impl From<MetaRequest> for MetaResponse {
fn from(mut m: MetaRequest) -> Self {
m.info.created = utils::now();
MetaResponse {
info: m.info,
parser: m.parser,
err_parser: m.err_parser,
body_fn: m.body_fn,
redirected: false,
exts: m.exts,
}
}
}
#[derive(Default)]
pub struct ResponseBuilder {
pub inner: InnerResponse,
pub meta: MetaResponse,
}
impl Response {
#[inline]
pub fn builder() -> ResponseBuilder {
ResponseBuilder::new()
}
#[inline]
pub fn new<T>(body: T) -> Response
where
Body: From<T>,
{
Response {
inner: InnerResponse::default(),
body: Body::from(body),
metas: MetaResponse::default(),
#[cfg(feature = "xpath")]
context: (None, None),
}
}
#[inline]
pub fn from_parts(inner: InnerResponse, body: Body, meta: MetaResponse) -> Response {
Response {
inner,
body: body,
metas: meta,
#[cfg(feature = "xpath")]
context: (None, None),
}
}
#[inline]
pub fn status(&self) -> StatusCode {
self.inner.status
}
#[inline]
pub fn status_mut(&mut self) -> &mut StatusCode {
&mut self.inner.status
}
#[inline]
pub fn version(&self) -> Version {
self.inner.version
}
#[inline]
pub fn version_mut(&mut self) -> &mut Version {
&mut self.inner.version
}
#[inline]
pub fn headers(&self) -> &HeaderMap<HeaderValue> {
&self.inner.headers
}
#[inline]
pub fn headers_mut(&mut self) -> &mut HeaderMap<HeaderValue> {
&mut self.inner.headers
}
#[inline]
pub fn extensions(&self) -> &Extensions {
&self.inner.extensions.3
}
#[inline]
pub fn extensions_mut(&mut self) -> &mut Extensions {
&mut self.inner.extensions.3
}
#[inline]
pub fn exts(&self) -> &Extensions {
&self.metas.exts.3
}
#[inline]
pub fn exts_mut(&mut self) -> &mut Extensions {
&mut self.metas.exts.3
}
#[inline]
pub fn body(&self) -> &Body {
&self.body
}
#[inline]
pub fn body_mut(&mut self) -> &mut Body {
&mut self.body
}
#[inline]
pub fn into_body(self) -> Body {
self.body
}
#[inline]
pub fn into_parts(self) -> (InnerResponse, Body, MetaResponse) {
(self.inner, self.body, self.metas)
}
#[inline]
pub fn map<F>(self, f: F) -> Response
where
F: FnOnce(Body) -> Body,
{
Response {
body: f(self.body),
inner: self.inner,
metas: self.metas,
#[cfg(feature = "xpath")]
context: self.context,
}
}
}
impl ResponseBuilder {
#[inline]
pub fn new() -> ResponseBuilder {
ResponseBuilder::default()
}
pub fn status<T>(mut self, status: T) -> ResponseBuilder
where
StatusCode: TryFrom<T>,
<StatusCode as TryFrom<T>>::Error: Into<http::Error>,
{
self.inner.status = TryFrom::try_from(status).map_err(Into::into).unwrap();
self
}
pub fn version(mut self, version: Version) -> ResponseBuilder {
self.inner.version = version;
self
}
pub fn header<K, V>(mut self, key: K, value: V) -> ResponseBuilder
where
HeaderName: TryFrom<K>,
<HeaderName as TryFrom<K>>::Error: Into<http::Error>,
HeaderValue: TryFrom<V>,
<HeaderValue as TryFrom<V>>::Error: Into<http::Error>,
{
let name = <HeaderName as TryFrom<K>>::try_from(key)
.map_err(Into::into)
.unwrap();
let value = <HeaderValue as TryFrom<V>>::try_from(value)
.map_err(Into::into)
.unwrap();
self.inner.headers.append(name, value);
self
}
pub fn headers_ref(&self) -> &HeaderMap<HeaderValue> {
&self.inner.headers
}
pub fn headers_mut(&mut self) -> &mut HeaderMap<HeaderValue> {
&mut self.inner.headers
}
pub fn extension<S>(mut self, extension: S) -> ResponseBuilder
where
S: std::any::Any + Send + Sync + 'static,
{
self.inner.extensions.3.insert(extension);
self
}
pub fn extensions_ref(&self) -> &Extensions {
&self.inner.extensions.3
}
pub fn extensions_mut(&mut self) -> &mut Extensions {
&mut self.inner.extensions.3
}
#[inline]
pub fn exts<S>(mut self, extension: S) -> Self
where
S: std::any::Any + Send + Sync + 'static,
{
self.meta.exts.3.insert(extension);
self
}
#[inline]
pub fn exts_mut(&mut self) -> &mut Extensions {
&mut self.meta.exts.3
}
pub fn exts_ref(&self) -> &Extensions {
&self.meta.exts.3
}
pub fn body<T>(self, body: T) -> Response
where
Body: From<T>,
{
Response {
inner: self.inner,
body: Body::from(body),
metas: self.meta,
#[cfg(feature = "xpath")]
context: (None, None),
}
}
}