Files
natsdotnet/gaps/internal-ds.md
2026-02-25 15:12:52 -05:00

36 KiB

Internal Data Structures — Gap Analysis

This file tracks what has and hasn't been ported from Go to .NET for the Internal Data Structures module. See stillmissing.md for the full LOC comparison across all modules.

LLM Instructions: How to Analyze This Category

Step 1: Read the Go Reference Files

Read each Go source file listed below. For every file:

  1. Extract all exported types (structs, interfaces, type aliases)
  2. Extract all exported methods on those types (receiver functions)
  3. Extract all exported standalone functions
  4. Note key constants, enums, and protocol states
  5. Note important unexported helpers that implement core logic (functions >20 lines)
  6. Pay attention to concurrency patterns (goroutines, mutexes, channels) — these map to different .NET patterns

Step 2: Read the .NET Implementation Files

Read all .cs files in the .NET directories listed below. For each Go symbol found in Step 1:

  1. Search for a matching type, method, or function in .NET
  2. If found, compare the behavior: does it handle the same edge cases? Same error paths?
  3. If partially implemented, note what's missing
  4. If not found, note it as MISSING

Step 3: Cross-Reference Tests

Compare Go test functions against .NET test methods:

  1. For each Go Test* function, check if a corresponding .NET [Fact] or [Theory] exists
  2. Note which test scenarios are covered and which are missing
  3. Check the parity DB (docs/test_parity.db) for existing mappings:
    sqlite3 docs/test_parity.db "SELECT go_test, dotnet_test, confidence FROM test_mappings tm JOIN go_tests gt ON tm.go_test_id=gt.rowid JOIN dotnet_tests dt ON tm.dotnet_test_id=dt.rowid WHERE gt.go_file LIKE '%PATTERN%'"
    

Step 4: Classify Each Item

Use these status values:

Status Meaning
PORTED Equivalent exists in .NET with matching behavior
PARTIAL .NET implementation exists but is incomplete (missing edge cases, error handling, or features)
MISSING No .NET equivalent found — needs to be ported
NOT_APPLICABLE Go-specific pattern that doesn't apply to .NET (build tags, platform-specific goroutine tricks, etc.)
DEFERRED Intentionally skipped for now (document why)

Step 5: Fill In the Gap Inventory

Add rows to the Gap Inventory table below. Group by Go source file. Include the Go file and line number so a porting LLM can jump directly to the reference implementation.

Key Porting Notes for Internal Data Structures

  • This category is at 105% LOC parity — above Go.
  • The subject tree (stree) uses adaptive node sizing (4→10→16→48→256 children) for memory efficiency.
  • The AVL tree is used for tracking acknowledged sequences in JetStream consumers.
  • The time hash wheel provides O(1) TTL expiration checks.
  • PSE (platform-specific extensions) queries process RSS/CPU — may use System.Diagnostics.Process in .NET.
  • sysmem queries total system memory — may use GC.GetGCMemoryInfo() or P/Invoke in .NET.
  • Many Go files in pse/ and sysmem/ are platform-specific build-tagged files — classify platform-irrelevant ones as NOT_APPLICABLE.

Go Reference Files (Source)

  • golang/nats-server/server/avl/seqset.go — AVL tree for sparse sequence sets (JetStream ack tracking)
  • golang/nats-server/server/stree/ — Subject tree with adaptive nodes (node4, node10, node16, node48, node256) for per-subject state in streams. 11 files.
  • golang/nats-server/server/thw/thw.go — Time hash wheel for efficient TTL expiration
  • golang/nats-server/server/gsl/gsl.go — Generic subject list, optimized trie variant
  • golang/nats-server/server/pse/ — Platform-specific extensions (proc info: RSS, CPU). 12 files across platforms.
  • golang/nats-server/server/sysmem/ — System memory queries. 8 files across platforms.

Go Reference Files (Tests)

  • golang/nats-server/server/avl/seqset_test.go
  • golang/nats-server/server/stree/stree_test.go
  • golang/nats-server/server/thw/thw_test.go
  • golang/nats-server/server/gsl/gsl_test.go

.NET Implementation Files (Source)

  • src/NATS.Server/Internal/ (all files including subdirectories)
  • src/NATS.Server/Internal/Avl/
  • src/NATS.Server/Internal/Gsl/
  • src/NATS.Server/Internal/SubjectTree/
  • src/NATS.Server/Internal/TimeHashWheel/

.NET Implementation Files (Tests)

  • tests/NATS.Server.Tests/Internal/ (all subdirectories)

Gap Inventory

avl/seqset.go

