Skip to content

Commit

Permalink
Start Url Encode implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
danielmarbach committed Apr 24, 2024
1 parent 815db56 commit 81d8586
Showing 1 changed file with 53 additions and 20 deletions.
73 changes: 53 additions & 20 deletions sdk/src/Core/Amazon.Util/AWSSDKUtils.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@

using Amazon.Runtime.Internal.Util;
using System;
using System.Buffers;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
Expand Down Expand Up @@ -1107,35 +1108,67 @@ public static string UrlEncode(string data, bool path)
/// Currently recognised RFC versions are 1738 (Dec '94) and 3986 (Jan '05).
/// If the specified RFC is not recognised, 3986 is used by default.
/// </remarks>
// TODO Add SkipsLocalsInit?
public static string UrlEncode(int rfcNumber, string data, bool path)
{
StringBuilder encoded = new StringBuilder(data.Length * 2);
string validUrlCharacters;
if (!RFCEncodingSchemes.TryGetValue(rfcNumber, out validUrlCharacters))
validUrlCharacters = ValidUrlCharacters;
byte[] sharedDataBuffer = null, sharedEncodedBuffer = null;
// Put this elsewhere?
const int MaxStackLimit = 256;
try
{
string validUrlCharacters;
if (!RFCEncodingSchemes.TryGetValue(rfcNumber, out validUrlCharacters))
validUrlCharacters = ValidUrlCharacters;

string unreservedChars = String.Concat(validUrlCharacters, (path ? ValidPathCharacters : ""));

var dataAsSpan = data.AsSpan();
var encoding = Encoding.UTF8;

var dataByteLength = encoding.GetMaxByteCount(dataAsSpan.Length);
var dataBuffer = dataByteLength <= MaxStackLimit
? stackalloc byte[MaxStackLimit]
: sharedDataBuffer = ArrayPool<byte>.Shared.Rent(dataByteLength);
var bytesWritten = encoding.GetBytes(dataAsSpan, dataBuffer);

var encodedByteLength = dataByteLength * dataByteLength;
var encodedBuffer = encodedByteLength <= MaxStackLimit
? stackalloc byte[MaxStackLimit]
: sharedEncodedBuffer = ArrayPool<byte>.Shared.Rent(encodedByteLength);
int index = 0;
foreach (byte symbol in dataBuffer.Slice(0, bytesWritten))
{
if (unreservedChars.IndexOf((char)symbol) != -1)
{
encodedBuffer[index++] = symbol;
}
else
{
encodedBuffer[index++] = (byte)'%';

// Break apart the byte into two four-bit components and
// then convert each into their hexadecimal equivalent.
int hiNibble = symbol >> 4;
int loNibble = symbol & 0xF;
encodedBuffer[index++] = (byte)ToUpperHex(hiNibble);
encodedBuffer[index++] = (byte)ToUpperHex(loNibble);
}
}

string unreservedChars = String.Concat(validUrlCharacters, (path ? ValidPathCharacters : ""));
foreach (char symbol in System.Text.Encoding.UTF8.GetBytes(data))
return encoding.GetString(encodedBuffer.Slice(index));
}
finally
{
if (unreservedChars.IndexOf(symbol) != -1)
if (sharedDataBuffer != null)
{
encoded.Append(symbol);
ArrayPool<byte>.Shared.Return(sharedDataBuffer);
}
else

if (sharedEncodedBuffer != null)
{
encoded.Append('%');

// Break apart the byte into two four-bit components and
// then convert each into their hexadecimal equivalent.
byte b = (byte)symbol;
int hiNibble = b >> 4;
int loNibble = b & 0xF;
encoded.Append(ToUpperHex(hiNibble));
encoded.Append(ToUpperHex(loNibble));
ArrayPool<byte>.Shared.Return(sharedEncodedBuffer);
}
}

return encoded.ToString();
}

private static char ToUpperHex(int value)
Expand Down

0 comments on commit 81d8586

Please sign in to comment.