Skip to main content

Crate nwnrs_gff

Crate nwnrs_gff 

Source
Expand description

§nwnrs-gff

nwnrs-gff reads and writes GFF V3.2, the structured container format underlying a large portion of NWN gameplay data.

§Scope

  • parse typed GFF roots, structures, fields, and values
  • preserve authored field order so stable editing remains possible
  • write typed GFF documents back to binary form
  • provide a compact typed vocabulary on which higher-level crates can build

The principal entry points are read_gff_root, write_gff_root, and GffRoot.

§Example

use std::io::Cursor;

use nwnrs_gff::{GffRoot, GffValue, read_gff_root, write_gff_root};

let mut root = GffRoot::new("UTC ");
root.put_value("Tag", GffValue::CExoString("nw_chicken".to_string()))?;

let mut bytes = Cursor::new(Vec::new());
write_gff_root(&mut bytes, &root)?;
bytes.set_position(0);

let decoded = read_gff_root(&mut bytes)?;
assert_eq!(decoded.file_type, "UTC ");
assert_eq!(decoded.fields().len(), 1);

§Public Surface

  • GffRoot
  • GffStruct
  • GffField
  • GffFieldKind
  • GffValue
  • GffCExoLocString
  • GffError
  • GffResult
  • read_gff_root
  • write_gff_root
  • merge_root_preserving_provenance

§Core Model

  • GffRoot carries the outer file tag, version, root struct, and optional source provenance
  • GffStruct is an ordered labeled field map keyed by unique labels
  • GffField separates field metadata from GffValue
  • GffValue does not collapse field kinds into one lossy generic scalar type
  • GffCExoLocString preserves both the top-level str_ref and the explicit localized override entries

§Binary Layout

The crate models GFF V3.2.

0x00  file_type[4]          e.g. "UTC ", "ARE ", "GIT "
0x04  file_version[4]       "V3.2"
0x08  struct_offset         u32
0x0C  struct_count          u32
0x10  field_offset          u32
0x14  field_count           u32
0x18  label_offset          u32
0x1C  label_count           u32
0x20  field_data_offset     u32
0x24  field_data_size       u32
0x28  field_indices_offset  u32
0x2C  field_indices_size    u32
0x30  list_indices_offset   u32
0x34  list_indices_size     u32

total header size: 56 bytes

After the header:

+----------------------+
| struct table         | struct_count * 12
+----------------------+
| field table          | field_count * 12
+----------------------+
| label table          | label_count * 16
+----------------------+
| field data blob      | variable
+----------------------+
| field index array    | i32[]
+----------------------+
| list index array     | i32[]
+----------------------+

Struct table entry:

i32 id
i32 data_or_offset
i32 field_count

Field table entry:

u32 field_kind
i32 label_index
i32 data_or_offset

Important indirections:

  • if a struct has field_count == 0, it has no fields
  • if a struct has field_count == 1, data_or_offset is the direct field index
  • if a struct has field_count > 1, data_or_offset is a byte offset into the field-index array
  • list fields point into the list-index array
  • complex field kinds point into the field-data blob

§Field-Kind Semantics

Inline 32-bit payloads:

  • Byte
  • Char
  • Word
  • Short
  • Dword
  • Int
  • Float

Out-of-line payloads in the field-data blob:

  • Dword64
  • Int64
  • Double
  • CExoString
  • ResRef
  • CExoLocString
  • Void

Recursive payloads:

  • Struct
  • List

The practical point is that “GFF value” is not one uniform storage class. Reconstruction requires honoring the original split between inline scalars, out-of-line payloads, and recursive references.

§Invariants

  • the order of fields inside each GffStruct is preserved explicitly
  • the root file_type and file_version remain first-class typed fields
  • each GffValue retains its declared GFF field kind
  • writes are derived from the typed representation rather than from an unstructured map
  • labels must be unique within a struct
  • complex fields preserve raw payload bytes when that is needed for stable rewrites
  • merge_root_preserving_provenance exists because naive merge logic tends to destroy stable ordering and untouched raw structure

§See also

  • nwnrs-git, which layers typed area-instance semantics over raw GFF data
  • nwnrs-erf, which often carries GFF payloads in NWN archives

§Why This Crate Exists

GFF is one of the places where reverse engineering turns into systems design. The difficult part is not only learning the table layout. It is deciding which properties are structural enough to model:

  • order
  • typed field kind
  • label identity
  • recursive structure
  • raw payload fidelity

This crate chooses to preserve all of those explicitly so higher layers can lift GFF into domain types without pretending the underlying container is a schema-free blob.

Modules§

prelude
Common imports for consumers of this crate.

Structs§

GffCExoLocString
A CExoLocString value. A localized string may either reference a TLK entry via str_ref or carry inline language-specific overrides in entries.
GffField
A labeled GFF field. Labels are stored on the containing GffStruct; this type only wraps the typed value.
GffRoot
A complete GFF document.
GffStruct
A GFF structure containing labeled fields.

Enums§

GffError
Errors returned by GFF readers and writers.
GffFieldKind
The primitive and compound value kinds supported by GFF. These correspond directly to the numeric field type ids stored in the binary format.
GffValue
A typed GFF field value. The enum variants mirror the canonical GFF V3.2 field kinds.

Functions§

merge_root_preserving_provenance
Applies edited onto target while retaining provenance already present on matching parsed fields and structures.
read_gff_root
Reads a complete GFF document from reader.
write_gff_root
Writes a complete GFF document to writer.

Type Aliases§

GffResult
A result alias for GFF operations.