HexConverter
using System.Runtime.CompilerServices;
namespace System
{
internal static class HexConverter
{
public enum Casing : uint
{
Upper = 0,
Lower = 8224
}
private ref struct SpanCasingPair
{
public ReadOnlySpan<byte> Bytes {
[System.Runtime.CompilerServices.IsReadOnly]
get;
set;
}
public Casing Casing {
[System.Runtime.CompilerServices.IsReadOnly]
get;
set;
}
}
public unsafe static ReadOnlySpan<byte> CharToHexLookup => new ReadOnlySpan<byte>(&global::<PrivateImplementationDetails>.21244F82B210125632917591768F6BF22EB6861F80C6C25A25BD26DFB580EA7B, 256);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ToBytesBuffer(byte value, Span<byte> buffer, int startingIndex = 0, Casing casing = Casing.Upper)
{
uint num = (uint)(((value & 240) << 4) + (value & 15) - 35209);
uint num2 = (uint)((int)((((0 - num) & 28784) >> 4) + num + 47545) | (int)casing);
buffer[startingIndex + 1] = (byte)num2;
buffer[startingIndex] = (byte)(num2 >> 8);
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void ToCharsBuffer(byte value, Span<char> buffer, int startingIndex = 0, Casing casing = Casing.Upper)
{
uint num = (uint)(((value & 240) << 4) + (value & 15) - 35209);
uint num2 = (uint)((int)((((0 - num) & 28784) >> 4) + num + 47545) | (int)casing);
buffer[startingIndex + 1] = (char)(num2 & 255);
buffer[startingIndex] = (char)(num2 >> 8);
}
public static void EncodeToUtf8(ReadOnlySpan<byte> source, Span<byte> utf8Destination, Casing casing = Casing.Upper)
{
for (int i = 0; i < source.Length; i++) {
ToBytesBuffer(source[i], utf8Destination, i * 2, casing);
}
}
public static void EncodeToUtf16(ReadOnlySpan<byte> source, Span<char> destination, Casing casing = Casing.Upper)
{
for (int i = 0; i < source.Length; i++) {
ToCharsBuffer(source[i], destination, i * 2, casing);
}
}
public unsafe static string ToString(ReadOnlySpan<byte> bytes, Casing casing = Casing.Upper)
{
Span<char> span;
if (bytes.Length > 16)
span = new char[bytes.Length * 2].AsSpan();
else {
int num = bytes.Length * 2;
span = new Span<char>(stackalloc byte[(int)checked(unchecked((ulong)(uint)num) * 2)], num);
}
Span<char> buffer = span;
int num2 = 0;
ReadOnlySpan<byte> readOnlySpan = bytes;
for (int num = 0; num < readOnlySpan.Length; num++) {
ToCharsBuffer(readOnlySpan[num], buffer, num2, casing);
num2 += 2;
}
return buffer.ToString();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static char ToCharUpper(int value)
{
value &= 15;
value += 48;
if (value > 57)
value += 7;
return (char)value;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static char ToCharLower(int value)
{
value &= 15;
value += 48;
if (value > 57)
value += 39;
return (char)value;
}
public static bool TryDecodeFromUtf8(ReadOnlySpan<byte> utf8Source, Span<byte> destination, out int bytesProcessed)
{
return TryDecodeFromUtf8_Scalar(utf8Source, destination, out bytesProcessed);
}
public static bool TryDecodeFromUtf16(ReadOnlySpan<char> source, Span<byte> destination, out int charsProcessed)
{
return TryDecodeFromUtf16_Scalar(source, destination, out charsProcessed);
}
private static bool TryDecodeFromUtf8_Scalar(ReadOnlySpan<byte> utf8Source, Span<byte> destination, out int bytesProcessed)
{
int num = 0;
int num2 = 0;
int num3 = 0;
int num4 = 0;
while (num2 < destination.Length) {
num3 = FromChar(utf8Source[num + 1]);
num4 = FromChar(utf8Source[num]);
if ((num3 | num4) == 255)
break;
destination[num2++] = (byte)((num4 << 4) | num3);
num += 2;
}
if (num3 == 255)
num++;
bytesProcessed = num;
return (num3 | num4) != 255;
}
private static bool TryDecodeFromUtf16_Scalar(ReadOnlySpan<char> source, Span<byte> destination, out int charsProcessed)
{
int num = 0;
int num2 = 0;
int num3 = 0;
int num4 = 0;
while (num2 < destination.Length) {
num3 = FromChar(source[num + 1]);
num4 = FromChar(source[num]);
if ((num3 | num4) == 255)
break;
destination[num2++] = (byte)((num4 << 4) | num3);
num += 2;
}
if (num3 == 255)
num++;
charsProcessed = num;
return (num3 | num4) != 255;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int FromChar(int c)
{
ReadOnlySpan<byte> charToHexLookup = CharToHexLookup;
if (c < charToHexLookup.Length) {
charToHexLookup = CharToHexLookup;
return charToHexLookup[c];
}
return 255;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int FromUpperChar(int c)
{
if (c <= 71)
return CharToHexLookup[c];
return 255;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static int FromLowerChar(int c)
{
if ((uint)(c - 48) <= 9)
return c - 48;
if ((uint)(c - 97) <= 5)
return c - 97 + 10;
return 255;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsHexChar(int c)
{
if (IntPtr.Size == 8) {
ulong num = (uint)(c - 48);
long num2 = -17875860044349952 << (int)num;
ulong num3 = num - 64;
return (num2 & (long)num3) < 0;
}
return FromChar(c) != 255;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsHexUpperChar(int c)
{
if ((uint)(c - 48) > 9)
return (uint)(c - 65) <= 5;
return true;
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static bool IsHexLowerChar(int c)
{
if ((uint)(c - 48) > 9)
return (uint)(c - 97) <= 5;
return true;
}
}
}