This commit is contained in:
@@ -2,15 +2,32 @@ namespace Just.Core.Tests.GuidV8Tests;
|
|||||||
|
|
||||||
public class NewGuid
|
public class NewGuid
|
||||||
{
|
{
|
||||||
|
[Theory]
|
||||||
|
[InlineData(RngEntropy.Weak)]
|
||||||
|
[InlineData(RngEntropy.Strong)]
|
||||||
|
public void Version_And_Variant_Should_Be_Correct(RngEntropy entropy)
|
||||||
|
{
|
||||||
|
var rng = new Random(25);
|
||||||
|
var referenceTime = new DateTime(2020, 05, 17, 15, 36, 13, 771, DateTimeKind.Utc);
|
||||||
|
|
||||||
|
for (int i = 0; i < 2000; i++)
|
||||||
|
{
|
||||||
|
var timestamp = referenceTime.AddSeconds(rng.Next());
|
||||||
|
var result = GuidV8.NewGuid(timestamp, entropy);
|
||||||
|
result.Version.Should().Be(8);
|
||||||
|
(result.Variant & 0b1100).Should().Be(0b1000);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData(RngEntropy.Weak,
|
[InlineData(RngEntropy.Weak,
|
||||||
-25000000, -10000000, -5000000, -2000000, -1000000, -500000, -250000, -100000, -25000, -10000, -5000,
|
-25000000, -20000000, -10000000, -5000000, -2000000, -1000000, -500000, -250000, -100000, -25000, -10000, -5000,
|
||||||
-2500, -1000, -500, -499, -497, -450, -300, -200, -50, -1, 0, 1, 2, 5, 10, 20, 50, 100, 200, 350, 500, 1000,
|
-2500, -1000, -500, -499, -497, -450, -300, -200, -50, -1, 0, 1, 2, 5, 10, 20, 50, 100, 200, 350, 500, 1000,
|
||||||
2500, 5000, 10000, 25000, 100000, 250000, 500000, 1000000, 2000000, 5000000, 10000000, 100000000, 250000000)]
|
2500, 5000, 10000, 25000, 100000, 250000, 500000, 1000000, 2000000, 5000000, 10000000, 20000000, 50000000, 100000000)]
|
||||||
[InlineData(RngEntropy.Strong,
|
[InlineData(RngEntropy.Strong,
|
||||||
-25000000, -10000000, -5000000, -2000000, -1000000, -500000, -250000, -100000, -25000, -10000, -5000,
|
-25000000, -20000000, -10000000, -5000000, -2000000, -1000000, -500000, -250000, -100000, -25000, -10000, -5000,
|
||||||
-2500, -1000, -500, -499, -497, -450, -300, -200, -50, -1, 0, 1, 2, 5, 10, 20, 50, 100, 200, 350, 500, 1000,
|
-2500, -1000, -500, -499, -497, -450, -300, -200, -50, -1, 0, 1, 2, 5, 10, 20, 50, 100, 200, 350, 500, 1000,
|
||||||
2500, 5000, 10000, 25000, 100000, 250000, 500000, 1000000, 2000000, 5000000, 10000000, 100000000, 250000000)]
|
2500, 5000, 10000, 25000, 100000, 250000, 500000, 1000000, 2000000, 5000000, 10000000, 20000000, 50000000, 100000000)]
|
||||||
[InlineData(RngEntropy.Weak,
|
[InlineData(RngEntropy.Weak,
|
||||||
-9863, -9740, -9214, -8878, -8674, -8652, -8640, -8565, -8518, -8449,
|
-9863, -9740, -9214, -8878, -8674, -8652, -8640, -8565, -8518, -8449,
|
||||||
-8390, -8193, -8108, -7808, -7501, -7203, -7133, -7020, -6983, -6855,
|
-8390, -8193, -8108, -7808, -7501, -7203, -7133, -7020, -6983, -6855,
|
||||||
@@ -34,27 +51,27 @@ public class NewGuid
|
|||||||
6128, 6277, 6323, 6437, 6699, 6853, 7556, 7776, 7795, 8099,
|
6128, 6277, 6323, 6437, 6699, 6853, 7556, 7776, 7795, 8099,
|
||||||
8336, 8592, 8682, 8683, 8818, 8904, 9375, 9466, 9551, 9708)]
|
8336, 8592, 8682, 8683, 8818, 8904, 9375, 9466, 9551, 9708)]
|
||||||
[InlineData(RngEntropy.Weak,
|
[InlineData(RngEntropy.Weak,
|
||||||
5635912, 6673780, 17277183, 17512959, 19098799, 21672621, 30581958, 30824885, 31874213, 35192781,
|
10024, 28660, 289641, 356015, 443164, 478759, 599586, 705860, 791271, 876512,
|
||||||
36337094, 37752116, 38387215, 39154682, 40525427, 52288093, 55218356, 59065156, 65231785, 75430932,
|
884503, 894899, 898584, 980136, 1007927, 1680328, 1690193, 1804615, 1847117, 2005534,
|
||||||
76289058, 79078058, 85770685, 85925884, 94726743, 94864163, 95781967, 96150006, 96482085, 102570414,
|
2106684, 2111936, 2252935, 2271396, 2298685, 2385409, 2414094, 2451706, 2549138, 2605538,
|
||||||
107768232, 110571078, 110680108, 117974892, 119800380, 126381415, 135895862, 140034471, 149039187, 150906974,
|
2864629, 2923476, 3004288, 3182875, 3266693, 3379019, 3542110, 3851467, 3871420, 4035463,
|
||||||
156853001, 160514433, 166446323, 170148965, 171759448, 176494242, 184537553, 188558155, 197194403, 197615804,
|
4316004, 4726381, 4814068, 4902666, 4979292, 4993443, 5117765, 5240585, 5249671, 5319528,
|
||||||
201195323, 202294490, 203040975, 203331457, 205016944, 213460258, 217072025, 217185345, 231344025, 232390198,
|
5387595, 5434544, 5504506, 5531264, 5546173, 5780381, 5889341, 6066328, 6167883, 6185073,
|
||||||
235053215, 240175073, 245030721, 252275255, 252310334, 277070940, 277359970, 280624756, 288601124, 292427106,
|
6299021, 6412136, 6621498, 6666562, 6741169, 6870279, 6949855, 6965427, 7153467, 7184150,
|
||||||
292563035, 299285016, 303834917, 310357836, 315078337, 316367236, 318311758, 318873972, 319675272, 321784171,
|
7300456, 7311381, 7413697, 7505235, 7802811, 7979134, 8053665, 8177676, 8260284, 8260773,
|
||||||
324204294, 327667283, 330287252, 338438172, 349863360, 360777768, 366398711, 368637150, 368776734, 371900343,
|
8269944, 8406526, 8442932, 8475162, 8555250, 8853347, 8861733, 8892200, 9069869, 9117839,
|
||||||
379094084, 379818879, 381448333, 381814627, 382393101, 382483709, 385600870, 389455134, 396115960, 399364095)]
|
9225445, 9245837, 9378644, 9497874, 9553625, 9650968, 9704053, 9713592, 9715054, 9735988)]
|
||||||
[InlineData(RngEntropy.Strong,
|
[InlineData(RngEntropy.Strong,
|
||||||
5635912, 6673780, 17277183, 17512959, 19098799, 21672621, 30581958, 30824885, 31874213, 35192781,
|
10024, 28660, 289641, 356015, 443164, 478759, 599586, 705860, 791271, 876512,
|
||||||
36337094, 37752116, 38387215, 39154682, 40525427, 52288093, 55218356, 59065156, 65231785, 75430932,
|
884503, 894899, 898584, 980136, 1007927, 1680328, 1690193, 1804615, 1847117, 2005534,
|
||||||
76289058, 79078058, 85770685, 85925884, 94726743, 94864163, 95781967, 96150006, 96482085, 102570414,
|
2106684, 2111936, 2252935, 2271396, 2298685, 2385409, 2414094, 2451706, 2549138, 2605538,
|
||||||
107768232, 110571078, 110680108, 117974892, 119800380, 126381415, 135895862, 140034471, 149039187, 150906974,
|
2864629, 2923476, 3004288, 3182875, 3266693, 3379019, 3542110, 3851467, 3871420, 4035463,
|
||||||
156853001, 160514433, 166446323, 170148965, 171759448, 176494242, 184537553, 188558155, 197194403, 197615804,
|
4316004, 4726381, 4814068, 4902666, 4979292, 4993443, 5117765, 5240585, 5249671, 5319528,
|
||||||
201195323, 202294490, 203040975, 203331457, 205016944, 213460258, 217072025, 217185345, 231344025, 232390198,
|
5387595, 5434544, 5504506, 5531264, 5546173, 5780381, 5889341, 6066328, 6167883, 6185073,
|
||||||
235053215, 240175073, 245030721, 252275255, 252310334, 277070940, 277359970, 280624756, 288601124, 292427106,
|
6299021, 6412136, 6621498, 6666562, 6741169, 6870279, 6949855, 6965427, 7153467, 7184150,
|
||||||
292563035, 299285016, 303834917, 310357836, 315078337, 316367236, 318311758, 318873972, 319675272, 321784171,
|
7300456, 7311381, 7413697, 7505235, 7802811, 7979134, 8053665, 8177676, 8260284, 8260773,
|
||||||
324204294, 327667283, 330287252, 338438172, 349863360, 360777768, 366398711, 368637150, 368776734, 371900343,
|
8269944, 8406526, 8442932, 8475162, 8555250, 8853347, 8861733, 8892200, 9069869, 9117839,
|
||||||
379094084, 379818879, 381448333, 381814627, 382393101, 382483709, 385600870, 389455134, 396115960, 399364095)]
|
9225445, 9245837, 9378644, 9497874, 9553625, 9650968, 9704053, 9713592, 9715054, 9735988)]
|
||||||
public void Guids_Differing_By_Minutes_Should_Be_Sortable(RngEntropy entropy, params int[] seconds)
|
public void Guids_Differing_By_Minutes_Should_Be_Sortable(RngEntropy entropy, params int[] seconds)
|
||||||
{
|
{
|
||||||
var rng = new Random(25);
|
var rng = new Random(25);
|
||||||
@@ -78,13 +95,13 @@ public class NewGuid
|
|||||||
|
|
||||||
[Theory]
|
[Theory]
|
||||||
[InlineData(RngEntropy.Weak,
|
[InlineData(RngEntropy.Weak,
|
||||||
-250000000, -25000000, -10000000, -5000000, -2000000, -1000000, -500000, -250000, -100000, -25000, -10000, -5000,
|
-100000000, -25000000, -10000000, -5000000, -2000000, -1000000, -500000, -250000, -100000, -25000, -10000, -5000,
|
||||||
-2500, -1000, -500, -499, -497, -450, -300, -200, -50, -1, 0, 1, 2, 5, 10, 20, 50, 100, 200, 350, 500, 1000,
|
-2500, -1000, -500, -499, -497, -450, -300, -200, -50, -1, 0, 1, 2, 5, 10, 20, 50, 100, 200, 350, 500, 1000,
|
||||||
2500, 5000, 10000, 25000, 100000, 250000, 500000, 1000000, 2000000, 5000000, 10000000, 100000000, 2100000000)]
|
2500, 5000, 10000, 25000, 100000, 250000, 500000, 1000000, 2000000, 5000000, 10000000, 100000000, 200000000)]
|
||||||
[InlineData(RngEntropy.Strong,
|
[InlineData(RngEntropy.Strong,
|
||||||
-250000000, -25000000, -10000000, -5000000, -2000000, -1000000, -500000, -250000, -100000, -25000, -10000, -5000,
|
-100000000, -25000000, -10000000, -5000000, -2000000, -1000000, -500000, -250000, -100000, -25000, -10000, -5000,
|
||||||
-2500, -1000, -500, -499, -497, -450, -300, -200, -50, -1, 0, 1, 2, 5, 10, 20, 50, 100, 200, 350, 500, 1000,
|
-2500, -1000, -500, -499, -497, -450, -300, -200, -50, -1, 0, 1, 2, 5, 10, 20, 50, 100, 200, 350, 500, 1000,
|
||||||
2500, 5000, 10000, 25000, 100000, 250000, 500000, 1000000, 2000000, 5000000, 10000000, 100000000, 2100000000)]
|
2500, 5000, 10000, 25000, 100000, 250000, 500000, 1000000, 2000000, 5000000, 10000000, 100000000, 200000000)]
|
||||||
[InlineData(RngEntropy.Weak,
|
[InlineData(RngEntropy.Weak,
|
||||||
-9863, -9740, -9214, -8878, -8674, -8652, -8640, -8565, -8518, -8449,
|
-9863, -9740, -9214, -8878, -8674, -8652, -8640, -8565, -8518, -8449,
|
||||||
-8390, -8193, -8108, -7808, -7501, -7203, -7133, -7020, -6983, -6855,
|
-8390, -8193, -8108, -7808, -7501, -7203, -7133, -7020, -6983, -6855,
|
||||||
|
|||||||
@@ -1,38 +1,42 @@
|
|||||||
using System.Runtime.InteropServices;
|
|
||||||
using System.Security.Cryptography;
|
using System.Security.Cryptography;
|
||||||
|
|
||||||
namespace Just.Core;
|
namespace Just.Core;
|
||||||
|
|
||||||
public static class GuidV8
|
public static class GuidV8
|
||||||
{
|
{
|
||||||
[Pure, MethodImpl(MethodImplOptions.AggressiveInlining)]
|
private const long TicksPrecision = TimeSpan.TicksPerMillisecond / 10;
|
||||||
|
|
||||||
|
[MethodImpl(MethodImplOptions.AggressiveInlining)]
|
||||||
public static Guid NewGuid(RngEntropy entropy = RngEntropy.Strong) => NewGuid(DateTime.UtcNow, entropy);
|
public static Guid NewGuid(RngEntropy entropy = RngEntropy.Strong) => NewGuid(DateTime.UtcNow, entropy);
|
||||||
|
|
||||||
[Pure]
|
|
||||||
public static Guid NewGuid(DateTime dateTime, RngEntropy entropy = RngEntropy.Strong)
|
public static Guid NewGuid(DateTime dateTime, RngEntropy entropy = RngEntropy.Strong)
|
||||||
{
|
{
|
||||||
var epoch = dateTime.Subtract(DateTime.UnixEpoch);
|
var epoch = dateTime.Subtract(DateTime.UnixEpoch);
|
||||||
var timestamp = epoch.Ticks / (TimeSpan.TicksPerMillisecond / 10);
|
var timestamp = epoch.Ticks / TicksPrecision;
|
||||||
|
|
||||||
Span<byte> ts = stackalloc byte[8];
|
uint tsHigh = (uint)((timestamp >> 16) & 0xFFFFFFFF);
|
||||||
MemoryMarshal.Write(ts, timestamp);
|
ushort tsLow = (ushort)(timestamp & 0x0000FFFF);
|
||||||
|
|
||||||
Span<byte> bytes = stackalloc byte[16];
|
Span<byte> bytes = stackalloc byte[10];
|
||||||
|
|
||||||
ts[0..2].CopyTo(bytes[4..6]);
|
|
||||||
ts[2..6].CopyTo(bytes[..4]);
|
|
||||||
|
|
||||||
if (entropy == RngEntropy.Strong)
|
if (entropy == RngEntropy.Strong)
|
||||||
{
|
{
|
||||||
RandomNumberGenerator.Fill(bytes[6..]);
|
RandomNumberGenerator.Fill(bytes);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Random.Shared.NextBytes(bytes[6..]);
|
Random.Shared.NextBytes(bytes);
|
||||||
}
|
}
|
||||||
|
|
||||||
bytes[7] = (byte)((bytes[7] & 0x0F) | 0x80);
|
bytes[0] = (byte)((bytes[0] & 0x0F) | 0x80); // Version 8
|
||||||
|
bytes[2] = (byte)((bytes[2] & 0x1F) | 0x80); // Variant 0b1000
|
||||||
|
|
||||||
return new Guid(bytes);
|
ushort version = (ushort)((bytes[0] << 8) | bytes[1]);
|
||||||
|
|
||||||
|
return new Guid(
|
||||||
|
tsHigh,
|
||||||
|
tsLow,
|
||||||
|
version,
|
||||||
|
bytes[2], bytes[3], bytes[4], bytes[5], bytes[6], bytes[7], bytes[8], bytes[9]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user