# cocoa-archive

A small Rust library and command-line interface for generating archives for
a limited set of macOS Cocoa objects.

This project is primarily intended to provide a way to generate property list
values for use in macOS applications, especially for the pesky base64-encoded
`<data>` elements.

## Features

- Generate [`NSKeyedArchiver`](https://developer.apple.com/documentation/foundation/nskeyedarchiver)-compatible
  property list encodings of supported Cocoa objects, currently including:

  - [`NSColor`](https://developer.apple.com/documentation/appkit/nscolor)
  - [`NSFont`](https://developer.apple.com/documentation/appkit/nsfont)

- Output binary property lists, optionally base64-encoded

## Installation

### From crates.io

```sh
cargo install cocoa-archive
```

### From GitHub

```sh
cargo install --git https://github.com/kayskayskays/cocoa-archive
```

### With Nix

You can run the CLI directly:

```sh
nix run github:kayskayskays/cocoa-archive -- --help
```

Or install it into your Nix profile:

```sh
nix profile add github:kayskayskays/cocoa-archive
```

If you use NixOS or Home Manager, you will also be able to use the nixpkgs
package if/when it is available — coming soon, hopefully!

```nix
home.packages = [
  pkgs.cocoa-archive
];
```

### From Source

```sh
git clone https://github.com/kayskayskays/cocoa-archive
cd cocoa-archive
cargo build --release
```

## CLI usage

```sh
cocoa-archive --help
```

Generate an archived [`NSColor`](https://developer.apple.com/documentation/appkit/nscolor) object:

```sh
cocoa-archive color \
  --red 1.0 \
  --green 0.0 \
  --blue 0.0 \
  --alpha 1.0 \
  --format base64
```

Generate an archived [`NSFont`](https://developer.apple.com/documentation/appkit/nsfont) object:

```sh
cocoa-archive font \
  --name "Helvetica" \
  --size 12.0 \
  --format base64
```

## Library usage

```rust
use cocoa_archive::*;

let target = ArchiveTarget::Color {
    red: 1.0,
    green: 0.0,
    blue: 0.0,
    alpha: 1.0,
};

let mut writer = Vec::new();

ArchiverVariant::KeyedArchiver
    .archive(target, ArchiveFormat::Base64, &mut writer)
    .unwrap();

let base64 = String::from_utf8(writer).unwrap();

assert!(!base64.is_empty());
```

## Compatibility

This is **not** a complete implementation of [`NSKeyedArchiver`](https://developer.apple.com/documentation/foundation/nskeyedarchiver).

The archives generated by this library are intended for compatibility with macOS
applications. They are not suitable as a general-purpose replacement for the 
archives produced by Apple’s Foundation APIs.

Compatibility has been tested by:

- Decoding generated archives with Apple's [`NSKeyedUnarchiver`](https://developer.apple.com/documentation/foundation/nskeyedunarchiver). 
- Using the generated archives in Terminal.app property list configuration.

## Testing

Run the normal Rust test suite with:

```sh
cargo test
```

The repository also contains macOS-only tests that invoke a Swift helper. These 
tests call Apple's [`NSKeyedUnarchiver`](https://developer.apple.com/documentation/foundation/nskeyedunarchiver)
to decode generated archives.

These tests are not run by default because they require macOS and the Apple
developer toolchain. They can instead be run with:

```sh
cargo test macos_compatibility -- --ignored
```

CI runs the ordinary suite on Ubuntu and macOS, with the ignored compatibility
tests run on macOS only.

## Contributing

Feel free to open an issue or a pull request!

## License

MIT
