-
Notifications
You must be signed in to change notification settings - Fork 79
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
63a4966
commit 8777158
Showing
5 changed files
with
402 additions
and
43 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,34 +1,64 @@ | ||
namespace MassTransit.NewIdFormatters | ||
{ | ||
using System.Diagnostics; | ||
using System.Runtime.CompilerServices; | ||
#if NET6_0_OR_GREATER | ||
using System; | ||
using System.Runtime.InteropServices; | ||
using System.Runtime.Intrinsics; | ||
using System.Runtime.Intrinsics.X86; | ||
#endif | ||
|
||
|
||
public class HexFormatter : | ||
INewIdFormatter | ||
{ | ||
readonly int _alpha; | ||
readonly uint _alpha; | ||
const uint LowerCaseUInt = 0x2020U; | ||
|
||
public HexFormatter(bool upperCase = false) | ||
{ | ||
_alpha = upperCase ? 'A' : 'a'; | ||
_alpha = upperCase ? 0 : LowerCaseUInt; | ||
} | ||
|
||
public string Format(in byte[] bytes) | ||
public unsafe string Format(in byte[] bytes) | ||
{ | ||
var result = new char[32]; | ||
Debug.Assert(bytes.Length == 16); | ||
|
||
#if NET6_0_OR_GREATER | ||
if (Avx2.IsSupported && BitConverter.IsLittleEndian) | ||
{ | ||
var isUpperCase = _alpha != LowerCaseUInt; | ||
return string.Create(32, (bytes, isUpperCase), (span, state) => | ||
{ | ||
var (bytes, isUpper) = state; | ||
|
||
var offset = 0; | ||
for (var i = 0; i < 16; i++) | ||
var inputVec = MemoryMarshal.Read<Vector128<byte>>(bytes); | ||
var hexVec = IntrinsicsHelper.EncodeBytesHex(inputVec, isUpper); | ||
|
||
var byteSpan = MemoryMarshal.Cast<char, byte>(span); | ||
IntrinsicsHelper.Vector256ToCharUtf16(hexVec, byteSpan); | ||
}); | ||
} | ||
#endif | ||
var result = stackalloc char[32]; | ||
|
||
for (int pos = 0; pos < bytes.Length; pos++) | ||
{ | ||
var value = bytes[i]; | ||
result[offset++] = HexToChar(value >> 4, _alpha); | ||
result[offset++] = HexToChar(value, _alpha); | ||
HexToChar(bytes[pos], result, pos * 2, _alpha); | ||
} | ||
|
||
return new string(result, 0, 32); | ||
} | ||
|
||
static char HexToChar(int value, int alpha) | ||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | ||
static unsafe void HexToChar(byte value, char* buffer, int startingIndex, uint casing) | ||
{ | ||
value &= 0xf; | ||
return (char)(value > 9 ? value - 10 + alpha : value + 0x30); | ||
uint difference = (((uint)value & 0xF0U) << 4) + ((uint)value & 0x0FU) - 0x8989U; | ||
uint packedResult = ((((uint)(-(int)difference) & 0x7070U) >> 4) + difference + 0xB9B9U) | (uint)casing; | ||
|
||
buffer[startingIndex + 1] = (char)(packedResult & 0xFF); | ||
buffer[startingIndex] = (char)(packedResult >> 8); | ||
} | ||
} | ||
} |
Oops, something went wrong.