rust-api 0.0.2

FastAPI-inspired REST framework for Rust with route macros, dependency injection, and automatic OpenAPI generation
Documentation
//! Controller trait — pure descriptor for composable route groups.
//!
//! A `Controller` is a zero-knowledge marker type. It knows only two things:
//!   1. `type State` — the service it needs (`Arc<State>` is resolved and
//!      passed in)
//!   2. `fn mount` — a Kleisli arrow `Arc<State> -> (Router -> Result<Router>)`
//!
//! Controllers have **no dependency on `Router`, `RouteSet`, or any DI
//! container**. The `mount_handlers!` macro generates the `mount`
//! implementation from a simple list of `(route_constant, handler_fn)` pairs.
//! Users only write handlers.
//!
//! # Kleisli Composition
//!
//! `mount` returns `impl FnOnce(Router<()>) -> Result<Router<()>>` — a Kleisli
//! arrow in the `Result` monad. The `RouterPipeline` composes these arrows with
//! `and_then` (`>>=`), threading the router through each controller in
//! sequence. A failed arrow short-circuits the rest.
//!
//! # Immutability Contract
//!
//! State is passed as `Arc<S>` — shared, immutable after construction. Services
//! must not expose `&mut self` methods. All state mutation goes through
//! `Atomic*` primitives or channels (never `Mutex<T>` on the service struct).
//!
//! # Example
//!
//! ```ignore
//! pub struct HealthController;
//!
//! #[get("/health")]
//! pub async fn health_check(State(svc): State<Arc<HealthService>>) -> Json<HealthResponse> {
//!     Json(svc.health_check())
//! }
//!
//! // mount_handlers! generates the full Controller impl — user never writes Router.
//! mount_handlers!(HealthController, HealthService, [
//!     (__health_check_route, health_check),
//! ]);
//! ```

use std::sync::Arc;

use crate::{error::Result, router::Router};

/// A pure descriptor for a group of HTTP routes sharing a common service
/// dependency.
///
/// Do not implement this trait manually. Use the [`mount_handlers!`] macro,
/// which generates the correct Kleisli arrow from your handler list.
///
/// The trait's only concern is: given `Arc<State>`, produce a Kleisli arrow
/// that registers this controller's routes into a `Router<()>`.
pub trait Controller: Sized + 'static {
    /// The service this controller depends on.
    ///
    /// The framework wraps it in `Arc<State>` — `Clone` is not required on the
    /// service itself. Use `Atomic*` primitives or channels for any state that
    /// changes after construction.
    type State: Send + Sync + 'static;

    /// Returns the Kleisli arrow for this controller.
    ///
    /// Signature: `Arc<State> -> (Router<()> -> Result<Router<()>>)`
    ///
    /// Generated by `mount_handlers!`. The returned closure:
    ///   1. Builds a scoped `Router<Arc<State>>` with this controller's routes.
    ///   2. Provides state via `.with_state(state)` → `Router<()>`.
    ///   3. Merges into the outer `router` and returns `Ok(merged)`.
    fn mount(state: Arc<Self::State>) -> impl FnOnce(Router<()>) -> Result<Router<()>>;
}