fix: deserialize list-of-subpackets with pipe/dot SpecialSeparator#449
Merged
erwan-joly merged 1 commit intomasterfrom Apr 24, 2026
Merged
fix: deserialize list-of-subpackets with pipe/dot SpecialSeparator#449erwan-joly merged 1 commit intomasterfrom
erwan-joly merged 1 commit intomasterfrom
Conversation
Lists like ClinitPacket (`[PacketListIndex(0, SpecialSeparator = "|")]`) carry items space-separated on the wire, with inner fields joined by "|". The serializer produces this correctly. The deserializer had two bugs: 1. Line 325 picked SpecialSeparator as the list-item separator for IPacket lists, then tried to split the first match token by "|" to count items — turning "5130502|99|68|547|Trippybell" into length=5 instead of reading each whitespace-separated item. This inflated length and indexed past the end of the matches array. 2. Line 356's inner field-split loop looked up the next property's SpecialSeparator, falling back to "." when the sub-packet's properties didn't decorate their own separators. For ClinitSubPacket-style packets that fallback never matches the subpacket content, so the whole item was appended once per property — yielding "X|..X|..X|..X|..X|.." that failed to parse. Fix 1: for IPacket lists, ignore SpecialSeparator as list-item separator — it's the inner field separator. ListSeparator (when set) still wins. Fix 2: the inner field-split loop falls back to the outer list's SpecialSeparator when the sub-packet's properties don't specify one. Unlocks deserialisation of clinit / flinit / kdlinit / skyinit / finit / pinit / blinit / rcblist / rcslist / ninv / mlobjlst / tarank and the inner-field handling of any future list of sub-packets with shared separator. Regression test added on ClinitPacket. Primitive-list handling (stp, stp2, bpp, bpm, exclist, nstest server list) left unchanged — confirmed by full suite passing. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
|
Caution Review failedPull request was closed or merged during review WalkthroughUpdates deserialization logic for lists of Changes
Estimated code review effort🎯 3 (Moderate) | ⏱️ ~20 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches📝 Generate docstrings
🧪 Generate unit tests (beta)
Comment |
erwan-joly
added a commit
to NosCoreIO/NosCore.DeveloperTools
that referenced
this pull request
Apr 24, 2026
Picks up NosCoreIO/NosCore.Packets#449 — list-of-sub-packets deserialization fix (clinit/flinit/kdlinit/skyinit/finit/pinit/blinit and anything else using a pipe/dot inner-field separator). Co-authored-by: Claude Opus 4.7 (1M context) <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.
Bumps to 17.1.0 — non-breaking bug fix.
What's broken
Lists declared like `ClinitPacket`:
```csharp
[PacketListIndex(0, SpecialSeparator = "|")]
public List<ClinitSubPacket?>? SubPackets { get; set; }
```
…serialise to `clinit 14531|94|0|396|Raizen 3011|99|0|346|Thanos` — list items space-separated, inner fields `|`-separated. The existing serializer test at SerializerTest.cs:1102 locks this exact shape in. But the deserializer couldn't read its own output. Two coupled bugs:
`Deserializer.cs:325` picked `SpecialSeparator` as the list-item separator for IPacket lists, then ran `matches[currentIndex].Split("|")` over the first token — turning `"5130502|99|68|547|Trippybell"` into `length=5`. Looping 5 times while the actual list has 30+ items indexed straight off the end of `matches`.
`Deserializer.cs:364`'s inner field-split loop looked up the next property's `SpecialSeparator`, falling back to `.` when the sub-packet's properties didn't carry their own separator (the normal case for Clinit/Flinit/Finit/Pinit/etc. style sub-packets). `.IndexOf(".")` returned -1 and the `c == -1` branch appended the whole sub-packet once per property — producing `"5130502|99|68|547|Trippybell5130502|99|68|547|Trippybell5130502|99|68|547|Trippybell5130502|99|68|547|Trippybell5130502|99|68|547|Trippybell"` that `long.Parse` rightly rejected.
The fix
For IPacket lists, ignore `SpecialSeparator` as list-item separator — it's the inner-field separator. `ListSeparator` (when set) still wins. Non-IPacket primitive lists keep the existing `SpecialSeparator` / `.` behaviour.
The inner field-split loop falls back to the outer list's `SpecialSeparator` when the sub-packet property doesn't override it.
What this unblocks
Inbound round-trip for any list-of-subpackets where inner fields share a separator: `clinit`, `flinit`, `kdlinit`, `skyinit`, `finit`, `pinit`, `blinit`, `rcblist`, `rcslist`, `ninv`, `mlobjlst`, `tarank`, plus anything new.
Test plan
Summary by CodeRabbit
Bug Fixes
Tests