Define complete Rust API mapping schema

This commit is contained in:
2026-08-08 11:36:23 +02:00
parent a3e11bc39d
commit 3179d7a57d
8 changed files with 34898 additions and 11 deletions

View File

@@ -22,8 +22,11 @@ Generated inventories are intentionally checked in:
projects, including a SHA-256 digest.
- `api/public-api.json` is the authoritative compiled-metadata catalog for all
13 library assemblies after all six source generators run. It also records
every external type referenced by a public signature as a pending Rust
mapping obligation.
every external type referenced by a public signature.
- `api/RUST-TYPES.tsv` resolves all 3,066 public and 142 external signature
types, plus two support traits referenced by public inheritance metadata.
- `api/RUST-MAPPING.tsv` records the reviewed Rust destination and complete
signature decision for all 30,789 public members.
- `tests/upstream-tests.json` records every NUnit invocation and the SHA-256 of
its C# method body.
- `tests/PARITY.md` maps every NUnit invocation to its Rust test name.
@@ -45,8 +48,8 @@ The current workspace is a structural baseline, not a working client:
- 1,705 public C# type declarations produce compiling Rust type/trait shims;
- 12,195 public declaration lines are retained in the API ledger;
- compiled metadata records 3,066 public types and 30,789 public members with
matching independent ECMA-335 counts, plus 142 external signature types that
still require explicit Rust mapping decisions;
matching independent ECMA-335 counts, with all 142 external signature types
resolved to cross-platform Rust or project-owned boundary types;
- all 1,295 NUnit `[Test]`/`[TestCase]` invocations have compiling Rust test
entries that intentionally panic with their source identity and body hash;
- all nine sample/tool projects have compiling Rust binary targets;
@@ -166,6 +169,33 @@ Apply these rules consistently:
| vectors/quaternions/matrices | compatibility structs with LibreMetaverse field/order semantics; use `glam` internally after parity tests prove conversions |
| dependency injection container | normal constructors and explicit trait parameters; add no service-locator equivalent |
The checked-in mapping ledgers make those rules concrete:
- properties become getter/setter methods; indexers become `item`/`set_item`
methods with their index parameters;
- events become typed subscriptions returning a guard; stored delegates become
`Fn` callbacks, while CLR `BeginInvoke`/`EndInvoke` rows are retained as
intentional differences;
- `in` borrows immutably, `ref` borrows mutably, and `out` is a mutable output;
optional parameters use `Option<T>` rather than Rust default arguments;
- nullable values use `Option<T>` at the exact metadata node, including nested
generic arguments;
- inheritance maps to traits and composition rather than class inheritance;
generic parameters retain their names and cataloged constraints as explicit
Rust bounds recorded in the mapping ledgers;
- operators receive stable trait-style names; overloads receive parameter-based
descriptive suffixes and a stable ID suffix only when necessary;
- `[Flags]` enums use `bitflags` with unknown bits retained; wire enums use their
exact width/discriminants and an `Unknown(raw)` form only when extensible;
- all third-party types exposed by C# signatures map through project-owned
cross-platform boundary types. No mapping may name a macOS-only API unless
equivalent Linux and Windows implementations are provided.
Run `python3 tools/generate_rust_mapping.py --check` after any catalog or mapping
rule change. It regenerates in memory and rejects duplicate source IDs or Rust
destinations, stale/missing members, unresolved referenced types, invalid
statuses, missing assembly representatives, and platform-specific targets.
Public structs and enums that come from the protocol must be `#[non_exhaustive]`
when servers may add values. Do not derive `Serialize`/`Deserialize` as a
substitute for the specified wire encoding: LLUDP, LLSD, MessagePack, asset