Go Symbol Go File:Line Status .NET Equivalent Notes
SequenceSet (struct) golang/nats-server/server/avl/seqset.go:33 PORTED src/NATS.Server/Internal/Avl/SequenceSet.cs:26 Full class with all fields
SequenceSet.Insert golang/nats-server/server/avl/seqset.go:44 PORTED src/NATS.Server/Internal/Avl/SequenceSet.cs:52
SequenceSet.Exists golang/nats-server/server/avl/seqset.go:52 PORTED src/NATS.Server/Internal/Avl/SequenceSet.cs:63
SequenceSet.SetInitialMin golang/nats-server/server/avl/seqset.go:69 PORTED src/NATS.Server/Internal/Avl/SequenceSet.cs:89 Go returns error; .NET throws
SequenceSet.Delete golang/nats-server/server/avl/seqset.go:80 PORTED src/NATS.Server/Internal/Avl/SequenceSet.cs:103
SequenceSet.Size golang/nats-server/server/avl/seqset.go:97 PORTED src/NATS.Server/Internal/Avl/SequenceSet.cs:43 Property in .NET
SequenceSet.Nodes golang/nats-server/server/avl/seqset.go:102 PORTED src/NATS.Server/Internal/Avl/SequenceSet.cs:46 Property in .NET
SequenceSet.Empty golang/nats-server/server/avl/seqset.go:107 PORTED src/NATS.Server/Internal/Avl/SequenceSet.cs:127
SequenceSet.IsEmpty golang/nats-server/server/avl/seqset.go:114 PORTED src/NATS.Server/Internal/Avl/SequenceSet.cs:49 Property in .NET
SequenceSet.Range golang/nats-server/server/avl/seqset.go:124 PORTED src/NATS.Server/Internal/Avl/SequenceSet.cs:138
SequenceSet.Heights golang/nats-server/server/avl/seqset.go:129 PORTED src/NATS.Server/Internal/Avl/SequenceSet.cs:141 Returns tuple in .NET
SequenceSet.State golang/nats-server/server/avl/seqset.go:143 PORTED src/NATS.Server/Internal/Avl/SequenceSet.cs:153 Returns named tuple
SequenceSet.MinMax golang/nats-server/server/avl/seqset.go:152 PORTED src/NATS.Server/Internal/Avl/SequenceSet.cs:166
clone (unexported) golang/nats-server/server/avl/seqset.go:169 PORTED src/NATS.Server/Internal/Avl/SequenceSet.cs:424 CloneNode private static method
SequenceSet.Clone golang/nats-server/server/avl/seqset.go:180 PORTED src/NATS.Server/Internal/Avl/SequenceSet.cs:195
SequenceSet.Union (method) golang/nats-server/server/avl/seqset.go:191 PORTED src/NATS.Server/Internal/Avl/SequenceSet.cs:203
Union (function) golang/nats-server/server/avl/seqset.go:208 PORTED src/NATS.Server/Internal/Avl/SequenceSet.cs:228 SequenceSet.CreateUnion static method
SequenceSet.EncodeLen golang/nats-server/server/avl/seqset.go:238 PORTED src/NATS.Server/Internal/Avl/SequenceSet.cs:252 EncodeLength() in .NET
SequenceSet.Encode golang/nats-server/server/avl/seqset.go:242 PARTIAL src/NATS.Server/Internal/Avl/SequenceSet.cs:255 Go signature takes optional buf to reuse; .NET always allocates new. Behavior equivalent.
ErrBadEncoding golang/nats-server/server/avl/seqset.go:276 PORTED src/NATS.Server/Internal/Avl/SequenceSet.cs:288 Thrown as InvalidOperationException
ErrBadVersion golang/nats-server/server/avl/seqset.go:277 PORTED src/NATS.Server/Internal/Avl/SequenceSet.cs:295 Thrown as InvalidOperationException
ErrSetNotEmpty golang/nats-server/server/avl/seqset.go:278 PORTED src/NATS.Server/Internal/Avl/SequenceSet.cs:93 Thrown as InvalidOperationException
Decode golang/nats-server/server/avl/seqset.go:282 PORTED src/NATS.Server/Internal/Avl/SequenceSet.cs:285 Static method, same v1/v2 dispatch
decodev2 (unexported) golang/nats-server/server/avl/seqset.go:298 PORTED src/NATS.Server/Internal/Avl/SequenceSet.cs:300 DecodeV2 private static
decodev1 (unexported) golang/nats-server/server/avl/seqset.go:329 PORTED src/NATS.Server/Internal/Avl/SequenceSet.cs:338 DecodeV1 private static
SequenceSet.insertNode (unexported) golang/nats-server/server/avl/seqset.go:376 PORTED src/NATS.Server/Internal/Avl/SequenceSet.cs:389 InsertNode private method
node (struct) golang/nats-server/server/avl/seqset.go:407 PORTED src/NATS.Server/Internal/Avl/SequenceSet.cs:439 Node nested class
node.set golang/nats-server/server/avl/seqset.go:418 PORTED src/NATS.Server/Internal/Avl/SequenceSet.cs:448 SetBit
node.insert golang/nats-server/server/avl/seqset.go:428 PORTED src/NATS.Server/Internal/Avl/SequenceSet.cs:521 Node.Insert static
node.rotateL golang/nats-server/server/avl/seqset.go:464 PORTED src/NATS.Server/Internal/Avl/SequenceSet.cs:672 RotateLeft private static
node.rotateR golang/nats-server/server/avl/seqset.go:478 PORTED src/NATS.Server/Internal/Avl/SequenceSet.cs:692 RotateRight private static
balanceF golang/nats-server/server/avl/seqset.go:492 PORTED src/NATS.Server/Internal/Avl/SequenceSet.cs:711 BalanceFactor internal static
maxH golang/nats-server/server/avl/seqset.go:506 PORTED src/NATS.Server/Internal/Avl/SequenceSet.cs:724 MaxHeight internal static
node.clear golang/nats-server/server/avl/seqset.go:526 PORTED src/NATS.Server/Internal/Avl/SequenceSet.cs:461 ClearBit
node.delete golang/nats-server/server/avl/seqset.go:542 PORTED src/NATS.Server/Internal/Avl/SequenceSet.cs:571 Node.Delete static
node.insertNodePrev golang/nats-server/server/avl/seqset.go:588 PORTED src/NATS.Server/Internal/Avl/SequenceSet.cs:635 InsertNodePrev private static
node.exists golang/nats-server/server/avl/seqset.go:613 PORTED src/NATS.Server/Internal/Avl/SequenceSet.cs:484 ExistsBit
node.min golang/nats-server/server/avl/seqset.go:622 PORTED src/NATS.Server/Internal/Avl/SequenceSet.cs:493 Min()
node.max golang/nats-server/server/avl/seqset.go:635 PORTED src/NATS.Server/Internal/Avl/SequenceSet.cs:508 Max()
node.nodeIter golang/nats-server/server/avl/seqset.go:647 PORTED src/NATS.Server/Internal/Avl/SequenceSet.cs:738 NodeIter internal static
node.iter golang/nats-server/server/avl/seqset.go:658 PORTED src/NATS.Server/Internal/Avl/SequenceSet.cs:751 Iter internal static

