Pin Holds on every list shape, and drop C#'s redundant first-slot check

CultElementIds.Holds is the one fact a store marks its header by; a test now
drives it directly over a dictionary value, a list of lists, a list under an
unset element and an element, and over unset ids that hold nothing, so a
mutant that skips any of those branches fails.

C# ReadStoreHeader refused a first-slot string without the cultcache.store.
prefix and then ran RequireSingleFileFormat, which refuses every string that
is not v1, v2 or v3 anyway. The prefix check is gone; a non-header string is
refused as a format this runtime does not read.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Meta Vens 2026-09-30 00:11:13 +02:00
commit fd1cf22ffe
2 changed files with 19 additions and 2 deletions

View file

@ -270,9 +270,8 @@ public static class CultDocumentMessagePackSerialization
var reader = new MessagePackReader(bytes);
if (reader.ReadArrayHeader() == 0 || reader.NextMessagePackType != MessagePackType.String)
return null;
// A first slot that is a string is a header, and one this runtime does not read is refused, whatever the string says.
var header = reader.ReadString() ?? string.Empty;
if (!header.StartsWith("cultcache.store.", StringComparison.Ordinal))
throw new NotSupportedException($"The store's first slot is the string '{header}', not a store header; it is not rewritten.");
RequireSingleFileFormat(new CultPersistedStoreSnapshot { FormatVersion = header });
return header;
}

View file

@ -67,6 +67,24 @@ namespace GameCult.Caching.Tests
Assert.That(Assign(root, "r", deterministic: false), Is.EqualTo(0), "a second pass finds nothing unset");
}
// Holds is what a store marks its header by: an id anywhere a list can sit counts, and an unset one does not.
[Test]
public void HoldsFindsASetIdWhereverAListCanSitAndNothingElse()
{
const string id = "0123456789ab";
Assert.That(CultElementIds.Holds(null), Is.False);
Assert.That(CultElementIds.Holds(new HAll
{
Dict = { ["k"] = new HHasIds { Items = { new EIded() } } },
Grid = { new List<EIded> { new EIded() } },
Nest = { new ENest { Sub = { new EIded() } } },
}), Is.False, "unset ids hold nothing");
Assert.That(CultElementIds.Holds(new HAll { Dict = { ["k"] = new HHasIds { Items = { new EIded { Id = id } } } } }), Is.True, "a dictionary value");
Assert.That(CultElementIds.Holds(new HAll { Grid = { new List<EIded> { new EIded { Id = id } } } }), Is.True, "a list of lists");
Assert.That(CultElementIds.Holds(new HAll { Nest = { new ENest { Sub = { new EIded { Id = id } } } } }), Is.True, "a list under an unset element");
Assert.That(CultElementIds.Holds(new HAll { Nest = { new ENest { Id = id } } }), Is.True, "an element");
}
[Test]
public void APlanCountsAndChangesNothingUntilApplied()
{