typed_use_cases 0.1.2

Formalize use cases at the type level. Zero runtime overhead. Experimental proof-of-concept.
Documentation
/// Marks a type as an actor — the initiator of a use case.
///
/// Actors exist independently of any entity or action. They represent who or what
/// is performing the use case.
///
/// # Examples
///
/// ```rust
/// use typed_use_cases::Actor;
///
/// #[derive(Actor)]
/// struct Anonymous;
///
/// #[derive(Actor)]
/// struct Authenticated {
///     user_id: u64,
/// }
/// ```
///
/// # Manual Implementation
///
/// ```rust
/// use typed_use_cases::Actor;
///
/// struct CustomActor;
/// impl Actor for CustomActor {}
/// ```
pub trait Actor {}

/// Marks a type as a domain entity — what a use case operates on.
///
/// Entities are the subject of actions in use cases. They represent the domain objects
/// that actors interact with.
///
/// # Examples
///
/// ```rust
/// use typed_use_cases::Entity;
///
/// #[derive(Entity)]
/// struct Product {
///     id: u64,
///     name: String,
/// }
///
/// #[derive(Entity)]
/// struct Cart {
///     items: Vec<u64>,
/// }
/// ```
///
/// # DependentEntity Heuristic
///
/// The `#[derive(Entity)]` macro uses a **heuristic** to optionally implement [`DependentEntity`]:
/// - If there is a field named exactly `owner`
/// - And its type is a single-segment identifier (e.g., `User`, not `crate::User`)
/// - Then it will generate `DependentEntity<FieldType>`
///
/// This is **not guaranteed** - it's a best-effort heuristic. For complex cases, implement
/// [`DependentEntity`] manually.
///
/// ```rust
/// use typed_use_cases::{Actor, Entity, DependentEntity};
///
/// #[derive(Actor)]
/// struct User { id: u64 }
///
/// #[derive(Entity)]
/// struct Cart {
///     owner: User,  // ← May implement DependentEntity<User> (heuristic)
///     items: Vec<u64>,
/// }
/// ```
pub trait Entity {}

/// A domain entity whose existence is tied to a specific actor.
///
/// Extends [`Entity`] and adds ownership semantics. This trait represents entities that
/// "belong to" a specific actor, like a shopping cart belonging to a user.
///
/// # Examples
///
/// ## Derive Heuristic (May Work)
///
/// The `#[derive(Entity)]` macro uses a heuristic - if you have a field named `owner`
/// with a simple type name, it may generate `DependentEntity` for you:
///
/// ```rust
/// use typed_use_cases::{Actor, Entity};
///
/// #[derive(Actor)]
/// struct Authenticated { user_id: u64 }
///
/// #[derive(Entity)]
/// struct Cart {
///     owner: Authenticated,  // Field named "owner" - heuristic may work
///     items: Vec<u64>,
/// }
///
/// // May implement DependentEntity<Authenticated> automatically
/// ```
///
/// **Note**: This is a best-effort heuristic. It may not work for:
/// - Complex type paths (e.g., `crate::User` instead of `User`)
/// - Generic types
/// - Types from other modules
///
/// ## Manual Implementation (Always Works)
///
/// For reliable results, implement it manually:
///
/// ```rust
/// use typed_use_cases::{Actor, Entity, DependentEntity};
///
/// struct User;
/// impl Actor for User {}
///
/// struct Order {
///     user: User,
///     items: Vec<String>,
/// }
/// impl Entity for Order {}
///
/// impl DependentEntity<User> for Order {
///     fn owner(&self) -> &User {
///         &self.user
///     }
/// }
/// ```
pub trait DependentEntity<A: Actor>: Entity {
    /// Returns a reference to the actor that owns this entity.
    fn owner(&self) -> &A;
}