stree/stree.go

Go Symbol Go File:Line Status .NET Equivalent Notes
SubjectTree[T] (struct) golang/nats-server/server/stree/stree.go:28 PORTED src/NATS.Server/Internal/SubjectTree/SubjectTree.cs:9
NewSubjectTree[T] golang/nats-server/server/stree/stree.go:34 PORTED src/NATS.Server/Internal/SubjectTree/SubjectTree.cs:9 In .NET, new SubjectTree<T>() used directly
SubjectTree.Size golang/nats-server/server/stree/stree.go:39 PORTED src/NATS.Server/Internal/SubjectTree/SubjectTree.cs:17
SubjectTree.Empty golang/nats-server/server/stree/stree.go:47 PORTED src/NATS.Server/Internal/SubjectTree/SubjectTree.cs:22
SubjectTree.Insert golang/nats-server/server/stree/stree.go:56 PORTED src/NATS.Server/Internal/SubjectTree/SubjectTree.cs:33 Signature uses ReadOnlySpan<byte>
SubjectTree.Find golang/nats-server/server/stree/stree.go:74 PORTED src/NATS.Server/Internal/SubjectTree/SubjectTree.cs:52
SubjectTree.Delete golang/nats-server/server/stree/stree.go:106 PORTED src/NATS.Server/Internal/SubjectTree/SubjectTree.cs:97
SubjectTree.Match golang/nats-server/server/stree/stree.go:119 PORTED src/NATS.Server/Internal/SubjectTree/SubjectTree.cs:115
SubjectTree.MatchUntil golang/nats-server/server/stree/stree.go:137 PORTED src/NATS.Server/Internal/SubjectTree/SubjectTree.cs:135
SubjectTree.IterOrdered golang/nats-server/server/stree/stree.go:149 PORTED src/NATS.Server/Internal/SubjectTree/SubjectTree.cs:149
SubjectTree.IterFast golang/nats-server/server/stree/stree.go:158 PORTED src/NATS.Server/Internal/SubjectTree/SubjectTree.cs:158
SubjectTree.insert (internal) golang/nats-server/server/stree/stree.go:169 PORTED src/NATS.Server/Internal/SubjectTree/SubjectTree.cs:170 InsertInternal
SubjectTree.delete (internal) golang/nats-server/server/stree/stree.go:253 PORTED src/NATS.Server/Internal/SubjectTree/SubjectTree.cs:286 DeleteInternal
SubjectTree.match (internal) golang/nats-server/server/stree/stree.go:318 PORTED src/NATS.Server/Internal/SubjectTree/SubjectTree.cs:383 MatchInternal
SubjectTree.iter (internal) golang/nats-server/server/stree/stree.go:418 PORTED src/NATS.Server/Internal/SubjectTree/SubjectTree.cs:512 IterInternal
LazyIntersect[TL,TR] golang/nats-server/server/stree/stree.go:463 PORTED src/NATS.Server/Internal/SubjectTree/SubjectTree.cs:584 SubjectTreeHelper.LazyIntersect static
IntersectGSL[T,SL] golang/nats-server/server/stree/stree.go:488 MISSING No .NET equivalent. Intersects stree with gsl.GenericSublist. Used in JetStream consumer NumPending.
_intersectGSL (internal) golang/nats-server/server/stree/stree.go:496 MISSING Helper for IntersectGSL
hasInterestForTokens (internal) golang/nats-server/server/stree/stree.go:521 MISSING Token-boundary interest check for GSL intersection
bytesToString (internal) golang/nats-server/server/stree/stree.go:534 NOT_APPLICABLE Go unsafe zero-copy string conversion. In .NET, System.Text.Encoding.UTF8.GetString or MemoryMarshal.Cast used instead

