typed_use_cases 0.1.2

Formalize use cases at the type level. Zero runtime overhead. Experimental proof-of-concept.
Documentation
# Quick Start Guide

## Installation

Using cargo (recommended):

```bash
cargo add typed_use_cases
```

Or manually in `Cargo.toml`:

```toml
[dependencies]
typed_use_cases = "0.1"
```

## Basic Usage

### 1. Define Actors

```rust
use typed_use_cases::Actor;

#[derive(Actor)]
struct Anonymous;

#[derive(Actor)]
struct Authenticated {
    user_id: u64,
}
```

### 2. Define Entities

```rust
use typed_use_cases::Entity;

#[derive(Entity)]
struct Cart {
    owner: Authenticated,  // Automatically becomes DependentEntity<Authenticated>
    items: Vec<u64>,
}

#[derive(Entity)]
struct Catalog {
    products: Vec<Product>,
}
```

### 3. Declare Use Cases

```rust
use typed_use_cases::UseCase;

trait AddItemToCart: UseCase<
    Authenticated,       // Actor
    Cart,                // Entity
    Input = Product,     // Additional input
    Output = Result<Cart, String>,  // Output
    Dependencies = Box<dyn CartRepository>,  // Services needed
> {}
```

### 4. Create Your System Type (Application-Specific)

**Important**: The `System` type is **not** part of the library. You define it in your application:

```rust
// This is YOUR type, defined in YOUR code
struct System;  // Zero-sized!
```

### 5. Implement Use Cases on Your System

```rust
impl UseCase<Authenticated, Cart> for System {
    const NAME: &'static str = "Add item to cart";
    const DESCRIPTION: &'static str = "An authenticated user can add a product to their cart";
    
    type Input = Product;
    type Output = Result<Cart, String>;
    type Dependencies = Box<dyn CartRepository>;

    fn satisfy(
        actor: Authenticated,
        mut cart: Cart,
        product: Product,
        deps: Self::Dependencies,
    ) -> Self::Output {
        // Your implementation
        cart.items.push(product.id);
        deps.save(&cart)?;
        Ok(cart)
    }
}

impl AddItemToCart for System {}
```

### 6. Verify All Use Cases Are Implemented

```rust
typed_use_cases::implement_all_use_cases!(System: [
    AddItemToCart,
    Checkout,
    BrowseCatalog,
]);
```

This macro generates compile-time assertions that run during `cargo test`. If you forget to implement a use case, your tests won't compile.

## Using Parametric Services

The `Dependencies` type can be any type you need:

```rust
// No dependencies
type Dependencies = ();

// Single dependency
type Dependencies = Box<dyn Repository>;

// Multiple dependencies (tuple)
type Dependencies = (
    Box<dyn InventoryService>,
    Box<dyn PaymentService>,
    Box<dyn CartRepository>,
);

// Concrete types
type Dependencies = MyServiceStruct;
```

Example with parametric services:

```rust
trait CheckoutUseCase: UseCase<
    Authenticated,
    Order,
    Input = String,  // shipping address
    Output = Result<Order, String>,
    Dependencies = (Box<dyn PaymentService>, Box<dyn CartRepository>),
> {}

impl UseCase<Authenticated, Order> for System {
    // ...
    type Dependencies = (Box<dyn PaymentService>, Box<dyn CartRepository>);

    fn satisfy(
        actor: Authenticated,
        order: Order,
        address: String,
        deps: Self::Dependencies,
    ) -> Self::Output {
        let (payment_service, cart_repo) = deps;
        
        // Use the services
        payment_service.process_payment(order.total, actor.user_id)?;
        cart_repo.clear(actor.user_id)?;
        
        Ok(order)
    }
}

## API Reference

### Traits

#### `Actor`
Marks a type as an actor (the initiator of a use case).

```rust
#[derive(Actor)]
struct MyActor;
```

#### `Entity`
Marks a type as a domain entity (what a use case operates on).

```rust
#[derive(Entity)]
struct MyEntity;
```

#### `DependentEntity<A: Actor>`
An entity whose existence is tied to a specific actor.

```rust
impl DependentEntity<Authenticated> for Cart {
    fn owner(&self) -> &Authenticated {
        &self.owner
    }
}
```

The `#[derive(Entity)]` macro automatically implements this if a field named `owner` exists.

#### `UseCase<A: Actor, E: Entity>`
The central trait. A use case IS an action.

```rust
trait MyUseCase: UseCase<
    MyActor,
    MyEntity,
    Input = InputType,
    Output = OutputType,
    Dependencies = (),
> {}
```

### Macros

#### `implement_all_use_cases!`
Verifies at compile time (in test builds) that all use cases are implemented.

```rust
typed_use_cases::implement_all_use_cases!(System: [
    UseCase1,
    UseCase2,
    // ... all your use cases
]);
```

## Testing

Run tests:

```bash
cargo test
```

Run example:

```bash
cargo run --example ecommerce
cargo test --example ecommerce
```

## FAQ

**Q: What does this library actually do?**  
A: It makes your type system aware of declared use cases. When you change code structure, the compiler alerts you if those changes affect use case declarations. It does NOT verify that your implementation is correct.

**Q: Is this production-ready?**  
A: No. This is an experimental proof-of-concept. It has not been validated in production.

**Q: Does this prove my program satisfies a use case?**  
A: No. This library cannot prove that your implementation fulfills use case requirements. Testing use case fulfillment is not feasible to automate completely.

**Q: Where is System defined?**  
A: The `System` type is defined by YOU in your application code, not by this library. Each application creates its own System type.

**Q: Why is System a zero-sized type?**  
A: Zero bytes means zero runtime cost. The System type exists purely for the compiler to verify your use cases are implemented.

**Q: Can I have multiple use cases with the same actor and entity?**  
A: Each `UseCase<A, E>` implementation must be unique. Use different entity types or create wrapper types if needed.

**Q: Does this work with async/await?**  
A: The trait signature is synchronous. For async, either:
- Use the trait as a contract witness only
- Implement your async logic separately
- Or wrap the execution in an async block

**Q: What if I use a different DI framework?**  
A: No problem! `Dependencies` is a free associated type. Use `()` for no dependencies, or pass any type you want.

## Examples

See [`examples/ecommerce.rs`](examples/ecommerce.rs) for a complete working example.

## Learn More

- [README.md]README.md - Full documentation
- [VERIFICATION.md]VERIFICATION.md - Test results and verification

## License

MIT