Skip to content

Commit

Permalink
Refactor writing QPACK status (#62069)
Browse files Browse the repository at this point in the history
Co-authored-by: JamesNK <JamesNK@users.noreply.github.com>
  • Loading branch information
github-actions[bot] and JamesNK committed Nov 26, 2021
1 parent 15649df commit 574b2d4
Show file tree
Hide file tree
Showing 3 changed files with 52 additions and 48 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@ internal static partial class H2StaticTable

public static ref readonly HeaderField Get(int index) => ref s_staticDecoderTable[index];

public static int GetStatusIndex(int status) =>
status switch
public static bool TryGetStatusIndex(int status, out int index)
{
index = status switch
{
200 => 8,
204 => 9,
Expand All @@ -21,9 +22,12 @@ public static int GetStatusIndex(int status) =>
400 => 12,
404 => 13,
500 => 14,
_ => throw new ArgumentOutOfRangeException(nameof(status))
_ => -1
};

return index != -1;
}

private static readonly HeaderField[] s_staticDecoderTable = new HeaderField[]
{
CreateHeaderField(":authority", ""),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,36 +44,31 @@ public static bool EncodeIndexedHeaderField(int index, Span<byte> destination, o
public static bool EncodeStatusHeader(int statusCode, Span<byte> destination, out int bytesWritten)
{
// Bytes written depend on whether the status code value maps directly to an index
switch (statusCode)
if (H2StaticTable.TryGetStatusIndex(statusCode, out var index))
{
case 200:
case 204:
case 206:
case 304:
case 400:
case 404:
case 500:
// Status codes which exist in the HTTP/2 StaticTable.
return EncodeIndexedHeaderField(H2StaticTable.GetStatusIndex(statusCode), destination, out bytesWritten);
default:
// If the status code doesn't have a static index then we need to include the full value.
// Write a status index and then the number bytes as a string literal.
if (!EncodeLiteralHeaderFieldWithoutIndexing(H2StaticTable.Status200, destination, out var nameLength))
{
bytesWritten = 0;
return false;
}
// Status codes which exist in the HTTP/2 StaticTable.
return EncodeIndexedHeaderField(index, destination, out bytesWritten);
}
else
{
// If the status code doesn't have a static index then we need to include the full value.
// Write a status index and then the number bytes as a string literal.
if (!EncodeLiteralHeaderFieldWithoutIndexing(H2StaticTable.Status200, destination, out var nameLength))
{
bytesWritten = 0;
return false;
}

var statusBytes = StatusCodes.ToStatusBytes(statusCode);
var statusBytes = StatusCodes.ToStatusBytes(statusCode);

if (!EncodeStringLiteral(statusBytes, destination.Slice(nameLength), out var valueLength))
{
bytesWritten = 0;
return false;
}
if (!EncodeStringLiteral(statusBytes, destination.Slice(nameLength), out var valueLength))
{
bytesWritten = 0;
return false;
}

bytesWritten = nameLength + valueLength;
return true;
bytesWritten = nameLength + valueLength;
return true;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,24 +8,6 @@ namespace System.Net.Http.QPack
{
internal static partial class H3StaticTable
{
private static readonly Dictionary<int, int> s_statusIndex = new Dictionary<int, int>
{
[103] = 24,
[200] = 25,
[304] = 26,
[404] = 27,
[503] = 28,
[100] = 63,
[204] = 64,
[206] = 65,
[302] = 66,
[400] = 67,
[403] = 68,
[421] = 69,
[425] = 70,
[500] = 71,
};

private static readonly Dictionary<HttpMethod, int> s_methodIndex = new Dictionary<HttpMethod, int>
{
// TODO connect is internal to system.net.http
Expand All @@ -37,10 +19,33 @@ internal static partial class H3StaticTable
[HttpMethod.Put] = 21,
};

public static bool TryGetStatusIndex(int status, out int index)
{
index = status switch
{
103 => 24,
200 => 25,
304 => 26,
404 => 27,
503 => 28,
100 => 63,
204 => 64,
206 => 65,
302 => 66,
400 => 67,
403 => 68,
421 => 69,
425 => 70,
500 => 71,
_ => -1
};

return index != -1;
}

public static int Count => s_staticTable.Length;

// TODO: just use Dictionary directly to avoid interface dispatch.
public static IReadOnlyDictionary<int, int> StatusIndex => s_statusIndex;
public static IReadOnlyDictionary<HttpMethod, int> MethodIndex => s_methodIndex;

public static HeaderField GetHeaderFieldAt(int index) => s_staticTable[index];
Expand Down

0 comments on commit 574b2d4

Please sign in to comment.