stree/node.go

Go Symbol Go File:Line Status .NET Equivalent Notes
node (interface) golang/nats-server/server/stree/node.go:17 PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:7 INode interface
meta (struct) golang/nats-server/server/stree/node.go:35 PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:46 NodeMeta class
meta.isLeaf golang/nats-server/server/stree/node.go:40 PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:9 Via INode.IsLeaf
meta.base golang/nats-server/server/stree/node.go:41 PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:10 Via INode.Base
meta.setPrefix golang/nats-server/server/stree/node.go:43 PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:11 Via INode.SetPrefix
meta.numChildren golang/nats-server/server/stree/node.go:47 PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:26 Via INode.NumChildren
meta.path golang/nats-server/server/stree/node.go:48 PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:27 Via INode.Path
meta.matchParts golang/nats-server/server/stree/node.go:51 PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:22 Via INode.MatchParts

stree/leaf.go

Go Symbol Go File:Line Status .NET Equivalent Notes
leaf[T] (struct) golang/nats-server/server/stree/leaf.go:23 PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:58 Leaf<T> class
newLeaf[T] golang/nats-server/server/stree/leaf.go:30 PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:63 new Leaf<T>(suffix, value) constructor
leaf.isLeaf golang/nats-server/server/stree/leaf.go:34 PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:69
leaf.base golang/nats-server/server/stree/leaf.go:34 PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:70 Returns null
leaf.match golang/nats-server/server/stree/leaf.go:36 PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:75
leaf.setSuffix golang/nats-server/server/stree/leaf.go:37 PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:77
leaf.matchParts golang/nats-server/server/stree/leaf.go:39 PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:85
leaf.iter golang/nats-server/server/stree/leaf.go:40 PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:83 No-op on leaf
leaf.children golang/nats-server/server/stree/leaf.go:41 PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:81 Returns empty array
leaf.numChildren golang/nats-server/server/stree/leaf.go:42 PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:72 Returns 0
leaf.path golang/nats-server/server/stree/leaf.go:43 PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:79 Returns suffix

stree/node4.go

Go Symbol Go File:Line Status .NET Equivalent Notes
node4 (struct) golang/nats-server/server/stree/node4.go:18 PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:105 Node4 class
newNode4 golang/nats-server/server/stree/node4.go:24 PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:111 Constructor
node4.addChild golang/nats-server/server/stree/node4.go:31 PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:128
node4.findChild golang/nats-server/server/stree/node4.go:40 PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:136 Returns ChildRef? wrapper
node4.isFull golang/nats-server/server/stree/node4.go:49 PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:119
node4.grow golang/nats-server/server/stree/node4.go:51 PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:174
node4.deleteChild golang/nats-server/server/stree/node4.go:60 PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:149
node4.shrink golang/nats-server/server/stree/node4.go:80 PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:184
node4.iter golang/nats-server/server/stree/node4.go:88 PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:190
node4.children golang/nats-server/server/stree/node4.go:96 PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:198

