Skip to content

Commit

Permalink
Use Ascii transcoding APIs in more places in System.Net.Http (#93511)
Browse files Browse the repository at this point in the history
  • Loading branch information
MihaZupan authored Oct 14, 2023
1 parent 5233eea commit 3e0afa6
Show file tree
Hide file tree
Showing 3 changed files with 34 additions and 42 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

#nullable enable
using System.Buffers;
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
Expand Down Expand Up @@ -370,6 +371,8 @@ private static bool EncodeLiteralHeaderName(string value, Span<byte> destination
// | String Data (Length octets) |
// +-------------------------------+

Debug.Assert(Ascii.IsValid(value));

if (destination.Length != 0)
{
destination[0] = 0; // TODO: Use Huffman encoding
Expand All @@ -380,11 +383,9 @@ private static bool EncodeLiteralHeaderName(string value, Span<byte> destination
destination = destination.Slice(integerLength);
if (value.Length <= destination.Length)
{
for (int i = 0; i < value.Length; i++)
{
char c = value[i];
destination[i] = (byte)((uint)(c - 'A') <= ('Z' - 'A') ? c | 0x20 : c);
}
OperationStatus status = Ascii.ToLower(value, destination, out int valueBytesWritten);
Debug.Assert(status == OperationStatus.Done);
Debug.Assert(valueBytesWritten == value.Length);

bytesWritten = integerLength + value.Length;
return true;
Expand All @@ -400,16 +401,15 @@ private static void EncodeValueStringPart(string value, Span<byte> destination)
{
Debug.Assert(destination.Length >= value.Length);

for (int i = 0; i < value.Length; i++)
{
char c = value[i];
if ((c & 0xFF80) != 0)
{
throw new HttpRequestException(SR.net_http_request_invalid_char_encoding);
}
OperationStatus status = Ascii.FromUtf16(value, destination, out int bytesWritten);

destination[i] = (byte)c;
if (status == OperationStatus.InvalidData)
{
throw new HttpRequestException(SR.net_http_request_invalid_char_encoding);
}

Debug.Assert(status == OperationStatus.Done);
Debug.Assert(bytesWritten == value.Length);
}

public static bool EncodeStringLiteral(ReadOnlySpan<byte> value, Span<byte> destination, out int bytesWritten)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.

#nullable enable
using System.Buffers;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net.Http.HPack;
Expand Down Expand Up @@ -311,22 +312,20 @@ private static void EncodeValueStringPart(string s, Span<byte> buffer)
{
Debug.Assert(buffer.Length >= s.Length);

for (int i = 0; i < s.Length; ++i)
{
char ch = s[i];

if (ch > 127)
{
throw new QPackEncodingException(SR.net_http_request_invalid_char_encoding);
}
OperationStatus status = Ascii.FromUtf16(s, buffer, out int bytesWritten);

buffer[i] = (byte)ch;
if (status == OperationStatus.InvalidData)
{
throw new QPackEncodingException(SR.net_http_request_invalid_char_encoding);
}

Debug.Assert(status == OperationStatus.Done);
Debug.Assert(bytesWritten == s.Length);
}

private static bool EncodeNameString(string s, Span<byte> buffer, out int length)
{
const int toLowerMask = 0x20;
Debug.Assert(Ascii.IsValid(s));

if (buffer.Length != 0)
{
Expand All @@ -338,18 +337,9 @@ private static bool EncodeNameString(string s, Span<byte> buffer, out int length

if (buffer.Length >= s.Length)
{
for (int i = 0; i < s.Length; ++i)
{
int ch = s[i];
Debug.Assert(ch <= 127, "HttpHeaders prevents adding non-ASCII header names.");

if ((uint)(ch - 'A') <= 'Z' - 'A')
{
ch |= toLowerMask;
}

buffer[i] = (byte)ch;
}
OperationStatus status = Ascii.ToLower(s, buffer, out int valueBytesWritten);
Debug.Assert(status == OperationStatus.Done);
Debug.Assert(valueBytesWritten == s.Length);

length = nameLength + s.Length;
return true;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -473,15 +473,17 @@ private void WriteString(string s, Encoding? encoding)
{
_writeBuffer.EnsureAvailableSpace(s.Length);
Span<byte> buffer = _writeBuffer.AvailableSpan;
for (int i = 0; i < s.Length; i++)
OperationStatus status = Ascii.FromUtf16(s, buffer, out int bytesWritten);
if (status == OperationStatus.InvalidData)
{
char c = s[i];
if (!char.IsAscii(c))
{
ThrowForInvalidCharEncoding();
}
buffer[i] = (byte)c;
ThrowForInvalidCharEncoding();
}
Debug.Assert(status == OperationStatus.Done);
Debug.Assert(bytesWritten == s.Length);
_writeBuffer.Commit(s.Length);
}
else
Expand Down

0 comments on commit 3e0afa6

Please sign in to comment.