feat(batch24): complete leaf nodes implementation and verification
This commit is contained in:
@@ -1064,18 +1064,130 @@ public static class ProtocolParser
|
||||
// =====================================================================
|
||||
|
||||
/// <summary>
|
||||
/// Parses leaf MSG arguments. Same format as routed MSG args.
|
||||
/// Stub — will be fully implemented with leaf node support.
|
||||
/// Parses leaf MSG arguments:
|
||||
/// <c>subject size</c>,
|
||||
/// <c>subject reply size</c>,
|
||||
/// <c>subject + reply queues... size</c>,
|
||||
/// <c>subject | queues... size</c>.
|
||||
/// Mirrors Go <c>client.processLeafMsgArgs</c>.
|
||||
/// </summary>
|
||||
public static Exception? ProcessLeafMsgArgs(ParseContext c, byte[] arg) =>
|
||||
ProcessRoutedMsgArgs(c, arg);
|
||||
public static Exception? ProcessLeafMsgArgs(ParseContext c, byte[] arg)
|
||||
{
|
||||
var routedErr = ProcessRoutedMsgArgs(c, arg);
|
||||
if (routedErr is null)
|
||||
return null;
|
||||
|
||||
var tokens = SplitArgs(arg);
|
||||
if (tokens.Count < 2)
|
||||
return new InvalidOperationException($"processLeafMsgArgs Parse Error: '{Encoding.ASCII.GetString(arg)}'");
|
||||
|
||||
c.Pa.Account = null;
|
||||
c.Pa.Subject = tokens[0];
|
||||
c.Pa.Arg = arg;
|
||||
c.Pa.Queues = null;
|
||||
|
||||
if (tokens.Count == 2)
|
||||
{
|
||||
c.Pa.Reply = null;
|
||||
c.Pa.SizeBytes = tokens[1];
|
||||
if (!TryParseSize(tokens[1], out var size))
|
||||
return new InvalidOperationException($"processLeafMsgArgs Bad or Missing Size: '{Encoding.ASCII.GetString(arg)}'");
|
||||
c.Pa.Size = size;
|
||||
return null;
|
||||
}
|
||||
|
||||
if (tokens.Count == 3)
|
||||
{
|
||||
c.Pa.Reply = tokens[1];
|
||||
c.Pa.SizeBytes = tokens[2];
|
||||
if (!TryParseSize(tokens[2], out var size))
|
||||
return new InvalidOperationException($"processLeafMsgArgs Bad or Missing Size: '{Encoding.ASCII.GetString(arg)}'");
|
||||
c.Pa.Size = size;
|
||||
return null;
|
||||
}
|
||||
|
||||
if (tokens[1].Length != 1 || (tokens[1][0] != (byte)'+' && tokens[1][0] != (byte)'|'))
|
||||
return new InvalidOperationException($"processLeafMsgArgs Bad or Missing Reply Indicator: '{Encoding.ASCII.GetString(tokens[1])}'");
|
||||
|
||||
c.Pa.Reply = tokens[1][0] == (byte)'+' ? tokens[2] : null;
|
||||
c.Pa.SizeBytes = tokens[^1];
|
||||
if (!TryParseSize(tokens[^1], out var msgSize))
|
||||
return new InvalidOperationException($"processLeafMsgArgs Bad or Missing Size: '{Encoding.ASCII.GetString(arg)}'");
|
||||
c.Pa.Size = msgSize;
|
||||
|
||||
c.Pa.Queues = [];
|
||||
var queueStart = c.Pa.Reply is null ? 2 : 3;
|
||||
for (var i = queueStart; i < tokens.Count - 1; i++)
|
||||
c.Pa.Queues.Add(tokens[i]);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses leaf HMSG arguments. Same format as routed header MSG args.
|
||||
/// Stub — will be fully implemented with leaf node support.
|
||||
/// Parses leaf HMSG arguments:
|
||||
/// <c>subject hdr_size total_size</c>,
|
||||
/// <c>subject reply hdr_size total_size</c>,
|
||||
/// <c>subject + reply queues... hdr_size total_size</c>,
|
||||
/// <c>subject | queues... hdr_size total_size</c>.
|
||||
/// Mirrors Go <c>client.processLeafHeaderMsgArgs</c>.
|
||||
/// </summary>
|
||||
public static Exception? ProcessLeafHeaderMsgArgs(ParseContext c, byte[] arg) =>
|
||||
ProcessRoutedHeaderMsgArgs(c, arg);
|
||||
public static Exception? ProcessLeafHeaderMsgArgs(ParseContext c, byte[] arg)
|
||||
{
|
||||
var routedErr = ProcessRoutedHeaderMsgArgs(c, arg);
|
||||
if (routedErr is null)
|
||||
return null;
|
||||
|
||||
var tokens = SplitArgs(arg);
|
||||
if (tokens.Count < 3)
|
||||
return new InvalidOperationException($"processLeafHeaderMsgArgs Parse Error: '{Encoding.ASCII.GetString(arg)}'");
|
||||
|
||||
c.Pa.Account = null;
|
||||
c.Pa.Subject = tokens[0];
|
||||
c.Pa.Arg = arg;
|
||||
c.Pa.Queues = null;
|
||||
|
||||
if (tokens.Count == 3)
|
||||
{
|
||||
c.Pa.Reply = null;
|
||||
if (!TryParseSize(tokens[1], out var hdr) || !TryParseSize(tokens[2], out var size))
|
||||
return new InvalidOperationException($"processLeafHeaderMsgArgs Bad sizes: '{Encoding.ASCII.GetString(arg)}'");
|
||||
if (hdr > size) return ServerErrors.ErrBadMsgHeader;
|
||||
c.Pa.HeaderSize = hdr;
|
||||
c.Pa.SizeBytes = tokens[2];
|
||||
c.Pa.Size = size;
|
||||
return null;
|
||||
}
|
||||
|
||||
if (tokens.Count == 4)
|
||||
{
|
||||
c.Pa.Reply = tokens[1];
|
||||
if (!TryParseSize(tokens[2], out var hdr) || !TryParseSize(tokens[3], out var size))
|
||||
return new InvalidOperationException($"processLeafHeaderMsgArgs Bad sizes: '{Encoding.ASCII.GetString(arg)}'");
|
||||
if (hdr > size) return ServerErrors.ErrBadMsgHeader;
|
||||
c.Pa.HeaderSize = hdr;
|
||||
c.Pa.SizeBytes = tokens[3];
|
||||
c.Pa.Size = size;
|
||||
return null;
|
||||
}
|
||||
|
||||
if (tokens[1].Length != 1 || (tokens[1][0] != (byte)'+' && tokens[1][0] != (byte)'|'))
|
||||
return new InvalidOperationException($"processLeafHeaderMsgArgs Bad or Missing Reply Indicator: '{Encoding.ASCII.GetString(tokens[1])}'");
|
||||
|
||||
c.Pa.Reply = tokens[1][0] == (byte)'+' ? tokens[2] : null;
|
||||
if (!TryParseSize(tokens[^2], out var hdrSize) || !TryParseSize(tokens[^1], out var totalSize))
|
||||
return new InvalidOperationException($"processLeafHeaderMsgArgs Bad sizes: '{Encoding.ASCII.GetString(arg)}'");
|
||||
if (hdrSize > totalSize) return ServerErrors.ErrBadMsgHeader;
|
||||
c.Pa.HeaderSize = hdrSize;
|
||||
c.Pa.SizeBytes = tokens[^1];
|
||||
c.Pa.Size = totalSize;
|
||||
|
||||
c.Pa.Queues = [];
|
||||
var queueStart = c.Pa.Reply is null ? 2 : 3;
|
||||
for (var i = queueStart; i < tokens.Count - 2; i++)
|
||||
c.Pa.Queues.Add(tokens[i]);
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parses LMSG arguments (origin cluster routed messages).
|
||||
|
||||
Reference in New Issue
Block a user