stree/node10.go

Go Symbol Go File:Line Status .NET Equivalent Notes
node10 (struct) golang/nats-server/server/stree/node10.go:20 PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:217 Node10 class
newNode10 golang/nats-server/server/stree/node10.go:26 PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:223 Constructor
node10.addChild golang/nats-server/server/stree/node10.go:34 PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:240
node10.findChild golang/nats-server/server/stree/node10.go:43 PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:248
node10.isFull golang/nats-server/server/stree/node10.go:52 PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:231
node10.grow golang/nats-server/server/stree/node10.go:54 PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:286
node10.deleteChild golang/nats-server/server/stree/node10.go:63 PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:258
node10.shrink golang/nats-server/server/stree/node10.go:83 PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:295
node10.iter golang/nats-server/server/stree/node10.go:95 PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:307
node10.children golang/nats-server/server/stree/node10.go:103 PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:315

stree/node16.go, stree/node48.go, stree/node256.go

Go Symbol Go File:Line Status .NET Equivalent Notes
node16 (struct) golang/nats-server/server/stree/node16.go PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:334 Node16 class
node48 (struct) golang/nats-server/server/stree/node48.go PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:451 Node48 class
node256 (struct) golang/nats-server/server/stree/node256.go PORTED src/NATS.Server/Internal/SubjectTree/Nodes.cs:569 Node256 class

stree/parts.go

Go Symbol Go File:Line Status .NET Equivalent Notes
genParts golang/nats-server/server/stree/parts.go:23 PORTED src/NATS.Server/Internal/SubjectTree/Parts.cs:57 Parts.GenParts static method
matchParts golang/nats-server/server/stree/parts.go:78 PORTED src/NATS.Server/Internal/SubjectTree/Parts.cs:145 Parts.MatchPartsAgainstFragment

stree/util.go

Go Symbol Go File:Line Status .NET Equivalent Notes
pwc, fwc, tsep constants golang/nats-server/server/stree/util.go:17 PORTED src/NATS.Server/Internal/SubjectTree/Parts.cs:10 Parts.Pwc, Parts.Fwc, Parts.Tsep
commonPrefixLen golang/nats-server/server/stree/util.go:24 PORTED src/NATS.Server/Internal/SubjectTree/Parts.cs:33 Parts.CommonPrefixLen
copyBytes golang/nats-server/server/stree/util.go:36 PORTED src/NATS.Server/Internal/SubjectTree/Parts.cs:47 Parts.CopyBytes
position (interface) golang/nats-server/server/stree/util.go:45 NOT_APPLICABLE Go generic constraint on numeric types; not needed in .NET
noPivot constant golang/nats-server/server/stree/util.go:48 PORTED src/NATS.Server/Internal/SubjectTree/Parts.cs:17 Parts.NoPivot
pivot golang/nats-server/server/stree/util.go:52 PORTED src/NATS.Server/Internal/SubjectTree/Parts.cs:23 Parts.Pivot

stree/dump.go

Go Symbol Go File:Line Status .NET Equivalent Notes
SubjectTree.Dump golang/nats-server/server/stree/dump.go:23 MISSING Debug utility for printing tree structure to an io.Writer. No .NET equivalent. Low priority — debug/diagnostic only.
SubjectTree.dump (internal) golang/nats-server/server/stree/dump.go:29 MISSING Internal helper for Dump
dumpPre golang/nats-server/server/stree/dump.go:59 MISSING Indentation helper for Dump
leaf.kind, node4.kind, etc. golang/nats-server/server/stree/dump.go:51 PARTIAL src/NATS.Server/Internal/SubjectTree/Nodes.cs INode.Kind property exists on each node type, but Dump method is not implemented

thw/thw.go

