restify-openapi 0.0.1

STILL WIP
Documentation
use std::convert::Infallible;

use axum::{
  extract::Request,
  handler::Handler,
  response::IntoResponse,
  routing::{self, Route},
};
use tower_layer::Layer;
use tower_service::Service;

use crate::{
  paths::{Operation, OperationType, PathItem},
  Components, DefinitionHolder, PathItemDefinition,
};

use super::MethodFilter;

pub const AXUM_METHODS: &'static [(MethodFilter, OperationType)] = &[
  (MethodFilter::GET, OperationType::Get),
  (MethodFilter::DELETE, OperationType::Delete),
  (MethodFilter::HEAD, OperationType::Head),
  (MethodFilter::OPTIONS, OperationType::Options),
  (MethodFilter::PATCH, OperationType::Patch),
  (MethodFilter::POST, OperationType::Post),
  (MethodFilter::PUT, OperationType::Put),
  (MethodFilter::TRACE, OperationType::Trace),
];

pub fn on<H, T, S>(filter: MethodFilter, handler: H) -> MethodRouter<S, Infallible>
where
  H: Handler<T, S>,
  H::Future: PathItemDefinition,
  T: 'static,
  S: Clone + Send + Sync + 'static,
{
  MethodRouter::new().on(filter, handler)
}

pub struct MethodRouter<S = (), E = Infallible> {
  pub(crate) inner: routing::MethodRouter<S, E>,
  pub(crate) def: PathItem,
  pub(crate) components: Vec<Components>,
}

pub struct RouteWrapper<S, E = Infallible> {
  path: String,
  method: MethodRouter<S, E>
}

impl<S> MethodRouter<S, Infallible>
where
  S: Clone,
{
  #[track_caller]
  pub fn on<H, T>(mut self, filter: MethodFilter, handler: H) -> Self
  where
    H: Handler<T, S>,
    H::Future: PathItemDefinition,
    T: 'static,
    S: Send + Sync + 'static,
  {
    if H::Future::is_visible() {}

    self.inner = self.inner.on(filter.clone().into(), handler);

    self.components.extend(H::Future::components());

    let operation: Operation = H::Future::operation();

    for (method, op) in AXUM_METHODS {
      if filter.contains(*method) {
        self.def.operations.insert(op.clone(), operation.clone());
      }
    }

    self
  }
}

impl<S, E> MethodRouter<S, E>
where
  S: Clone,
{
  pub fn new() -> Self {
    Self {
      inner: routing::MethodRouter::new(),
      def: Default::default(),
      components: Default::default(),
    }
  }

  pub fn with_state<S2>(self, state: S) -> MethodRouter<S2, E> {
    MethodRouter {
      inner: self.inner.with_state(state),
      components: self.components,
      def: self.def,
    }
  }

  #[track_caller]
  pub fn on_service<T>(mut self, filter: MethodFilter, svc: T) -> Self
  where
    T: Service<Request, Error = E> + Clone + Send + 'static,
    T::Response: IntoResponse + 'static,
    T::Future: Send + 'static,
  {
    self.inner = self.inner.on_service(filter.into(), svc);

    self
  }

  pub fn layer<L, NewError>(self, layer: L) -> MethodRouter<S, NewError>
  where
    L: Layer<Route<E>> + Clone + Send + 'static,
    L::Service: Service<Request> + Clone + Send + 'static,
    <L::Service as Service<Request>>::Response: IntoResponse + 'static,
    <L::Service as Service<Request>>::Error: Into<NewError> + 'static,
    <L::Service as Service<Request>>::Future: Send + 'static,
    E: 'static,
    S: 'static,
    NewError: 'static,
  {
    MethodRouter {
      inner: self.inner.layer(layer),
      components: self.components,
      def: self.def,
    }
  }

  #[track_caller]
  pub fn route_layer<L>(self, layer: L) -> MethodRouter<S, E>
  where
    L: Layer<Route<E>> + Clone + Send + 'static,
    L::Service: Service<Request, Error = E> + Clone + Send + 'static,
    <L::Service as Service<Request>>::Response: IntoResponse + 'static,
    <L::Service as Service<Request>>::Future: Send + 'static,
    E: 'static,
    S: 'static,
  {
    MethodRouter {
      inner: self.inner.route_layer(layer),
      components: self.components,
      def: self.def,
    }
  }

  #[track_caller]
  pub fn merge(mut self, other: MethodRouter<S, E>) -> Self {
    self.inner = self.inner.merge(other.inner);

    self.components.extend(other.components);

    self.def.parameters.extend(other.def.parameters);
    self.def.operations.extend(other.def.operations);

    self
  }
}


impl<S, E> DefinitionHolder for RouteWrapper<S, E>
where
  S: Clone,
{
    fn path(&self) -> &str {
        &self.path
    }

    fn operations(&mut self) -> indexmap::IndexMap<OperationType, Operation> {
        todo!()
    }

    fn components(&mut self) -> Vec<Components> {
        todo!()
    }
}