ZK_Framework/Assets/Plugins/MessagePack/Internal/GuidBits.cs

395 lines
14 KiB
C#

// Copyright (c) All contributors. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
using System;
using System.Runtime.InteropServices;
namespace MessagePack.Internal
{
[StructLayout(LayoutKind.Explicit, Pack = 1)]
internal struct GuidBits
{
[FieldOffset(0)]
public readonly Guid Value;
[FieldOffset(0)]
public readonly byte Byte0;
[FieldOffset(1)]
public readonly byte Byte1;
[FieldOffset(2)]
public readonly byte Byte2;
[FieldOffset(3)]
public readonly byte Byte3;
[FieldOffset(4)]
public readonly byte Byte4;
[FieldOffset(5)]
public readonly byte Byte5;
[FieldOffset(6)]
public readonly byte Byte6;
[FieldOffset(7)]
public readonly byte Byte7;
[FieldOffset(8)]
public readonly byte Byte8;
[FieldOffset(9)]
public readonly byte Byte9;
[FieldOffset(10)]
public readonly byte Byte10;
[FieldOffset(11)]
public readonly byte Byte11;
[FieldOffset(12)]
public readonly byte Byte12;
[FieldOffset(13)]
public readonly byte Byte13;
[FieldOffset(14)]
public readonly byte Byte14;
[FieldOffset(15)]
public readonly byte Byte15;
// string.Join(", ", Enumerable.Range(0, 256).Select(x => (int)BitConverter.ToString(new byte[] { (byte)x }).ToLower()[0]))
private static ReadOnlySpan<byte> GetByteToHexStringHigh() => new byte[256] { 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 48, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 49, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 50, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 51, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 52, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 53, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 54, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 55, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 56, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 57, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 97, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 98, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 99, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 101, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102, 102 };
// string.Join(", ", Enumerable.Range(0, 256).Select(x => (int)BitConverter.ToString(new byte[] { (byte)x }).ToLower()[1]))
private static ReadOnlySpan<byte> GetByteToHexStringLow() => new byte[256] { 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 97, 98, 99, 100, 101, 102 };
public GuidBits(ref Guid value)
{
this = default(GuidBits);
this.Value = value;
}
// 4-pattern, lower/upper and '-' or no
public GuidBits(ReadOnlySpan<byte> utf8string)
{
this = default(GuidBits);
// 32
if (utf8string.Length == 32)
{
if (BitConverter.IsLittleEndian)
{
this.Byte0 = Parse(utf8string, 6);
this.Byte1 = Parse(utf8string, 4);
this.Byte2 = Parse(utf8string, 2);
this.Byte3 = Parse(utf8string, 0);
this.Byte4 = Parse(utf8string, 10);
this.Byte5 = Parse(utf8string, 8);
this.Byte6 = Parse(utf8string, 14);
this.Byte7 = Parse(utf8string, 12);
}
else
{
this.Byte0 = Parse(utf8string, 0);
this.Byte1 = Parse(utf8string, 2);
this.Byte2 = Parse(utf8string, 4);
this.Byte3 = Parse(utf8string, 6);
this.Byte4 = Parse(utf8string, 8);
this.Byte5 = Parse(utf8string, 10);
this.Byte6 = Parse(utf8string, 12);
this.Byte7 = Parse(utf8string, 14);
}
this.Byte8 = Parse(utf8string, 16);
this.Byte9 = Parse(utf8string, 18);
this.Byte10 = Parse(utf8string, 20);
this.Byte11 = Parse(utf8string, 22);
this.Byte12 = Parse(utf8string, 24);
this.Byte13 = Parse(utf8string, 26);
this.Byte14 = Parse(utf8string, 28);
this.Byte15 = Parse(utf8string, 30);
return;
}
else if (utf8string.Length == 36)
{
// '-' => 45
if (BitConverter.IsLittleEndian)
{
this.Byte0 = Parse(utf8string, 6);
this.Byte1 = Parse(utf8string, 4);
this.Byte2 = Parse(utf8string, 2);
this.Byte3 = Parse(utf8string, 0);
if (utf8string[8] != '-')
{
goto ERROR;
}
this.Byte4 = Parse(utf8string, 11);
this.Byte5 = Parse(utf8string, 9);
if (utf8string[13] != '-')
{
goto ERROR;
}
this.Byte6 = Parse(utf8string, 16);
this.Byte7 = Parse(utf8string, 14);
}
else
{
this.Byte0 = Parse(utf8string, 0);
this.Byte1 = Parse(utf8string, 2);
this.Byte2 = Parse(utf8string, 4);
this.Byte3 = Parse(utf8string, 6);
if (utf8string[8] != '-')
{
goto ERROR;
}
this.Byte4 = Parse(utf8string, 9);
this.Byte5 = Parse(utf8string, 11);
if (utf8string[13] != '-')
{
goto ERROR;
}
this.Byte6 = Parse(utf8string, 14);
this.Byte7 = Parse(utf8string, 16);
}
if (utf8string[18] != '-')
{
goto ERROR;
}
this.Byte8 = Parse(utf8string, 19);
this.Byte9 = Parse(utf8string, 21);
if (utf8string[23] != '-')
{
goto ERROR;
}
this.Byte10 = Parse(utf8string, 24);
this.Byte11 = Parse(utf8string, 26);
this.Byte12 = Parse(utf8string, 28);
this.Byte13 = Parse(utf8string, 30);
this.Byte14 = Parse(utf8string, 32);
this.Byte15 = Parse(utf8string, 34);
return;
}
ERROR:
throw new MessagePackSerializationException("Invalid Guid Pattern.");
}
#if !UNITY_2018_3_OR_NEWER
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
#endif
private static byte Parse(ReadOnlySpan<byte> bytes, int highOffset)
{
return unchecked((byte)((SwitchParse(bytes[highOffset]) * 16) + SwitchParse(bytes[highOffset + 1])));
}
#if !UNITY_2018_3_OR_NEWER
[System.Runtime.CompilerServices.MethodImpl(System.Runtime.CompilerServices.MethodImplOptions.AggressiveInlining)]
#endif
private static byte SwitchParse(byte b)
{
// '0'(48) ~ '9'(57) => -48
// 'A'(65) ~ 'F'(70) => -55
// 'a'(97) ~ 'f'(102) => -87
switch (b)
{
case 48:
case 49:
case 50:
case 51:
case 52:
case 53:
case 54:
case 55:
case 56:
case 57:
return unchecked((byte)(b - 48));
case 65:
case 66:
case 67:
case 68:
case 69:
case 70:
return unchecked((byte)(b - 55));
case 97:
case 98:
case 99:
case 100:
case 101:
case 102:
return unchecked((byte)(b - 87));
case 0:
case 1:
case 2:
case 3:
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 10:
case 11:
case 12:
case 13:
case 14:
case 15:
case 16:
case 17:
case 18:
case 19:
case 20:
case 21:
case 22:
case 23:
case 24:
case 25:
case 26:
case 27:
case 28:
case 29:
case 30:
case 31:
case 32:
case 33:
case 34:
case 35:
case 36:
case 37:
case 38:
case 39:
case 40:
case 41:
case 42:
case 43:
case 44:
case 45:
case 46:
case 47:
case 58:
case 59:
case 60:
case 61:
case 62:
case 63:
case 64:
case 71:
case 72:
case 73:
case 74:
case 75:
case 76:
case 77:
case 78:
case 79:
case 80:
case 81:
case 82:
case 83:
case 84:
case 85:
case 86:
case 87:
case 88:
case 89:
case 90:
case 91:
case 92:
case 93:
case 94:
case 95:
case 96:
default:
throw new MessagePackSerializationException("Invalid Guid Pattern.");
}
}
// 4(x2) - 2(x2) - 2(x2) - 2(x2) - 6(x2)
public void Write(Span<byte> buffer)
{
var high = GetByteToHexStringHigh();
var low = GetByteToHexStringLow();
if (BitConverter.IsLittleEndian)
{
// int(_a)
buffer[6] = high[this.Byte0];
buffer[7] = low[this.Byte0];
buffer[4] = high[this.Byte1];
buffer[5] = low[this.Byte1];
buffer[2] = high[this.Byte2];
buffer[3] = low[this.Byte2];
buffer[0] = high[this.Byte3];
buffer[1] = low[this.Byte3];
buffer[8] = (byte)'-';
// short(_b)
buffer[11] = high[this.Byte4];
buffer[12] = low[this.Byte4];
buffer[9] = high[this.Byte5];
buffer[10] = low[this.Byte5];
buffer[13] = (byte)'-';
// short(_c)
buffer[16] = high[this.Byte6];
buffer[17] = low[this.Byte6];
buffer[14] = high[this.Byte7];
buffer[15] = low[this.Byte7];
}
else
{
buffer[0] = high[this.Byte0];
buffer[1] = low[this.Byte0];
buffer[2] = high[this.Byte1];
buffer[3] = low[this.Byte1];
buffer[4] = high[this.Byte2];
buffer[5] = low[this.Byte2];
buffer[6] = high[this.Byte3];
buffer[7] = low[this.Byte3];
buffer[8] = (byte)'-';
buffer[9] = high[this.Byte4];
buffer[10] = low[this.Byte4];
buffer[11] = high[this.Byte5];
buffer[12] = low[this.Byte5];
buffer[13] = (byte)'-';
buffer[14] = high[this.Byte6];
buffer[15] = low[this.Byte6];
buffer[16] = high[this.Byte7];
buffer[17] = low[this.Byte7];
}
buffer[18] = (byte)'-';
buffer[19] = high[this.Byte8];
buffer[20] = low[this.Byte8];
buffer[21] = high[this.Byte9];
buffer[22] = low[this.Byte9];
buffer[23] = (byte)'-';
buffer[24] = high[this.Byte10];
buffer[25] = low[this.Byte10];
buffer[26] = high[this.Byte11];
buffer[27] = low[this.Byte11];
buffer[28] = high[this.Byte12];
buffer[29] = low[this.Byte12];
buffer[30] = high[this.Byte13];
buffer[31] = low[this.Byte13];
buffer[32] = high[this.Byte14];
buffer[33] = low[this.Byte14];
buffer[34] = high[this.Byte15];
buffer[35] = low[this.Byte15];
}
}
}