lest 0.2.1

A modular approach to a web server. Based on actix-web.
Documentation
use either::Either;

use super::{guard::Guard, request::Request, response::{Response, Status}};
use std::{error::Error, future::Future, pin::Pin};
use crate::types::method::Method;
use libcoerced::{generic::Text, json};


/// This RequestVerify type is an alias for Either<Text, Json>.
type RequestVerify = Either<Text, json::Json>;

/// This Route struct defines a route with type checking and guards.
pub struct Route {
    pub method: Method,
    pub function: Box<dyn Fn(Request) -> Pin<Box<dyn Future<Output = Result<Response, Box<dyn Error>>>>> + 'static>,
    pub request_verify: RequestVerify,
    pub response_verify: ResponseVerificationMap,
    pub guard: Guard
}

#[allow(dead_code)]
impl Route {
    /// Create a new route without type checking or guards.
    pub fn new_basic(
        method: Method,
        function: impl Fn(Request) -> RouteResponse + 'static
    ) -> Self {
        Route {
            method,
            function: Box::new(function),
            request_verify: Either::Left(Text::Any()),
            response_verify: Box::new([]),
            guard: Guard::Any()
        }
    }

    /// Create a new route with type checking and guards.
    pub fn new(
        method: Method,
        function: impl Fn(Request) -> Pin<Box<dyn Future<Output = Result<Response, Box<dyn Error>>>>> + 'static,
        request_verify: Option<RequestVerify>,
        response_verify: Option<ResponseVerificationMap>,
        guard: Guard
    ) -> Self {
        Route {
            method,
            function: Box::new(function),
            request_verify: request_verify.unwrap_or(Either::Left(Text::Any())),
            response_verify: response_verify.unwrap_or(Box::new([])),
            guard
        }
    }
}

impl Default for Route {
    fn default() -> Self {
        Route {
            method: Method::Get,
            function: Box::new(|_| Box::pin(async { Ok(Response::new(Status::from_u16(200))) })),
            request_verify: Either::Left(Text::Any()),
            response_verify: Box::new([]),
            guard: Guard::Any()
        }
    }
}

#[allow(dead_code)]
/// This RouteResponse type is an alias for Pin<Box<dyn Future<Output = Result<Response, Box<dyn Error>>>>>.
pub type RouteResponse = Pin<Box<dyn Future<Output = Result<Response, Box<dyn Error>>>>>;

#[allow(dead_code)]
/// This ResponseVerificationMap type is an alias for Box<[(Status, RequestVerify)]>.
pub type ResponseVerificationMap = Box<[(Status, RequestVerify) ]>;