use core::fmt::Debug;
use crate::io::{Error, Read, Write};
pub use super::{Headers, Method, Query, Status};
pub use crate::io::ErrorType;
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Request<C>(C);
impl<C> Request<C>
where
C: Connection,
{
pub fn wrap(connection: C) -> Request<C> {
if connection.is_response_initiated() {
panic!("connection is not in request phase");
}
Request(connection)
}
pub fn split(&mut self) -> (&C::Headers, &mut C::Read) {
self.0.split()
}
pub fn into_response<'b>(
mut self,
status: u16,
message: Option<&'b str>,
headers: &'b [(&'b str, &'b str)],
) -> Result<Response<C>, C::Error> {
self.0.initiate_response(status, message, headers)?;
Ok(Response(self.0))
}
pub fn into_status_response(self, status: u16) -> Result<Response<C>, C::Error> {
self.into_response(status, None, &[])
}
pub fn into_ok_response(self) -> Result<Response<C>, C::Error> {
self.into_response(200, Some("OK"), &[])
}
pub fn connection(&mut self) -> &mut C {
&mut self.0
}
pub fn release(self) -> C {
self.0
}
pub fn uri(&self) -> &'_ str {
self.0.uri()
}
pub fn method(&self) -> Method {
self.0.method()
}
pub fn header(&self, name: &str) -> Option<&'_ str> {
self.0.header(name)
}
pub fn read(&mut self, buf: &mut [u8]) -> Result<usize, C::Error> {
self.0.read(buf)
}
}
impl<C> ErrorType for Request<C>
where
C: ErrorType,
{
type Error = C::Error;
}
impl<C> Read for Request<C>
where
C: Connection,
{
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
Request::read(self, buf)
}
}
impl<C> Headers for Request<C>
where
C: Connection,
{
fn header(&self, name: &str) -> Option<&'_ str> {
Request::header(self, name)
}
}
impl<C> Query for Request<C>
where
C: Connection,
{
fn uri(&self) -> &'_ str {
Request::uri(self)
}
fn method(&self) -> Method {
Request::method(self)
}
}
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Response<C>(C);
impl<C> Response<C>
where
C: Connection,
{
pub fn wrap(connection: C) -> Response<C> {
if !connection.is_response_initiated() {
panic!("connection is not in response phase");
}
Response(connection)
}
pub fn connection(&mut self) -> &mut C {
&mut self.0
}
pub fn release(self) -> C {
self.0
}
pub fn write(&mut self, buf: &[u8]) -> Result<usize, C::Error> {
self.0.write(buf)
}
pub fn flush(&mut self) -> Result<(), C::Error> {
self.0.flush()
}
}
impl<C> ErrorType for Response<C>
where
C: ErrorType,
{
type Error = C::Error;
}
impl<C> Write for Response<C>
where
C: Connection,
{
fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
Response::write(self, buf)
}
fn flush(&mut self) -> Result<(), Self::Error> {
Response::flush(self)
}
}
pub trait Connection: Query + Headers + Read + Write {
type Headers: Query + Headers;
type Read: Read<Error = Self::Error>;
type RawConnectionError: Error;
type RawConnection: Read<Error = Self::RawConnectionError>
+ Write<Error = Self::RawConnectionError>;
fn split(&mut self) -> (&Self::Headers, &mut Self::Read);
fn initiate_response<'a>(
&'a mut self,
status: u16,
message: Option<&'a str>,
headers: &'a [(&'a str, &'a str)],
) -> Result<(), Self::Error>;
fn is_response_initiated(&self) -> bool;
fn raw_connection(&mut self) -> Result<&mut Self::RawConnection, Self::Error>;
}
impl<C> Connection for &mut C
where
C: Connection,
{
type Headers = C::Headers;
type Read = C::Read;
type RawConnectionError = C::RawConnectionError;
type RawConnection = C::RawConnection;
fn split(&mut self) -> (&Self::Headers, &mut Self::Read) {
(*self).split()
}
fn initiate_response<'a>(
&'a mut self,
status: u16,
message: Option<&'a str>,
headers: &'a [(&'a str, &'a str)],
) -> Result<(), Self::Error> {
(*self).initiate_response(status, message, headers)
}
fn is_response_initiated(&self) -> bool {
(**self).is_response_initiated()
}
fn raw_connection(&mut self) -> Result<&mut Self::RawConnection, Self::Error> {
(*self).raw_connection()
}
}
pub trait Handler<C>: Send
where
C: Connection,
{
type Error: Debug;
fn handle(&self, connection: &mut C) -> Result<(), Self::Error>;
}
impl<C, H> Handler<C> for &H
where
C: Connection,
H: Handler<C> + Send + Sync,
{
type Error = H::Error;
fn handle(&self, connection: &mut C) -> Result<(), Self::Error> {
(*self).handle(connection)
}
}
pub struct FnHandler<F>(F);
impl<F> FnHandler<F> {
pub const fn new<C, E>(f: F) -> Self
where
C: Connection,
F: Fn(Request<&mut C>) -> Result<(), E> + Send,
E: Debug,
{
Self(f)
}
}
impl<C, F, E> Handler<C> for FnHandler<F>
where
C: Connection,
F: Fn(Request<&mut C>) -> Result<(), E> + Send,
E: Debug,
{
type Error = E;
fn handle(&self, connection: &mut C) -> Result<(), Self::Error> {
self.0(Request::wrap(connection))
}
}
pub trait Middleware<C, H>: Send
where
C: Connection,
H: Handler<C>,
{
type Error: Debug;
fn handle(&self, connection: &mut C, handler: &H) -> Result<(), Self::Error>;
fn compose(self, handler: H) -> CompositeHandler<Self, H>
where
Self: Sized,
{
CompositeHandler::new(self, handler)
}
}
pub struct CompositeHandler<M, H> {
middleware: M,
handler: H,
}
impl<M, H> CompositeHandler<M, H> {
pub fn new(middleware: M, handler: H) -> Self {
Self {
middleware,
handler,
}
}
}
impl<M, H, C> Handler<C> for CompositeHandler<M, H>
where
M: Middleware<C, H>,
H: Handler<C>,
C: Connection,
{
type Error = M::Error;
fn handle(&self, connection: &mut C) -> Result<(), Self::Error> {
self.middleware.handle(connection, &self.handler)
}
}
pub mod asynch {
use core::fmt::Debug;
use crate::io::{asynch::Read, asynch::Write};
pub use super::{Headers, Method, Query, Status};
pub use crate::io::{Error, ErrorType};
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Request<C>(C);
impl<C> Request<C>
where
C: Connection,
{
pub fn wrap(connection: C) -> Request<C> {
if connection.is_response_initiated() {
panic!("connection is not in request phase");
}
Request(connection)
}
pub fn split(&mut self) -> (&C::Headers, &mut C::Read) {
self.0.split()
}
pub async fn into_response<'b>(
mut self,
status: u16,
message: Option<&'b str>,
headers: &'b [(&'b str, &'b str)],
) -> Result<Response<C>, C::Error> {
self.0.initiate_response(status, message, headers).await?;
Ok(Response(self.0))
}
pub async fn into_status_response(self, status: u16) -> Result<Response<C>, C::Error> {
self.into_response(status, None, &[]).await
}
pub async fn into_ok_response(self) -> Result<Response<C>, C::Error> {
self.into_response(200, Some("OK"), &[]).await
}
pub fn connection(&mut self) -> &mut C {
&mut self.0
}
pub fn release(self) -> C {
self.0
}
pub fn uri(&self) -> &'_ str {
self.0.uri()
}
pub fn method(&self) -> Method {
self.0.method()
}
pub fn header(&self, name: &str) -> Option<&'_ str> {
self.0.header(name)
}
pub async fn read(&mut self, buf: &mut [u8]) -> Result<usize, C::Error> {
self.0.read(buf).await
}
}
impl<C> ErrorType for Request<C>
where
C: ErrorType,
{
type Error = C::Error;
}
impl<C> Read for Request<C>
where
C: Connection,
{
async fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
Request::read(self, buf).await
}
}
impl<C> Query for Request<C>
where
C: Connection,
{
fn uri(&self) -> &'_ str {
Request::uri(self)
}
fn method(&self) -> Method {
Request::method(self)
}
}
impl<C> Headers for Request<C>
where
C: Connection,
{
fn header(&self, name: &str) -> Option<&'_ str> {
Request::header(self, name)
}
}
#[derive(Debug)]
#[cfg_attr(feature = "defmt", derive(defmt::Format))]
pub struct Response<C>(C);
impl<C> Response<C>
where
C: Connection,
{
pub fn wrap(connection: C) -> Response<C> {
if !connection.is_response_initiated() {
panic!("connection is not in response phase");
}
Response(connection)
}
pub fn connection(&mut self) -> &mut C {
&mut self.0
}
pub fn release(self) -> C {
self.0
}
pub async fn write(&mut self, buf: &[u8]) -> Result<usize, C::Error> {
self.0.write(buf).await
}
pub async fn flush(&mut self) -> Result<(), C::Error> {
self.0.flush().await
}
}
impl<C> ErrorType for Response<C>
where
C: ErrorType,
{
type Error = C::Error;
}
impl<C> Write for Response<C>
where
C: Connection,
{
async fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
Response::write(self, buf).await
}
async fn flush(&mut self) -> Result<(), Self::Error> {
Response::flush(self).await
}
}
pub trait Connection: Query + Headers + Read + Write {
type Headers: Query + Headers;
type Read: Read<Error = Self::Error>;
type RawConnectionError: Error;
type RawConnection: Read<Error = Self::RawConnectionError>
+ Write<Error = Self::RawConnectionError>;
fn split(&mut self) -> (&Self::Headers, &mut Self::Read);
async fn initiate_response(
&mut self,
status: u16,
message: Option<&str>,
headers: &[(&str, &str)],
) -> Result<(), Self::Error>;
fn is_response_initiated(&self) -> bool;
fn raw_connection(&mut self) -> Result<&mut Self::RawConnection, Self::Error>;
}
impl<C> Connection for &mut C
where
C: Connection,
{
type Headers = C::Headers;
type Read = C::Read;
type RawConnectionError = C::RawConnectionError;
type RawConnection = C::RawConnection;
fn split(&mut self) -> (&Self::Headers, &mut Self::Read) {
(*self).split()
}
async fn initiate_response(
&mut self,
status: u16,
message: Option<&str>,
headers: &[(&str, &str)],
) -> Result<(), Self::Error> {
(*self).initiate_response(status, message, headers).await
}
fn is_response_initiated(&self) -> bool {
(**self).is_response_initiated()
}
fn raw_connection(&mut self) -> Result<&mut Self::RawConnection, Self::Error> {
(*self).raw_connection()
}
}
pub trait Handler<C>: Send
where
C: Connection,
{
type Error: Debug;
async fn handle(&self, connection: &mut C) -> Result<(), Self::Error>;
}
impl<H, C> Handler<C> for &H
where
C: Connection,
H: Handler<C> + Send + Sync,
{
type Error = H::Error;
async fn handle(&self, connection: &mut C) -> Result<(), Self::Error> {
(*self).handle(connection).await
}
}
pub trait Middleware<C, H>: Send
where
C: Connection,
H: Handler<C>,
{
type Error: Debug;
async fn handle(&self, connection: &mut C, handler: &H) -> Result<(), Self::Error>;
fn compose(self, handler: H) -> CompositeHandler<Self, H>
where
Self: Sized,
{
CompositeHandler::new(self, handler)
}
}
pub struct CompositeHandler<M, H> {
middleware: M,
handler: H,
}
impl<M, H> CompositeHandler<M, H> {
pub fn new(middleware: M, handler: H) -> Self {
Self {
middleware,
handler,
}
}
}
impl<M, H, C> Handler<C> for CompositeHandler<M, H>
where
M: Middleware<C, H>,
H: Handler<C>,
C: Connection,
{
type Error = M::Error;
async fn handle(&self, connection: &mut C) -> Result<(), Self::Error> {
self.middleware.handle(connection, &self.handler).await
}
}
}