Go Symbol Go File:Line Status .NET Equivalent Notes
ErrTaskNotFound golang/nats-server/server/thw/thw.go:25 PORTED src/NATS.Server/Internal/TimeHashWheel/HashWheel.cs:91 Returned as false/exception instead of error
ErrInvalidVersion golang/nats-server/server/thw/thw.go:28 PORTED src/NATS.Server/Internal/TimeHashWheel/HashWheel.cs:289 Thrown as InvalidOperationException
slot (struct) golang/nats-server/server/thw/thw.go:39 PORTED src/NATS.Server/Internal/TimeHashWheel/HashWheel.cs:406 Slot internal class
HashWheel (struct) golang/nats-server/server/thw/thw.go:45 PORTED src/NATS.Server/Internal/TimeHashWheel/HashWheel.cs:17 HashWheel class
HashWheelEntry (struct) golang/nats-server/server/thw/thw.go:52 MISSING Go uses this struct for entry representation in some contexts; .NET uses (ulong, long) tuples inline instead
NewHashWheel golang/nats-server/server/thw/thw.go:58 PORTED src/NATS.Server/Internal/TimeHashWheel/HashWheel.cs:34 Constructor in .NET
HashWheel.getPosition (internal) golang/nats-server/server/thw/thw.go:66 PORTED src/NATS.Server/Internal/TimeHashWheel/HashWheel.cs:50 GetPosition private static
newSlot (internal) golang/nats-server/server/thw/thw.go:71 PORTED src/NATS.Server/Internal/TimeHashWheel/HashWheel.cs:406 Inline slot initialization in .NET
HashWheel.Add golang/nats-server/server/thw/thw.go:79 PORTED src/NATS.Server/Internal/TimeHashWheel/HashWheel.cs:60 Return type void vs error (never errors in practice)
HashWheel.Remove golang/nats-server/server/thw/thw.go:103 PORTED src/NATS.Server/Internal/TimeHashWheel/HashWheel.cs:91 Returns bool instead of error
HashWheel.Update golang/nats-server/server/thw/thw.go:123 PORTED src/NATS.Server/Internal/TimeHashWheel/HashWheel.cs:122
HashWheel.ExpireTasks golang/nats-server/server/thw/thw.go:133 PORTED src/NATS.Server/Internal/TimeHashWheel/HashWheel.cs:135
HashWheel.expireTasks (internal) golang/nats-server/server/thw/thw.go:138 PORTED src/NATS.Server/Internal/TimeHashWheel/HashWheel.cs:148 ExpireTasksInternal — public in .NET for testability
HashWheel.GetNextExpiration golang/nats-server/server/thw/thw.go:182 PORTED src/NATS.Server/Internal/TimeHashWheel/HashWheel.cs:219
HashWheel.Count golang/nats-server/server/thw/thw.go:190 PORTED src/NATS.Server/Internal/TimeHashWheel/HashWheel.cs:44 Property in .NET
HashWheel.Encode golang/nats-server/server/thw/thw.go:197 PORTED src/NATS.Server/Internal/TimeHashWheel/HashWheel.cs:235
HashWheel.Decode golang/nats-server/server/thw/thw.go:216 PORTED src/NATS.Server/Internal/TimeHashWheel/HashWheel.cs:282 Returns (highSeq, bytesRead) tuple; Go returns (uint64, error)

gsl/gsl.go

