# 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
| `bool` | `CFBoolean` |
| `i64` | `CFNumber` (int64) |
| `f64` | `CFNumber` (double) |
| `String` | `CFString` |
| `Vec<String>` | `CFArray` of `CFString`s |
## License
MIT