use std::ops::{Deref, DerefMut};
use hyper::body::Incoming;
use serde::de::DeserializeOwned;
use crate::{
Extract,
extract::{Path, PathError, Query, QueryError},
};
pub struct Request<B = Incoming>(http::Request<B>);
impl<B> Request<B> {
pub fn extract<E>(&self) -> Result<E, E::Error>
where
E: Extract,
{
E::extract(self)
}
pub fn path<T>(&self) -> Result<T, PathError>
where
T: DeserializeOwned,
{
let Path(path) = Path::extract(self)?;
Ok(path)
}
pub fn query<T>(&self) -> Result<T, QueryError>
where
T: DeserializeOwned,
{
let Query(query) = Query::extract(self)?;
Ok(query)
}
pub async fn body<T>(self) -> Result<T::Output, T::Error>
where
T: FromRequest<B>,
{
T::from_request(self).await
}
pub fn into_inner(self) -> http::Request<B> {
self.0
}
}
impl<B> From<http::Request<B>> for Request<B> {
fn from(value: http::Request<B>) -> Self {
Request(value)
}
}
impl<B> Deref for Request<B> {
type Target = http::Request<B>;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl<B> DerefMut for Request<B> {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
pub trait FromRequest<B = Incoming>: Sized {
type Error;
type Output;
async fn from_request(request: Request<B>) -> Result<Self::Output, Self::Error>;
}
impl<B> FromRequest<B> for Request<B> {
type Error = ();
type Output = Self;
async fn from_request(request: Request<B>) -> Result<Self, Self::Error> {
Ok(request)
}
}