Go Symbol Go File:Line Status .NET Equivalent Notes
ErrInvalidSubject golang/nats-server/server/gsl/gsl.go:41 PORTED src/NATS.Server/Internal/Gsl/GenericSubjectList.cs:11 GslErrors.InvalidSubject
ErrNotFound golang/nats-server/server/gsl/gsl.go:42 PORTED src/NATS.Server/Internal/Gsl/GenericSubjectList.cs:12 GslErrors.NotFound
ErrNilChan golang/nats-server/server/gsl/gsl.go:43 NOT_APPLICABLE Go channel-specific error; channels don't apply to .NET pattern
ErrAlreadyRegistered golang/nats-server/server/gsl/gsl.go:44 NOT_APPLICABLE Used by notification channels in Go; no notification channel pattern in .NET port
SimpleSublist (type alias) golang/nats-server/server/gsl/gsl.go:49 PARTIAL src/NATS.Server/Internal/Gsl/GenericSubjectList.cs:650 SimpleSubjectList uses int instead of struct{}. Functionally equivalent but not a true zero-allocation alias
NewSimpleSublist golang/nats-server/server/gsl/gsl.go:52 PORTED src/NATS.Server/Internal/Gsl/GenericSubjectList.cs:650 new SimpleSubjectList()
GenericSublist[T] (struct) golang/nats-server/server/gsl/gsl.go:57 PORTED src/NATS.Server/Internal/Gsl/GenericSubjectList.cs:76 GenericSubjectList<T>
node[T] (struct) golang/nats-server/server/gsl/gsl.go:64 PORTED src/NATS.Server/Internal/Gsl/GenericSubjectList.cs:52 Node<T>
level[T] (struct) golang/nats-server/server/gsl/gsl.go:71 PORTED src/NATS.Server/Internal/Gsl/GenericSubjectList.cs:19 Level<T>
newNode[T] golang/nats-server/server/gsl/gsl.go:77 PORTED src/NATS.Server/Internal/Gsl/GenericSubjectList.cs:52 Inline new Node<T>()
newLevel[T] golang/nats-server/server/gsl/gsl.go:82 PORTED src/NATS.Server/Internal/Gsl/GenericSubjectList.cs:19 Inline new Level<T>()
NewSublist[T] golang/nats-server/server/gsl/gsl.go:87 PORTED src/NATS.Server/Internal/Gsl/GenericSubjectList.cs:76 new GenericSubjectList<T>() constructor
GenericSublist.Insert golang/nats-server/server/gsl/gsl.go:92 PORTED src/NATS.Server/Internal/Gsl/GenericSubjectList.cs:110 Throws instead of returning error
GenericSublist.Match golang/nats-server/server/gsl/gsl.go:150 PORTED src/NATS.Server/Internal/Gsl/GenericSubjectList.cs:205
GenericSublist.MatchBytes golang/nats-server/server/gsl/gsl.go:156 PORTED src/NATS.Server/Internal/Gsl/GenericSubjectList.cs:214
GenericSublist.HasInterest golang/nats-server/server/gsl/gsl.go:162 PORTED src/NATS.Server/Internal/Gsl/GenericSubjectList.cs:225
GenericSublist.NumInterest golang/nats-server/server/gsl/gsl.go:168 PORTED src/NATS.Server/Internal/Gsl/GenericSubjectList.cs:234
GenericSublist.match (internal) golang/nats-server/server/gsl/gsl.go:173 PORTED src/NATS.Server/Internal/Gsl/GenericSubjectList.cs:274 MatchInternal
GenericSublist.hasInterest (internal) golang/nats-server/server/gsl/gsl.go:198 PORTED src/NATS.Server/Internal/Gsl/GenericSubjectList.cs:295 HasInterestInternal
matchLevelForAny[T] golang/nats-server/server/gsl/gsl.go:223 PORTED src/NATS.Server/Internal/Gsl/GenericSubjectList.cs:400 MatchLevelForAny private static
callbacksForResults[T] golang/nats-server/server/gsl/gsl.go:266 PORTED src/NATS.Server/Internal/Gsl/GenericSubjectList.cs:448 CallbacksForResults private static
matchLevel[T] golang/nats-server/server/gsl/gsl.go:273 PORTED src/NATS.Server/Internal/Gsl/GenericSubjectList.cs:371 MatchLevel private static
lnt[T] (struct) golang/nats-server/server/gsl/gsl.go:301 PORTED src/NATS.Server/Internal/Gsl/GenericSubjectList.cs:68 Lnt<T> record struct
GenericSublist.remove (internal) golang/nats-server/server/gsl/gsl.go:308 PORTED src/NATS.Server/Internal/Gsl/GenericSubjectList.cs:458 RemoveInternal
GenericSublist.Remove golang/nats-server/server/gsl/gsl.go:368 PORTED src/NATS.Server/Internal/Gsl/GenericSubjectList.cs:188
GenericSublist.HasInterestStartingIn golang/nats-server/server/gsl/gsl.go:373 PORTED src/NATS.Server/Internal/Gsl/GenericSubjectList.cs:245
hasInterestStartingIn[T] (internal) golang/nats-server/server/gsl/gsl.go:381 PORTED src/NATS.Server/Internal/Gsl/GenericSubjectList.cs:537 HasInterestStartingInLevel private static
level.pruneNode golang/nats-server/server/gsl/gsl.go:403 PORTED src/NATS.Server/Internal/Gsl/GenericSubjectList.cs:37 Level<T>.PruneNode
node.isEmpty golang/nats-server/server/gsl/gsl.go:418 PORTED src/NATS.Server/Internal/Gsl/GenericSubjectList.cs:61 Node<T>.IsEmpty()
level.numNodes golang/nats-server/server/gsl/gsl.go:423 PORTED src/NATS.Server/Internal/Gsl/GenericSubjectList.cs:25 Level<T>.NumNodes()
GenericSublist.removeFromNode (internal) golang/nats-server/server/gsl/gsl.go:438 PORTED src/NATS.Server/Internal/Gsl/GenericSubjectList.cs:527 RemoveFromNode private static
GenericSublist.Count golang/nats-server/server/gsl/gsl.go:449 PORTED src/NATS.Server/Internal/Gsl/GenericSubjectList.cs:90
GenericSublist.numLevels (internal) golang/nats-server/server/gsl/gsl.go:457 PORTED src/NATS.Server/Internal/Gsl/GenericSubjectList.cs:264 NumLevels() internal
visitLevel[T] golang/nats-server/server/gsl/gsl.go:463 PORTED src/NATS.Server/Internal/Gsl/GenericSubjectList.cs:557 VisitLevel private static
tokenizeSubjectIntoSlice golang/nats-server/server/gsl/gsl.go:496 PORTED src/NATS.Server/Internal/Gsl/GenericSubjectList.cs:348 TokenizeSubjectIntoSpan

