noema 0.4.0

Noema IOC and DI framework for Rust
Documentation
# Items collections (`items_collections`)

Extensible enum-like sets. You declare a **collection**, **item** types, and one compile-time **`items!` list** (same idea as `subscribe!`). `resolve::<ItemSet<C>>()` is `Arc::clone`. There is no `load`, no `ctor` registry, and no lock — values are literals.

Enable:

```toml
noema = { version = "0.3", features = ["items_collections"] }
```

Depends on `di`.

## Quick path

```rust
use std::sync::Arc;
use noema::items_collections::{collection, item, ItemSet};
use noema::{items, resolve};

#[collection(i32, name = "Steps")]
struct Steps;

#[item(Steps, value = 1, name = "one")]
struct StepOne;

#[item(Steps, value = 2, name = "two")]
struct StepTwo;

items!(Steps: [StepOne, StepTwo]);

fn main() {
    let steps = resolve::<ItemSet<Steps>>();
    let one = steps.by_name("one").unwrap();
    println!("{} = {}", one.name(), one.value());
    assert_eq!(steps.len(), 2);
    assert_eq!(steps[0].name(), "one");
}
```

Empty collection: `items!(Empty: [])`.

## `ItemSet`

| Method | |
|--------|--|
| `all()` / `iter()` / `set[i]` | Members in `items!` order |
| `len()` / `is_empty()` | Size |
| `by_name` / `by_value` | First match |
| `names()` / `values()` | Projected iterators |
| `collection_name()` | From `#[collection]` |

Building a set in tests (no macro): `ItemSet::freeze([ItemSet::member::<StepOne>(), …])`.

## Inject

```rust
#[derive(Injectable)]
struct Workflow {
    steps: Arc<ItemSet<Steps>>,
}
```

Same `Resolver` as any other singleton. Do not also `dependency!(singleton, ItemSet<Steps>)`.

## Cross-crate

`items!` MUST live in the crate that defines the `#[collection]` type (`impl ItemList for Steps` is orphan-safe only there). Item **types** in the list MAY come from dependencies of that crate.

The crate that calls `items!` must name every member. Linking another crate is not enough if its items are omitted from the list. Other crates `resolve::<ItemSet<C>>()` as a normal singleton.

## Rules

- One `items!` per collection type (duplicate `Resolver` is a compile error).
- `#[item]` on a type that is not a `#[collection]` fails to compile.
- After first `resolve`, two `Arc` clones are pointer-equal.
- `all()` / index order is the `items!` list order. Lookup by name/value returns the first match.
- No `Any`, no `TypeId`, no `inventory`.