refactor(battlenode): single-source MsgEnvelope envelope keys (§E)
Behavior-preserving; 231 BattleNode tests green. The envelope key set was encoded three times (ReservedEnvelopeKeys, the ToJson writes, the FromJson reads). Added a private nested MsgEnvelope.Keys with a const per key; the reserved set, writes, and reads now all draw from it, so a key added in one place but not another (letting a body key shadow an envelope field) can no longer happen. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -24,9 +24,25 @@ public sealed record MsgEnvelope(
|
||||
// EngineIoHandshake). Every wire key here is explicit via the manual ToJson layering below.
|
||||
private static readonly JsonSerializerOptions Options = WireJsonOptions.CamelCase;
|
||||
|
||||
/// <summary>The fixed envelope wire keys, single-sourced. <see cref="ReservedEnvelopeKeys"/>,
|
||||
/// the <see cref="ToJson"/> writes, and the <see cref="FromJson"/> reads all draw from here, so
|
||||
/// the three encodings can't drift — adding a key in one place but not another (which would let a
|
||||
/// body key silently shadow an envelope field) is no longer possible.</summary>
|
||||
private static class Keys
|
||||
{
|
||||
public const string Uri = "uri";
|
||||
public const string ViewerId = "viewerId";
|
||||
public const string Uuid = "uuid";
|
||||
public const string Bid = "bid";
|
||||
public const string Try = "try";
|
||||
public const string Cat = "cat";
|
||||
public const string PubSeq = "pubSeq";
|
||||
public const string PlaySeq = "playSeq";
|
||||
}
|
||||
|
||||
private static readonly HashSet<string> ReservedEnvelopeKeys = new()
|
||||
{
|
||||
"uri", "viewerId", "uuid", "bid", "try", "cat", "pubSeq", "playSeq",
|
||||
Keys.Uri, Keys.ViewerId, Keys.Uuid, Keys.Bid, Keys.Try, Keys.Cat, Keys.PubSeq, Keys.PlaySeq,
|
||||
};
|
||||
|
||||
public static string ToJson(MsgEnvelope env)
|
||||
@@ -37,14 +53,14 @@ public sealed record MsgEnvelope(
|
||||
// field processed before "uri" is wiped before Matching.StartBattleLoad reads
|
||||
// it back. The prod wire emits envelope keys first; we must too.
|
||||
var result = new JsonObject();
|
||||
result["uri"] = env.Uri.ToString();
|
||||
result["viewerId"] = env.ViewerId;
|
||||
result["uuid"] = env.Uuid;
|
||||
result["try"] = env.RetryAttempt;
|
||||
result["cat"] = (int)env.Cat;
|
||||
if (env.Bid is not null) result["bid"] = env.Bid;
|
||||
if (env.PubSeq.HasValue) result["pubSeq"] = env.PubSeq.Value;
|
||||
if (env.PlaySeq.HasValue) result["playSeq"] = env.PlaySeq.Value;
|
||||
result[Keys.Uri] = env.Uri.ToString();
|
||||
result[Keys.ViewerId] = env.ViewerId;
|
||||
result[Keys.Uuid] = env.Uuid;
|
||||
result[Keys.Try] = env.RetryAttempt;
|
||||
result[Keys.Cat] = (int)env.Cat;
|
||||
if (env.Bid is not null) result[Keys.Bid] = env.Bid;
|
||||
if (env.PubSeq.HasValue) result[Keys.PubSeq] = env.PubSeq.Value;
|
||||
if (env.PlaySeq.HasValue) result[Keys.PlaySeq] = env.PlaySeq.Value;
|
||||
|
||||
if (env.Body is RawBody raw)
|
||||
{
|
||||
@@ -118,14 +134,14 @@ public sealed record MsgEnvelope(
|
||||
using var doc = JsonDocument.Parse(json);
|
||||
var root = doc.RootElement;
|
||||
|
||||
var uri = Enum.Parse<NetworkBattleUri>(root.GetProperty("uri").GetString()!);
|
||||
var viewerId = root.GetProperty("viewerId").GetInt64();
|
||||
var uuid = root.GetProperty("uuid").GetString()!;
|
||||
var bid = root.TryGetProperty("bid", out var bidEl) ? bidEl.GetString() : null;
|
||||
var retryAttempt = root.TryGetProperty("try", out var tryEl) ? tryEl.GetInt32() : 0;
|
||||
var cat = root.TryGetProperty("cat", out var catEl) ? (EmitCategory)catEl.GetInt32() : EmitCategory.Battle;
|
||||
var pubSeq = root.TryGetProperty("pubSeq", out var psEl) ? psEl.GetInt64() : (long?)null;
|
||||
var playSeq = root.TryGetProperty("playSeq", out var plsEl) ? plsEl.GetInt64() : (long?)null;
|
||||
var uri = Enum.Parse<NetworkBattleUri>(root.GetProperty(Keys.Uri).GetString()!);
|
||||
var viewerId = root.GetProperty(Keys.ViewerId).GetInt64();
|
||||
var uuid = root.GetProperty(Keys.Uuid).GetString()!;
|
||||
var bid = root.TryGetProperty(Keys.Bid, out var bidEl) ? bidEl.GetString() : null;
|
||||
var retryAttempt = root.TryGetProperty(Keys.Try, out var tryEl) ? tryEl.GetInt32() : 0;
|
||||
var cat = root.TryGetProperty(Keys.Cat, out var catEl) ? (EmitCategory)catEl.GetInt32() : EmitCategory.Battle;
|
||||
var pubSeq = root.TryGetProperty(Keys.PubSeq, out var psEl) ? psEl.GetInt64() : (long?)null;
|
||||
var playSeq = root.TryGetProperty(Keys.PlaySeq, out var plsEl) ? plsEl.GetInt64() : (long?)null;
|
||||
|
||||
var bodyDict = new Dictionary<string, object?>();
|
||||
foreach (var prop in root.EnumerateObject())
|
||||
|
||||
Reference in New Issue
Block a user