Skip to main content

nwnrs_key/
lib.rs

1#![forbid(unsafe_code)]
2#![doc = "# nwnrs-key\n\n`nwnrs-key` reads and writes KEY/BIF resource sets, which form the canonical\nindexed storage layout for base-game content.\n\n## Scope\n\n- parse KEY files and their BIF index tables\n- expose the result as a typed [`KeyTable`]\n- implement `nwnrs-resman` container behavior for KEY/BIF-backed content\n- write KEY/BIF output from typed archive state\n\nThe main entry points are [`read_key_table`], [`read_key_table_from_file`], and\n[`write_key_and_bif`].\n\n## Public Surface\n\n- `KeyTable`\n- `KeyBifEntry`\n- `KeyBifContents`\n- `KeyBifVersion`\n- `VariableResource`\n- `BifResolver`\n- `ResId`\n- `KeyError`\n- `KeyResult`\n- `read_key_table`\n- `read_key_table_from_file`\n- `write_key_and_bif`\n- `write_key_table_archive`\n\n## Core Model\n\n- `ResId` is a packed `u32`\n  - upper bits identify the owning BIF\n  - lower bits identify the variable resource within that BIF\n- `KeyTable` preserves:\n  - version\n  - label\n  - build year and day\n  - BIF handles\n  - resource-to-id lookup\n  - optional OID metadata\n- `VariableResource` preserves:\n  - packed id\n  - I/O offset\n  - stored size\n  - compression type\n  - uncompressed size\n\n## KEY Layout\n\nHeader size: `64` bytes.\n\nKnown KEY versions:\n\n- `V1`\n- `E1`\n\nHeader shape:\n\n```text\n0x00  \"KEY \"\n0x04  version\n0x08  bif_count              u32\n0x0C  key_count              u32\n0x10  offset_to_file_table   u32\n0x14  offset_to_key_table    u32\n0x18  build_year             u32\n0x1C  build_day              u32\n0x20  remaining header / OID area\n```\n\nBody:\n\n```text\n+----------------------+\n| KEY header           |\n+----------------------+\n| file table           | one row per BIF\n+----------------------+\n| filename strings     |\n+----------------------+\n| key table            | one row per resource\n+----------------------+\n```\n\n## BIF Layout\n\nKnown BIF magic:\n\n- `\"BIFF\"`\n\nKnown BIF versions:\n\n- `V1`\n- `E1`\n\nConceptually:\n\n```text\n+----------------------+\n| BIF header           |\n+----------------------+\n| variable table       |\n+----------------------+\n| payload 0            |\n+----------------------+\n| payload 1            |\n+----------------------+\n| ...                  |\n+----------------------+\n```\n\nEach variable-resource row records:\n\n- packed resource id\n- byte offset\n- stored size\n- resource type\n- optional `E1` compression metadata\n\n## Invariants\n\n- resource references remain typed rather than stringly indexed\n- the mapping from KEY entries to BIF-backed payload locations remains explicit\n- the same typed value may be inspected structurally and used as a\n  `ResContainer`\n- KEY indexing and BIF payload storage are separate concepts\n- `BifResolver` exists because the KEY file references BIFs by filename and the\n  actual stream-opening policy belongs to the caller\n\n## See also\n\n- [`nwnrs-resman`](https://docs.rs/nwnrs-resman), which consumes `KeyTable` as a\n  resource container\n- [`nwnrs-install`](https://docs.rs/nwnrs-install), which uses KEY/BIF data to\n  assemble a conventional install-backed resource stack\n\n## Why This Crate Exists\n\nIf you only think in terms of \"resource name to bytes,\" the KEY/BIF design\nlooks more complicated than it needs to be. If you think in terms of indexed\narchival storage, it becomes clear:\n\n- KEY is the index\n- BIF is the payload store\n- `ResId` is the join key\n\nThe crate makes that split explicit rather than hiding it behind opaque lookup\nmachinery.\n"include_str!("../README.md")]
3
4mod io;
5mod types;
6
7pub use io::*;
8pub use types::*;
9
10/// Common imports for consumers of this crate.
11pub mod prelude {
12    pub use crate::{
13        BifResolver, KeyBifContents, KeyBifEntry, KeyBifVersion, KeyError, KeyResult, KeyTable,
14        ResId, VariableResource, read_key_table, read_key_table_from_file, write_key_and_bif,
15        write_key_table_archive,
16    };
17}