# crustywad

[![CI](https://github.com/masriamir/crustywad/actions/workflows/ci.yml/badge.svg)](https://github.com/masriamir/crustywad/actions/workflows/ci.yml)
[![CodeQL](https://github.com/masriamir/crustywad/actions/workflows/codeql.yml/badge.svg)](https://github.com/masriamir/crustywad/actions/workflows/codeql.yml)
[![Coverage](https://codecov.io/gh/masriamir/crustywad/graph/badge.svg)](https://codecov.io/gh/masriamir/crustywad)
[![Benchmarks](https://img.shields.io/badge/benchmarks-Criterion-informational)](https://crustywad.dev/dev/bench/)
[![dependency status](https://deps.rs/repo/github/masriamir/crustywad/status.svg)](https://deps.rs/repo/github/masriamir/crustywad)
[![docs.rs](https://img.shields.io/badge/docs.rs-pending-blue)](https://docs.rs/crustywad)
[![crates.io](https://img.shields.io/badge/crates.io-pending-inactive)](https://crates.io/crates/crustywad)
[![License](https://img.shields.io/badge/license-MIT%20OR%20Apache--2.0-blue.svg)](LICENSE-MIT)
[![MSRV](https://img.shields.io/badge/MSRV-1.85.0-blue)](https://www.rust-lang.org)

Performant, safe, typed Doom WAD file I/O in Rust.

A Doom WAD is a container format that stores a header plus a directory of named "lumps" containing maps, graphics, audio, and other game data. The [Doom Wiki](https://doomwiki.org/wiki/WAD) is a good starting point for the unofficial format specification.

**Full guide, API usage, and CLI reference: [crustywad.dev](https://crustywad.dev)**

## Status

`crustywad` provides safe, documented reading of WAD headers, lump directories, and typed map-record lumps; zero-copy memory-mapped WAD loading via the `mmap` feature; writing of WAD headers, lump directories, and raw lump data via `WadBuilder`; and a `cwad` CLI for inspecting, validating, merging, diffing, extracting, and building WAD files. Correctness and performance are validated via `cargo-fuzz` targets and Criterion benchmarks.

Integration tests for each layer live in `crates/crustywad/tests/`:
- `wad_reader.rs` — WAD header and directory parsing
- `map_records.rs` — typed map-record decoding (`Thing`, `Linedef`, `Sector`, etc.)
- `write.rs` — WAD write support (`WadBuilder`)
- `e2e.rs` — end-to-end read → modify → write → verify pipeline
- `malformed_wads.rs` — synthetic corpus of malformed and large WAD inputs
- `freedoom.rs` — optional tests against real Freedoom WAD fixtures

## Installation

```toml
[dependencies]
crustywad = "0.1"
```

Enable optional features as needed (see [Feature flags](#feature-flags) below):

```toml
[dependencies]
crustywad = { version = "0.1", features = ["write", "mmap"] }
```

## Workspace layout

- `crates/crustywad` — core library for safe WAD reading and writing.
- `crates/crustywad-cli` — `cwad`, a CLI for inspecting, validating, merging, diffing, extracting, and building WAD files.
- `docs/` — design notes, ADRs, and the [mdBook user guide](https://crustywad.dev).
- `.github/` — CI, release automation, issue templates, and repository policy files.

## Quickstart

### Library

```rust
use crustywad::Wad;

let bytes = [
    b'I', b'W', b'A', b'D',
    0, 0, 0, 0,
    12, 0, 0, 0,
];

let wad = Wad::from_bytes(bytes)?;
assert_eq!(wad.lump_count(), 0);
# Ok::<(), crustywad::ParseError>(())
```

See [Reading WAD Files](https://crustywad.dev/reading-wads.html) and [Writing WAD Files](https://crustywad.dev/writing-wads.html) in the guide for the full API, or `crates/crustywad/examples/` for runnable examples (`cargo run -p crustywad --example read_wad`).

### CLI

```text
cargo run -p crustywad-cli -- info path/to/file.wad
cargo run -p crustywad-cli -- list path/to/file.wad
```

`cwad` also has `validate`, `merge`, `diff`, `extract`, and `build` subcommands — see [CLI Usage](https://crustywad.dev/cli.html) in the guide for the full reference.

## Feature flags

| Feature | Default | Description |
| --- | --- | --- |
| `mmap` | no | Enables `Wad::from_path_mapped` and `Wad::from_path_mapped_with_options` for memory-mapped file loading via `memmap2` — no heap copy on load. `Wad::from_path` always reads into memory regardless of this flag. |
| `write` | no | Enables `WadBuilder`, `WriteError`, `WriteOptions`, `WriteWarning`, and `Wad::to_builder()` for WAD serialization. |
| `freedoom-tests` | no | Enables optional integration tests that inspect locally downloaded Freedoom fixtures. |

## Development

Install [`just`](https://github.com/casey/just) and run:

```text
just build
just test
just lint
just doc
just fetch-fixtures
just ci
```

`just cov` uses `cargo-llvm-cov`, and the Codecov upload in CI may require a `CODECOV_TOKEN` repository secret depending on repository visibility and Codecov settings.

### Freedoom fixtures

Optional integration tests parse real Freedoom WAD files. The Freedoom version to download is configurable:

```bash
# Default version (v0.13.0)
just fetch-fixtures

# Override via argument
just fetch-fixtures version=v0.14.0

# Override via environment variable
FREEDOOM_VERSION=v0.14.0 just fetch-fixtures
```

Enable the optional fixture coverage by passing `--features freedoom-tests` (or `--all-features`) **and** setting `CRUSTYWAD_FREEDOOM_DIR=tests/fixtures/freedoom` when running tests locally.

## MSRV

The minimum supported Rust version is **1.85.0**, matching the first stable release with Rust edition 2024 support.

## Roadmap

1. ✅ Directory reading
2. 🔜 Map lump parsing
3. Graphics
4. Textures
5. Audio
6. ✅ Write support

## Contributing

See [CONTRIBUTING.md](CONTRIBUTING.md) for setup, hooks, fixture handling, and release notes.

## License

Licensed under either of:

- [MIT License](LICENSE-MIT)
- [Apache License, Version 2.0](LICENSE-APACHE)

at your option.
