<PackageReference Include="System.Text.Encodings.Web" Version="9.0.0-preview.4.24266.19" />

DefaultUrlEncoder

sealed class DefaultUrlEncoder : UrlEncoder
using System.Buffers; using System.Text.Unicode; namespace System.Text.Encodings.Web { internal sealed class DefaultUrlEncoder : UrlEncoder { private sealed class EscaperImplementation : ScalarEscaperBase { internal static readonly EscaperImplementation Singleton = new EscaperImplementation(); private EscaperImplementation() { } internal override int EncodeUtf8(System.Text.Rune value, Span<byte> destination) { uint utf8RepresentationForScalarValue = (uint)UnicodeHelpers.GetUtf8RepresentationForScalarValue((uint)value.Value); if (SpanUtility.IsValidIndex(destination, 2)) { destination[0] = 37; System.HexConverter.ToBytesBuffer((byte)utf8RepresentationForScalarValue, destination, 1, System.HexConverter.Casing.Upper); if ((utf8RepresentationForScalarValue >>= 8) == 0) return 3; if (SpanUtility.IsValidIndex(destination, 5)) { destination[3] = 37; System.HexConverter.ToBytesBuffer((byte)utf8RepresentationForScalarValue, destination, 4, System.HexConverter.Casing.Upper); if ((utf8RepresentationForScalarValue >>= 8) == 0) return 6; if (SpanUtility.IsValidIndex(destination, 8)) { destination[6] = 37; System.HexConverter.ToBytesBuffer((byte)utf8RepresentationForScalarValue, destination, 7, System.HexConverter.Casing.Upper); if ((utf8RepresentationForScalarValue >>= 8) == 0) return 9; if (SpanUtility.IsValidIndex(destination, 11)) { destination[9] = 37; System.HexConverter.ToBytesBuffer((byte)utf8RepresentationForScalarValue, destination, 10, System.HexConverter.Casing.Upper); return 12; } } } } return -1; } internal override int EncodeUtf16(System.Text.Rune value, Span<char> destination) { uint utf8RepresentationForScalarValue = (uint)UnicodeHelpers.GetUtf8RepresentationForScalarValue((uint)value.Value); if (SpanUtility.IsValidIndex(destination, 2)) { destination[0] = '%'; System.HexConverter.ToCharsBuffer((byte)utf8RepresentationForScalarValue, destination, 1, System.HexConverter.Casing.Upper); if ((utf8RepresentationForScalarValue >>= 8) == 0) return 3; if (SpanUtility.IsValidIndex(destination, 5)) { destination[3] = '%'; System.HexConverter.ToCharsBuffer((byte)utf8RepresentationForScalarValue, destination, 4, System.HexConverter.Casing.Upper); if ((utf8RepresentationForScalarValue >>= 8) == 0) return 6; if (SpanUtility.IsValidIndex(destination, 8)) { destination[6] = '%'; System.HexConverter.ToCharsBuffer((byte)utf8RepresentationForScalarValue, destination, 7, System.HexConverter.Casing.Upper); if ((utf8RepresentationForScalarValue >>= 8) == 0) return 9; if (SpanUtility.IsValidIndex(destination, 11)) { destination[9] = '%'; System.HexConverter.ToCharsBuffer((byte)utf8RepresentationForScalarValue, destination, 10, System.HexConverter.Casing.Upper); return 12; } } } } return -1; } } internal static readonly DefaultUrlEncoder BasicLatinSingleton = new DefaultUrlEncoder(new TextEncoderSettings(UnicodeRanges.BasicLatin)); private readonly OptimizedInboxTextEncoder _innerEncoder; public override int MaxOutputCharactersPerInputCharacter => 9; internal unsafe DefaultUrlEncoder(TextEncoderSettings settings) { if (settings == null) ThrowHelper.ThrowArgumentNullException(ExceptionArgument.settings); ScalarEscaperBase singleton = EscaperImplementation.Singleton; ref AllowedBmpCodePointsBitmap allowedCodePointsBitmap = ref settings.GetAllowedCodePointsBitmap(); byte* intPtr = stackalloc byte[62]; *(short*)intPtr = 32; *(short*)(intPtr + 2) = 35; *(short*)(intPtr + 2 * 2) = 37; *(short*)(intPtr + 3 * 2) = 47; *(short*)(intPtr + 4 * 2) = 58; *(short*)(intPtr + 5 * 2) = 61; *(short*)(intPtr + 6 * 2) = 63; *(short*)(intPtr + 7 * 2) = 91; *(short*)(intPtr + 8 * 2) = 92; *(short*)(intPtr + 9 * 2) = 93; *(short*)(intPtr + 10 * 2) = 94; *(short*)(intPtr + 11 * 2) = 96; *(short*)(intPtr + 12 * 2) = 123; *(short*)(intPtr + 13 * 2) = 124; *(short*)(intPtr + 14 * 2) = 125; *(short*)(intPtr + 15 * 2) = -16; *(short*)(intPtr + 16 * 2) = -15; *(short*)(intPtr + 17 * 2) = -14; *(short*)(intPtr + 18 * 2) = -13; *(short*)(intPtr + 19 * 2) = -12; *(short*)(intPtr + 20 * 2) = -11; *(short*)(intPtr + 21 * 2) = -10; *(short*)(intPtr + 22 * 2) = -9; *(short*)(intPtr + 23 * 2) = -8; *(short*)(intPtr + 24 * 2) = -7; *(short*)(intPtr + 25 * 2) = -6; *(short*)(intPtr + 26 * 2) = -5; *(short*)(intPtr + 27 * 2) = -4; *(short*)(intPtr + 28 * 2) = -3; *(short*)(intPtr + 29 * 2) = -2; *(short*)(intPtr + 30 * 2) = -1; Span<char> span = new Span<char>(intPtr, 31); _innerEncoder = new OptimizedInboxTextEncoder(singleton, ref allowedCodePointsBitmap, true, span); } private protected override OperationStatus EncodeCore(ReadOnlySpan<char> source, Span<char> destination, out int charsConsumed, out int charsWritten, bool isFinalBlock) { return _innerEncoder.Encode(source, destination, out charsConsumed, out charsWritten, isFinalBlock); } private protected override OperationStatus EncodeUtf8Core(ReadOnlySpan<byte> utf8Source, Span<byte> utf8Destination, out int bytesConsumed, out int bytesWritten, bool isFinalBlock) { return _innerEncoder.EncodeUtf8(utf8Source, utf8Destination, out bytesConsumed, out bytesWritten, isFinalBlock); } private protected override int FindFirstCharacterToEncode(ReadOnlySpan<char> text) { return _innerEncoder.GetIndexOfFirstCharToEncode(text); } public unsafe override int FindFirstCharacterToEncode(char* text, int textLength) { return _innerEncoder.FindFirstCharacterToEncode(text, textLength); } public override int FindFirstCharacterToEncodeUtf8(ReadOnlySpan<byte> utf8Text) { return _innerEncoder.GetIndexOfFirstByteToEncode(utf8Text); } public unsafe override bool TryEncodeUnicodeScalar(int unicodeScalar, char* buffer, int bufferLength, out int numberOfCharactersWritten) { return _innerEncoder.TryEncodeUnicodeScalar(unicodeScalar, buffer, bufferLength, out numberOfCharactersWritten); } public override bool WillEncode(int unicodeScalar) { return !_innerEncoder.IsScalarValueAllowed(new System.Text.Rune(unicodeScalar)); } } }