prefs 0.1.2

Type-safe macOS preferences library
# prefs

Type-safe macOS preferences library with a typed key API and optional derive macro.

## Features

- **Typed keys**`Key<T>` guarantees compile-time type safety
- **Collections** — support for `Vec<String>` (CFArray)
- **Derive macro** — declarative struct-based preferences with `#[derive(Preferences)]`
- **Zero-cost**`Key<T>` is a ZST wrapper around `&'static str`

## Installation

```toml
[dependencies]
prefs = { version = "0.1", features = ["derive"] }
```

## Usage

### Typed key API

```rust
use prefs::{Key, Preferences};

const VOLUME: Key<f64> = Key::new("volume");
const LAUNCHES: Key<i64> = Key::new("launches");
const DARK_MODE: Key<bool> = Key::new("dark_mode");

fn main() -> prefs::Result<()> {
    let prefs = Preferences::new("com.example.MyApp")?;

    let volume = prefs.get_or(VOLUME, 1.0)?;
    prefs.set(VOLUME, volume * 0.9)?;

    let launches = prefs.get_or(LAUNCHES, 0)?;
    prefs.set(LAUNCHES, launches + 1)?;

    let dark_mode = prefs.get_or(DARK_MODE, false)?;

    if prefs.contains(VOLUME)? {
        prefs.remove(VOLUME)?;
    }

    Ok(())
}
```

### Derive API

```rust
use prefs::Preferences;

#[derive(prefs::Preferences)]
#[preferences(domain = "com.example.MyApp")]
struct AppPrefs {
    #[preference(default = 1.0)]
    volume: f64,

    #[preference(default = 0)]
    launches: i64,

    #[preference(default = false)]
    dark_mode: bool,

    #[preference(name = "recent_files", default = "")]
    recent: Vec<String>,
}

fn main() -> prefs::Result<()> {
    let mut prefs = AppPrefs::load()?;

    prefs.launches += 1;
    prefs.volume = 0.8;

    prefs.save()?;

    Ok(())
}
```

### Supported types

| Rust type | CFPreferences type |
|-----------|-------------------|
| `bool` | `CFBoolean` |
| `i64` | `CFNumber` (int64) |
| `f64` | `CFNumber` (double) |
| `String` | `CFString` |
| `Vec<String>` | `CFArray` of `CFString`s |

## License

MIT