Repository navigation
C#: the FileEntity hierarchy, copy constructors — and the honest answer on generic entities - #5
Merged
Merged
Conversation
…date gap
Consumer feedback round 2 (welder-csharp 772e6c9, pin bumped):
1. GENERIC ENTITIES (ADT<ClientVersion>): assessed and declined — C#
generics take types, not values (no non-type template parameters), and
one generic definition carries ONE member set where the C++
instantiations differ per range; 11 era markers over 5 layouts would
also split type identity (ADT<Mop> != ADT<Legion> despite one native
class), breaking is-checks and dispatch. The hierarchy below is the
C#-idiomatic answer.
2. THE HIERARCHY: Formats.FileEntity (C++ formats::FileEntityBase, welded
"FileEntity") roots every file-level entity — the six family bases AND
BLP derive it. The rod's family surfaces are MULTI-LEVEL now, so the
root auto-hoists exactly the contract every child hierarchy binds:
Validate() and EnsureValid(), dispatched format-then-version through one
FileEntity-typed reference. fs Read/Write stay family-level — ADT's
alpha parameter breaks uniformity, and the intersection excludes them
AUTOMATICALLY rather than by hand list.
The build surfaced two real pre-existing gaps the intersection refused
to paper over:
- single-range families (Skeleton, WDTOcclusion, WDTParticulates) had NO
family surface at all — the rod's two-child minimum; fixed upstream
(the mark is the opt-in, not the child count), so Skeleton.ForVersion
results finally carry members;
- the WDT assembly was the ONE file entity with no validate()/
ensure_valid() in C++. It has them now — a compound over the main file
and every engaged satellite (root/occlusion/lights/fogs/particulates
member paths), mirroring WMO's; the validation-contracts docs page
picks it up automatically.
3. COPY CONSTRUCTION replaces Clone(): new ADTWotlk(other) — the BCL's own
copy idiom — everywhere a C++ copy constructor is admitted. Dispose
stays and now documents itself as OPTIONAL deterministic release (the
SafeHandle finalizer frees native memory on collection; using makes it
prompt).
Also: the BLP class welds as BLP for C# (weld_as(cs) — the dotnet style
coerced the all-caps identifier to Blp; Python always spelled BLP).
Guide gains "One root above the families"; FamilySurfaceTests locks the
heterogeneous WMO+BLP Validate loop, the Read exclusion, and the
copy-ctor surface. dotnet test: 34/34 against the fully rebuilt native.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…tex records The WoWRenderLib profile: ~15% of ParseADT inside McnrEntry.get_Normal / Vector<ushort>.get_Item / FixedArray<uint>.get_Item — element-wise live views paying interop per element (~4 P/Invokes + 4 allocations per packed normal, x37k records per tile). welder-csharp 7f84760 (pin bumped): every POD record class gains a nested blittable `Data` struct (explicit layout at the native offsets, fixed buffers for fixed scalar arrays, nested X.Data for nested records; layout asserted in the shim), and Vector<T>/FixedArray<T> gain AsSpan<TData>() — ONE interop crossing reinterprets the whole native buffer as a managed span, writable, zero allocations. 113 mirrors on our surface, McnrEntry among them: chunk.Normals.AsSpan<McnrEntry.Data>() replaces ~150-200k P/Invokes per tile with one. No new native symbols — the accessor rides the existing element-address thunk, so already-built native libraries keep working. Guide gains "Bulk access to per-vertex records (C#)" on the maps page (the exact profiled case); FamilySurfaceTests locks the McnrEntry span write-through, the live-view round-trip and the size gate. The tests csproj allows unsafe (fixed-buffer indexing). dotnet test: 35/35. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
User review of the bulk API: the AsSpan<McnrEntry.Data>() type argument is
a C# limitation (no associated types — Vector<T> cannot spell T.Data as a
return type, and the span's element must be the MIRROR, not the wrapper
class), but the generator knows the pairing — welder-csharp ad87e50 emits
per-element AsDataSpan() extensions, so the guide's hot loop reads
var normals = chunk.Normals.AsDataSpan();
The wowlib surface also caught the multi-extent dedup upstream (C3Vector
arrays at two extents share one FixedArray<C3Vector> type — extensions now
claim per element). Guide + FamilySurfaceTests use the sugar; pin bumped;
dotnet test 35/35.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Tree byte-identical to the ad87e50 branch head this previously pinned. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The second consumer-feedback round, one question at a time. Rides skarndev/welder-csharp#3 (pinned at
772e6c9) — merge that first.1.
ADT<ClientVersion>generics — assessed, and declinedC# cannot faithfully mimic the C++ value-templated interface: generics take types, not values (no non-type template parameters), and one generic definition carries one member set where
ADT<V>instantiations genuinely differ per range (version-gated members, retyped members). Faking it with 11 era marker types over the 5 real layouts would also split type identity —ADT<Mop>≠ADT<Legion>despite being one native class — breakingis-checks, equality, and the family dispatch. The hierarchy below delivers the intent (version-agnostic, statically-typed common surface) the way C# actually favors.2. The hierarchy:
Formats.FileEntityEvery file-level entity — the six family bases and
BLP— now derivesFormats.FileEntity. With welder-csharp's new multi-level family surfaces, the root auto-hoists exactly the contract every child hierarchy binds:Validate()andEnsureValid(), dispatching format-then-version through oneFileEntity-typed reference.Read/Writestay on the family bases — ADT's alpha parameter breaks uniformity, and the intersection excludes them automatically rather than by hand list.The build refused to paper over two real pre-existing gaps, both now fixed at the right layer:
Skeleton,WDTOcclusion,WDTParticulates— the rod's old two-child minimum). Fixed upstream;Skeleton.ForVersion(...)results finally carry members.validate()/ensure_valid()in C++. Added: a compound over the main file and every engaged satellite (root/occlusion/lights/fogs/particulatesmember paths), mirroring WMO's; the validation-contracts docs page picks it up automatically.3. Copy constructors + Dispose
new ADTWotlk(other)— the BCL's own copy idiom — replacesClone()everywhere a C++ copy constructor is admitted.Disposestays and now documents itself as optional deterministic release (the SafeHandle finalizer frees native memory on collection;usingmakes it prompt) — the C# answer to "proper destructor" is that the destructor already exists.Also: the
BLPclass welds asBLPfor C# (the dotnet style had coerced it toBlp; Python always spelledBLP) — the last straggler from the round-1 acronym directive.Verified
Guide gains "One root above the families";
FamilySurfaceTestslocks the heterogeneous WMO+BLPValidateloop, theReadexclusion, and the copy-ctor surface. Full native rebuild +dotnet test: 34/34.🤖 Generated with Claude Code