pse/ (Platform-Specific Extensions)

Go Symbol Go File:Line Status .NET Equivalent Notes
ProcUsage (darwin) golang/nats-server/server/pse/pse_darwin.go:83 PORTED src/NATS.Server/Monitoring/VarzHandler.cs:35 CPU via Process.TotalProcessorTime; RSS via proc.WorkingSet64. Equivalent behavior in /varz reporting.
ProcUsage (linux) golang/nats-server/server/pse/pse_linux.go PORTED src/NATS.Server/Monitoring/VarzHandler.cs:35 Same cross-platform .NET equivalent
ProcUsage (windows) golang/nats-server/server/pse/pse_windows.go PORTED src/NATS.Server/Monitoring/VarzHandler.cs:35 Same cross-platform .NET equivalent
ProcUsage (freebsd/netbsd/openbsd/dragonfly/solaris/zos) golang/nats-server/server/pse/pse_*.go NOT_APPLICABLE Platform-specific Go build-tagged files. .NET runtime abstracts these OS differences.
ProcUsage (wasm/rumprun) golang/nats-server/server/pse/pse_wasm.go NOT_APPLICABLE Stub/no-op implementations for unsupported platforms; not needed in .NET
updateUsage (darwin, internal) golang/nats-server/server/pse/pse_darwin.go:56 PORTED src/NATS.Server/Monitoring/VarzHandler.cs:39 CPU sampling logic in VarzHandler
periodic (darwin, internal) golang/nats-server/server/pse/pse_darwin.go:76 PARTIAL src/NATS.Server/Monitoring/VarzHandler.cs:39 Go runs periodic background timer; .NET samples on each /varz request with 1s cache. Semantics slightly different.

sysmem/ (System Memory Queries)

Go Symbol Go File:Line Status .NET Equivalent Notes
Memory (darwin) golang/nats-server/server/sysmem/mem_darwin.go:18 MISSING Queries total physical RAM via hw.memsize sysctl. No .NET equivalent in codebase. Used by JetStream for sizing decisions.
Memory (linux) golang/nats-server/server/sysmem/mem_linux.go:20 MISSING Queries via syscall.Sysinfo. No .NET equivalent found.
Memory (windows) golang/nats-server/server/sysmem/mem_windows.go MISSING No .NET equivalent found. Can be implemented via GC.GetGCMemoryInfo().TotalAvailableMemoryBytes.
Memory (bsd/solaris/wasm/zos) golang/nats-server/server/sysmem/mem_bsd.go etc. NOT_APPLICABLE Platform-specific stubs; .NET runtime abstracts these. GCMemoryInfo is the cross-platform equivalent.
sysctlInt64 golang/nats-server/server/sysmem/sysctl.go:23 NOT_APPLICABLE Darwin/BSD internal helper using unsafe sysctl; .NET abstracts this entirely

Keeping This File Updated

After porting work is completed:

  1. Update status: Change MISSING → PORTED or PARTIAL → PORTED for each item completed
  2. Add .NET path: Fill in the ".NET Equivalent" column with the actual file:line
  3. Re-count LOC: Update the LOC numbers in stillmissing.md:
    # Re-count .NET source LOC for this module
    find src/NATS.Server/Internal/ -name '*.cs' -type f -exec cat {} + | wc -l
    # Re-count .NET test LOC for this module
    find tests/NATS.Server.Tests/Internal/ -name '*.cs' -type f -exec cat {} + | wc -l
    
  4. Add a changelog entry below with date and summary of what was ported
  5. Update the parity DB if new test mappings were created:
    sqlite3 docs/test_parity.db "INSERT INTO test_mappings (go_test_id, dotnet_test_id, confidence, notes) VALUES (?, ?, 'manual', 'ported in YYYY-MM-DD session')"
    

Change Log

Date Change By
2026-02-25 File created with LLM analysis instructions auto
2026-02-25 Full gap inventory populated: 157 PORTED, 4 PARTIAL, 10 MISSING, 8 NOT_APPLICABLE, 0 DEFERRED auto