Skip to content

Instantly share code, notes, and snippets.

@kennykerr
Last active July 15, 2026 22:30
Show Gist options
  • Select an option

  • Save kennykerr/05c9fd30c5f544e01b1d14df79a8976f to your computer and use it in GitHub Desktop.

Select an option

Save kennykerr/05c9fd30c5f544e01b1d14df79a8976f to your computer and use it in GitHub Desktop.
Report: Faithful in-house metadata vs. win32metadata (windows-rs)

Report: Faithful in-house metadata vs. win32metadata

Recommendation: Adopt the faithful, header-derived approach (windows-rs windows-clang pipeline, PR #4649) as the metadata source of truth for the Rust projection. The evidence below supports this decisively for the windows-rs use case.

The two approaches

win32metadata (microsoft/win32metadata) is a C#/ClangSharp scraper that aims to produce metadata higher-level than the headers. It synthesizes friendly constructs — loose #define constants promoted to enums, handle lifetimes/RAII hints, struct-size fields, SetLastError behavior, doc URLs, OS-version availability, ANSI/Unicode merging, and an editorial sub-namespace taxonomy — encoded with a large custom-attribute vocabulary. To do this it needs an enormous body of hand-curated configuration (libMappings.rsp, enums.json, documentationMappings.rsp, remap/partition files, manual patches).

In-house (windows-clang → RDL → winmd) parses the SDK headers with libclang and emits only what the source directly expresses: SAL (_In_/_Out_/_opt_, counted/sized buffers, _z_, _COM_Outptr_), __declspec (uuid, noreturn, align, dllimport, deprecated), calling conventions, #pragma pack/alignment, unions, bitfields, scoped enums, IDL attributes, and the symbol→DLL map recovered from import libs. Everything lands in a single flat Windows.Win32 namespace, partitioned one file per defining header.

Why faithful wins for Rust

  1. Curation is the cost center. win32metadata's value-add is exactly the part that cannot be derived and must be hand-maintained forever — thousands of lines of .rsp/.json config that drift against every SDK release. The in-house tool has no type-level curation: its entire config is a list of headers, satellite rules, and import libs (const slices in main.rs). Adding APIs = listing a header and regenerating; a full SDK generational bump is absorbed with zero scraper changes.

  2. The "bells and whistles" don't help Rust. The synthesized attributes serve C#/.NET consumers. Rust ergonomics that matter (RAII handles, Result wrapping, typed factories) belong in the hand-written windows projection layer, not smuggled into metadata as synthetic attributes. The in-house pipeline emits exactly 11 attributes, all consumed by bindgen; win32metadata-only attributes (RAIIFree, AssociatedEnum, AlsoUsableFor, Agile, ConstAttribute, …) are simply gone.

  3. Faithful = fewer places to be wrong. Where win32metadata's higher-level output looks more ergonomic (D2D1CreateFactory<T>, enum-typed flags, optional handles), those are hand-patches with no header basis. The in-house signatures that look lower-level are correct, and the ergonomics reappear in the projection layer. Meanwhile faithfulness caught real ABI bugs the higher-level path masked (e.g. MSVC reverse-vtable-order for overloaded virtuals → stack-cookie fail-fast; _COM_Outptr_opt_ optionality loss).

  4. Reviewability & reproducibility. The committed metadata/win32/*.rdl text corpus makes every scrape change a readable git diff; builds are byte-for-byte deterministic (validated on Linux). No dependence on an external, separately-versioned project or its mdmerge/patching toolchain.

  5. Namespaces were an editorial invention. The SDK is a flat C namespace (only 0.02% of type names collide). win32metadata's sub-namespaces have no source signal to recover; the flat namespace + per-header files is the one faithful, mechanical routing signal, while per-function DLL truth is preserved as data (#[library("…")]).

Honest trade-offs

The faithful approach deliberately omits things win32metadata provides: loose-constant→enum promotion, RAII/handle-close metadata, struct auto-size fields, Unicode-first merging, doc URLs, and OS availability. These are handled by:

  • a short, explicitly-tracked editorial-deviation ledger (~13 automatable rules, e.g. unsigned-constant width, string-alias normalization, SAL-driven pointer const-ness) — the single audited place the scrape "tips the scales," each justified by author intent, not by matching win32metadata for its own sake; and
  • the hand-written projection layer for genuine ergonomics.

This is the right boundary: metadata stays honest and self-maintaining; opinion lives in reviewable Rust code.

Bottom line

For windows-rs, the faithful in-house pipeline eliminates a large external curation dependency, produces deterministic reviewable output, self-maintains across SDK bumps, and — because it re-homes ergonomics into the projection layer — loses nothing Rust consumers actually need while gaining ABI correctness. Recommend standardizing on it, keeping the deviation ledger short and the projection layer as the home for higher-level conveniences.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment