395 lines
14 KiB
C#
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];
|
|
}
|
|
}
|
|
}
|