auto_invalidate 0.1.1

Automatic cache invalidation on mutable access using a guard pattern
Documentation
# auto_invalidate

Automatic cache invalidation on mutable access using a guard pattern.

[![Crates.io](https://img.shields.io/crates/v/auto_invalidate.svg)](https://crates.io/crates/auto_invalidate)
[![Documentation](https://docs.rs/auto_invalidate/badge.svg)](https://docs.rs/auto_invalidate)
[![License](https://img.shields.io/crates/l/auto_invalidate.svg)](LICENSE-MIT)

## Overview

`auto_invalidate` provides a derive macro that wraps your structs with automatic cache invalidation. When you access the struct mutably through the `as_mut()` guard, all cache fields are automatically invalidated when the guard is dropped.

## Usage

```rust
use auto_invalidate::cached;
use std::cell::OnceCell;

#[cached]
struct Squarer {
    value: i32,
    #[invalidate]
    cache: OnceCell<i32>,
}

impl Squarer {
    fn new(value: i32) -> Self {
        Self::build(value)
    }

    fn square(&self) -> i32 {
        *self.cache.get_or_init(|| self.value * self.value)
    }

    fn set(&mut self, value: i32) {
        // as_mut() returns a guard that invalidates on drop
        self.as_mut().value = value;
    }
}

fn main() {
    let mut squarer = Squarer::new(4);
    
    assert_eq!(squarer.square(), 16);  // Computed and cached
    assert_eq!(squarer.square(), 16);  // Retrieved from cache
    
    squarer.set(5);                    // Cache automatically invalidated
    
    assert_eq!(squarer.square(), 25);  // Recomputed
}
```

## Features

### Invalidation Modes

- **`#[invalidate]`** or **`#[invalidate(take)]`** - Calls `.take()` on the field (works with `Option`, `OnceCell`, etc.)
- **`#[invalidate(default)]`** - Replaces the field with `Default::default()`
- **`#[invalidate(|c| expr)]`** - Custom invalidation logic

```rust
use std::cell::RefCell;
use std::collections::HashMap;

#[cached]
struct Cache {
    key: String,
    #[invalidate(|c| c.borrow_mut().clear())]
    data: RefCell<HashMap<String, i32>>,
}
```

### Multiple Cache Fields

```rust
#[cached]
struct MultiCache {
    value: i32,
    #[invalidate]
    cache1: OnceCell<i32>,
    #[invalidate]
    cache2: OnceCell<i32>,
}
```

### Generated `build()` Constructor

The macro always generates a `build()` constructor that takes non-cache fields as arguments and initializes cache fields to their defaults:

```rust
#[cached]
struct Example {
    value: i32,
    multiplier: f64,
    #[invalidate]
    cache: OnceCell<i32>,
}

// Generated: fn build(value: i32, multiplier: f64) -> Self
let e = Example::build(42, 2.0);
```

## How It Works

The `#[cached]` macro transforms your struct:

1. Renames your struct to `{Name}Inner`
2. Creates a newtype wrapper `{Name}` that holds `Cached<{Name}Inner>`
3. Implements `Deref` so you can access fields and methods transparently
4. Provides `as_mut()` which returns a guard that invalidates caches on drop

## License

Licensed under either of:

- Apache License, Version 2.0 ([LICENSE-APACHE]LICENSE-APACHE or http://www.apache.org/licenses/LICENSE-2.0)
- MIT license ([LICENSE-MIT]LICENSE-MIT or http://opensource.org/licenses/MIT)

at your option.