Skip to content

Commit 7dc32d9

Browse files
author
ladeak
committed
With custom utf8 and hex encoding combined
1 parent 713f552 commit 7dc32d9

File tree

1 file changed

+40
-10
lines changed

1 file changed

+40
-10
lines changed

src/Http/Headers/src/ContentDispositionHeaderValue.cs

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -618,7 +618,6 @@ private static bool TryDecodeMime(StringSegment input, [NotNullWhen(true)] out s
618618
private static string Encode5987(StringSegment input)
619619
{
620620
var builder = new StringBuilder("UTF-8\'\'");
621-
Span<byte> utf8CharBuffer = stackalloc byte[4];
622621
var remaining = input.AsSpan();
623622
while (remaining.Length > 0)
624623
{
@@ -644,14 +643,9 @@ private static string Encode5987(StringSegment input)
644643
for (int i = 0; i < length;)
645644
{
646645
Rune.DecodeFromUtf16(remaining.Slice(i), out Rune rune, out var runeLength);
647-
int utf8Length = rune.EncodeToUtf8(utf8CharBuffer);
648-
for (int j = 0; j < utf8Length; j++)
649-
{
650-
var utf8Part = utf8CharBuffer[j];
651-
builder.Append(CultureInfo.InvariantCulture, $"%{HexUpperChars[(utf8Part & 0xf0) >> 4]}{HexUpperChars[utf8Part & 0xf]}");
652-
}
646+
EncodeToUtf8Hex(rune, builder);
653647
i += runeLength;
654-
}
648+
}
655649

656650
remaining = remaining.Slice(length);
657651
}
@@ -663,9 +657,45 @@ private static string Encode5987(StringSegment input)
663657
'0', '1', '2', '3', '4', '5', '6', '7',
664658
'8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };
665659

666-
private static void HexEscape(StringBuilder builder, byte b)
660+
private static void EncodeToUtf8Hex(Rune rune, StringBuilder builder)
667661
{
668-
builder.Append(CultureInfo.InvariantCulture, $"%{HexUpperChars[(b & 0xf0) >> 4]}{HexUpperChars[b & 0xf]}");
662+
// Inspired by https://source.dot.net/#System.Private.CoreLib/src/libraries/System.Private.CoreLib/src/System/Text/Rune.cs TryEncodeToUtf8
663+
var value = (uint)rune.Value;
664+
if (rune.IsAscii)
665+
{
666+
var byteValue = (byte)value;
667+
builder.Append(CultureInfo.InvariantCulture, $"%{HexUpperChars[(byteValue & 0xf0) >> 4]}{HexUpperChars[byteValue & 0xf]}");
668+
}
669+
else if (rune.Value <= 0x7FFu)
670+
{
671+
// Scalar 00000yyy yyxxxxxx -> bytes [ 110yyyyy 10xxxxxx ]
672+
var byteValue = (byte)((value + (0b110u << 11)) >> 6);
673+
builder.Append(CultureInfo.InvariantCulture, $"%{HexUpperChars[(byteValue & 0xf0) >> 4]}{HexUpperChars[byteValue & 0xf]}");
674+
byteValue = (byte)((value & 0x3Fu) + 0x80u);
675+
builder.Append(CultureInfo.InvariantCulture, $"%{HexUpperChars[(byteValue & 0xf0) >> 4]}{HexUpperChars[byteValue & 0xf]}");
676+
}
677+
else if (rune.Value <= 0xFFFFu)
678+
{
679+
// Scalar zzzzyyyy yyxxxxxx -> bytes [ 1110zzzz 10yyyyyy 10xxxxxx ]
680+
var byteValue = (byte)((value + (0b1110 << 16)) >> 12);
681+
builder.Append(CultureInfo.InvariantCulture, $"%{HexUpperChars[(byteValue & 0xf0) >> 4]}{HexUpperChars[byteValue & 0xf]}");
682+
byteValue = (byte)(((value & (0x3Fu << 6)) >> 6) + 0x80u);
683+
builder.Append(CultureInfo.InvariantCulture, $"%{HexUpperChars[(byteValue & 0xf0) >> 4]}{HexUpperChars[byteValue & 0xf]}");
684+
byteValue = (byte)((value & 0x3Fu) + 0x80u);
685+
builder.Append(CultureInfo.InvariantCulture, $"%{HexUpperChars[(byteValue & 0xf0) >> 4]}{HexUpperChars[byteValue & 0xf]}");
686+
}
687+
else
688+
{
689+
// Scalar 000uuuuu zzzzyyyy yyxxxxxx -> bytes [ 11110uuu 10uuzzzz 10yyyyyy 10xxxxxx ]
690+
var byteValue = (byte)((value + (0b11110 << 21)) >> 18);
691+
builder.Append(CultureInfo.InvariantCulture, $"%{HexUpperChars[(byteValue & 0xf0) >> 4]}{HexUpperChars[byteValue & 0xf]}");
692+
byteValue = (byte)(((value & (0x3Fu << 12)) >> 12) + 0x80u);
693+
builder.Append(CultureInfo.InvariantCulture, $"%{HexUpperChars[(byteValue & 0xf0) >> 4]}{HexUpperChars[byteValue & 0xf]}");
694+
byteValue = (byte)(((value & (0x3Fu << 6)) >> 6) + 0x80u);
695+
builder.Append(CultureInfo.InvariantCulture, $"%{HexUpperChars[(byteValue & 0xf0) >> 4]}{HexUpperChars[byteValue & 0xf]}");
696+
byteValue = (byte)((value & 0x3Fu) + 0x80u);
697+
builder.Append(CultureInfo.InvariantCulture, $"%{HexUpperChars[(byteValue & 0xf0) >> 4]}{HexUpperChars[byteValue & 0xf]}");
698+
}
669699
}
670700

671701
// Attempt to decode using RFC 5987 encoding.

0 commit comments

Comments
 (0)