/// The central trait. A UseCase IS an action.
///
/// This trait represents a use case in your system. It defines:
/// - **Who** initiates it (Actor)
/// - **What** it operates on (Entity)
/// - **What data** it needs (Input)
/// - **What** it produces (Output)
/// - **What services** it depends on (Dependencies)
///
/// # Type Parameters
///
/// * `A` - The [`Actor`] type that initiates this use case
/// * `E` - The [`Entity`] type that this use case operates on
///
/// # Associated Types
///
/// * `Input` - Additional data needed beyond actor and entity (use `()` if none)
/// * `Output` - What the use case produces
/// * `Dependencies` - External services needed (use `()` if none, or a tuple of services)
///
/// # Associated Constants
///
/// * `NAME` - Human-readable name of the use case
/// * `DESCRIPTION` - Human-readable description
///
/// # Examples
///
/// ## Simple Use Case (No Dependencies)
///
/// ```rust
/// use typed_use_cases::{Actor, Entity, UseCase};
///
/// #[derive(Actor)]
/// struct Anonymous;
///
/// #[derive(Entity)]
/// struct Catalog { products: Vec<String> }
///
/// // Define the use case trait
/// trait BrowseCatalog: UseCase<
///     Anonymous,
///     Catalog,
///     Input = (),
///     Output = Catalog,
///     Dependencies = (),
/// > {}
///
/// // Your application's System type
/// struct System;
///
/// // Implement the use case
/// impl UseCase<Anonymous, Catalog> for System {
///     const NAME: &'static str = "Browse catalog";
///     const DESCRIPTION: &'static str = "Anonymous user browses products";
///     
///     type Input = ();
///     type Output = Catalog;
///     type Dependencies = ();
///
///     fn satisfy(_actor: Anonymous, catalog: Catalog, _input: (), _deps: ()) -> Catalog {
///         catalog
///     }
/// }
///
/// impl BrowseCatalog for System {}
/// ```
///
/// ## Use Case with Dependencies
///
/// ```rust
/// use typed_use_cases::{Actor, Entity, UseCase};
///
/// #[derive(Actor)]
/// struct Authenticated { user_id: u64 }
///
/// #[derive(Entity)]
/// struct Cart { items: Vec<u64> }
///
/// // Define service traits
/// trait InventoryService {
///     fn check_availability(&self, product_id: u64) -> bool;
/// }
///
/// trait CartRepository {
///     fn save(&self, cart: &Cart) -> Result<(), String>;
/// }
///
/// // Use case with parametric dependencies
/// trait AddItemToCart: UseCase<
///     Authenticated,
///     Cart,
///     Input = u64,  // product_id
///     Output = Result<Cart, String>,
///     Dependencies = (Box<dyn InventoryService>, Box<dyn CartRepository>),
/// > {}
///
/// struct System;
///
/// impl UseCase<Authenticated, Cart> for System {
///     const NAME: &'static str = "Add item to cart";
///     const DESCRIPTION: &'static str = "User adds a product to their cart";
///     
///     type Input = u64;
///     type Output = Result<Cart, String>;
///     type Dependencies = (Box<dyn InventoryService>, Box<dyn CartRepository>);
///
///     fn satisfy(
///         _actor: Authenticated,
///         mut cart: Cart,
///         product_id: u64,
///         deps: Self::Dependencies,
///     ) -> Result<Cart, String> {
///         let (inventory, repo) = deps;
///         
///         if !inventory.check_availability(product_id) {
///             return Err("Product not available".to_string());
///         }
///         
///         cart.items.push(product_id);
///         repo.save(&cart)?;
///         
///         Ok(cart)
///     }
/// }
///
/// impl AddItemToCart for System {}
/// ```
///
/// # Important Notes
///
/// The `satisfy` method is a **compile-time contract witness**, not meant to be called
/// directly in production code. It demonstrates what the use case does conceptually and
/// ensures the type system knows about the use case structure.
pub trait UseCase<A: Actor, E: Entity> {
    /// Human-readable name of the use case.
    ///
    /// This is a compile-time constant that can be used for documentation, logging,
    /// or tooling.
    const NAME: &'static str;

    /// Human-readable description of the use case.
    ///
    /// This is a compile-time constant that describes what the use case does.
    const DESCRIPTION: &'static str;

    /// Data the use case receives as input (beyond the actor and entity).
    ///
    /// Use `()` if no additional input is needed.
    ///
    /// # Examples
    ///
    /// ```rust,ignore
    /// type Input = ();                    // No input
    /// type Input = String;                // Single input
    /// type Input = (String, u64);         // Multiple inputs
    /// ```
    type Input;

    /// What the use case produces.
    ///
    /// # Examples
    ///
    /// ```rust,ignore
    /// type Output = ();                   // No output
    /// type Output = Order;                // Single entity
    /// type Output = Result<Order, Error>; // With error handling
    /// ```
    type Output;

    /// External services or dependencies the use case needs to satisfy its contract.
    ///
    /// Use `()` if no dependencies are needed. This can be:
    /// - A concrete type
    /// - A trait object (`Box<dyn Trait>`)
    /// - A tuple of services
    ///
    /// # Examples
    ///
    /// ```rust,ignore
    /// type Dependencies = ();                          // No dependencies
    /// type Dependencies = Box<dyn Repository>;         // Single service
    /// type Dependencies = (Box<dyn A>, Box<dyn B>);    // Multiple services
    /// type Dependencies = MyServiceStruct;             // Concrete type
    /// ```
    type Dependencies;

    /// Defines how the use case satisfies its contract.
    ///
    /// This is a compile-time witness that the use case structure exists.
    /// The implementation shows what the use case does conceptually.
    ///
    /// **Important**: This is NOT meant to be called at runtime in production.
    /// It serves as a type-level contract and documentation of the use case behavior.
    fn satisfy(
        actor: A,
        entity: E,
        input: Self::Input,
        deps: Self::Dependencies,
    ) -> Self::Output;
}