2 Commits

Author SHA1 Message Date
30af957fc6 + added ImmutableSequence
All checks were successful
.NET Test / test (push) Successful in 1m46s
.NET Publish / publish (push) Successful in 52s
2024-08-15 20:14:38 +04:00
d60b94dbaa * fixed guid generation 2024-08-15 19:55:04 +04:00
3 changed files with 196 additions and 95 deletions

View File

@@ -4,13 +4,87 @@ public class NewGuid
{
[Theory]
[InlineData(GuidV8Entropy.Weak,
-25000000 -10000000, -5000000, -2000000, -1000000, -500000, -250000, -100000, -25000, -10000, -5000,
-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, 5000, 10000, 25000, 100000, 250000, 500000, 1000000, 2000000, 5000000, 10000000)]
2500, 5000, 10000, 25000, 100000, 250000, 500000, 1000000, 2000000, 5000000, 10000000, 100000000, 250000000)]
[InlineData(GuidV8Entropy.Strong,
-25000000 -10000000, -5000000, -2000000, -1000000, -500000, -250000, -100000, -25000, -10000, -5000,
-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, 5000, 10000, 25000, 100000, 250000, 500000, 1000000, 2000000, 5000000, 10000000)]
2500, 5000, 10000, 25000, 100000, 250000, 500000, 1000000, 2000000, 5000000, 10000000, 100000000, 250000000)]
[InlineData(GuidV8Entropy.Weak,
-9863, -9740, -9214, -8878, -8674, -8652, -8640, -8565, -8518, -8449,
-8390, -8193, -8108, -7808, -7501, -7203, -7133, -7020, -6983, -6855,
-6576, -6162, -5630, -5505, -5472, -5382, -4706, -4680, -4509, -4454,
-4314, -3920, -3251, -3233, -3116, -2792, -2685, -2574, -2338, -2173,
-1934, -1914, -1528, -1483, -1410, -870, -757, -730, -263, -220,
151, 426, 588, 970, 1213, 1269, 1376, 1397, 1450, 1770,
2063, 2577, 2750, 2860, 3139, 3161, 3488, 3630, 3774, 4004,
4163, 4198, 4366, 4662, 4746, 4879, 5467, 5601, 5912, 5979,
6128, 6277, 6323, 6437, 6699, 6853, 7556, 7776, 7795, 8099,
8336, 8592, 8682, 8683, 8818, 8904, 9375, 9466, 9551, 9708)]
[InlineData(GuidV8Entropy.Strong,
-9863, -9740, -9214, -8878, -8674, -8652, -8640, -8565, -8518, -8449,
-8390, -8193, -8108, -7808, -7501, -7203, -7133, -7020, -6983, -6855,
-6576, -6162, -5630, -5505, -5472, -5382, -4706, -4680, -4509, -4454,
-4314, -3920, -3251, -3233, -3116, -2792, -2685, -2574, -2338, -2173,
-1934, -1914, -1528, -1483, -1410, -870, -757, -730, -263, -220,
151, 426, 588, 970, 1213, 1269, 1376, 1397, 1450, 1770,
2063, 2577, 2750, 2860, 3139, 3161, 3488, 3630, 3774, 4004,
4163, 4198, 4366, 4662, 4746, 4879, 5467, 5601, 5912, 5979,
6128, 6277, 6323, 6437, 6699, 6853, 7556, 7776, 7795, 8099,
8336, 8592, 8682, 8683, 8818, 8904, 9375, 9466, 9551, 9708)]
[InlineData(GuidV8Entropy.Weak,
5635912, 6673780, 17277183, 17512959, 19098799, 21672621, 30581958, 30824885, 31874213, 35192781,
36337094, 37752116, 38387215, 39154682, 40525427, 52288093, 55218356, 59065156, 65231785, 75430932,
76289058, 79078058, 85770685, 85925884, 94726743, 94864163, 95781967, 96150006, 96482085, 102570414,
107768232, 110571078, 110680108, 117974892, 119800380, 126381415, 135895862, 140034471, 149039187, 150906974,
156853001, 160514433, 166446323, 170148965, 171759448, 176494242, 184537553, 188558155, 197194403, 197615804,
201195323, 202294490, 203040975, 203331457, 205016944, 213460258, 217072025, 217185345, 231344025, 232390198,
235053215, 240175073, 245030721, 252275255, 252310334, 277070940, 277359970, 280624756, 288601124, 292427106,
292563035, 299285016, 303834917, 310357836, 315078337, 316367236, 318311758, 318873972, 319675272, 321784171,
324204294, 327667283, 330287252, 338438172, 349863360, 360777768, 366398711, 368637150, 368776734, 371900343,
379094084, 379818879, 381448333, 381814627, 382393101, 382483709, 385600870, 389455134, 396115960, 399364095)]
[InlineData(GuidV8Entropy.Strong,
5635912, 6673780, 17277183, 17512959, 19098799, 21672621, 30581958, 30824885, 31874213, 35192781,
36337094, 37752116, 38387215, 39154682, 40525427, 52288093, 55218356, 59065156, 65231785, 75430932,
76289058, 79078058, 85770685, 85925884, 94726743, 94864163, 95781967, 96150006, 96482085, 102570414,
107768232, 110571078, 110680108, 117974892, 119800380, 126381415, 135895862, 140034471, 149039187, 150906974,
156853001, 160514433, 166446323, 170148965, 171759448, 176494242, 184537553, 188558155, 197194403, 197615804,
201195323, 202294490, 203040975, 203331457, 205016944, 213460258, 217072025, 217185345, 231344025, 232390198,
235053215, 240175073, 245030721, 252275255, 252310334, 277070940, 277359970, 280624756, 288601124, 292427106,
292563035, 299285016, 303834917, 310357836, 315078337, 316367236, 318311758, 318873972, 319675272, 321784171,
324204294, 327667283, 330287252, 338438172, 349863360, 360777768, 366398711, 368637150, 368776734, 371900343,
379094084, 379818879, 381448333, 381814627, 382393101, 382483709, 385600870, 389455134, 396115960, 399364095)]
public void Guids_Differing_By_Minutes_Should_Be_Sortable(GuidV8Entropy entropy, params int[] seconds)
{
var rng = new Random(25);
var referenceTime = new DateTime(2024, 05, 17, 15, 36, 13, 771, DateTimeKind.Utc);
SortedList<DateTime, Guid> expected = new(seconds.Length);
foreach (var s in seconds)
{
var timestamp = referenceTime.AddMinutes(s);
expected.Add(timestamp, GuidV8.NewGuid(timestamp, entropy));
}
var sut = expected.Values.ToArray();
rng.Shuffle(sut);
sut.Order().Should().Equal(expected.Select(x => x.Value));
sut.OrderBy(x => x.ToString()).Should().Equal(expected.Select(x => x.Value));
sut.OrderDescending().Should().Equal(expected.Reverse().Select(x => x.Value));
sut.OrderByDescending(x => x.ToString()).Should().Equal(expected.Reverse().Select(x => x.Value));
}
[Theory]
[InlineData(GuidV8Entropy.Weak,
-250000000, -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, 5000, 10000, 25000, 100000, 250000, 500000, 1000000, 2000000, 5000000, 10000000, 100000000, 2100000000)]
[InlineData(GuidV8Entropy.Strong,
-250000000, -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, 5000, 10000, 25000, 100000, 250000, 500000, 1000000, 2000000, 5000000, 10000000, 100000000, 2100000000)]
[InlineData(GuidV8Entropy.Weak,
-9863, -9740, -9214, -8878, -8674, -8652, -8640, -8565, -8518, -8449,
-8390, -8193, -8108, -7808, -7501, -7203, -7133, -7020, -6983, -6855,
@@ -43,7 +117,7 @@ public class NewGuid
636537435, 637241486, 676077268, 691630262, 696158602, 714007596, 715537265, 718873134, 724266320, 741049828,
749379956, 757561933, 758668417, 761735205, 770349479, 797570403, 805896481, 809050934, 821655964, 821980469,
830824227, 840429528, 851772315, 859717719, 859763860, 867675943, 912124563, 914880620, 923914294, 930298008,
932610035, 937468680, 945565998, 949277691, 949397209, 951283050, 953249971, 953953188, 976210158, 982233484)]
932610035, 937468680, 945565998, 949277691, 949397209, 951283050, 953249971, 953953188, 976210158, 982233484, 982233485)]
[InlineData(GuidV8Entropy.Strong,
6629058, 24114993, 40561510, 46245969, 46876997, 48747281, 80489854, 110237218, 117445694, 118974860,
135132579, 141760591, 149114066, 158322437, 159065333, 164925904, 173848639, 175086337, 175704556, 176335514,
@@ -54,7 +128,7 @@ public class NewGuid
636537435, 637241486, 676077268, 691630262, 696158602, 714007596, 715537265, 718873134, 724266320, 741049828,
749379956, 757561933, 758668417, 761735205, 770349479, 797570403, 805896481, 809050934, 821655964, 821980469,
830824227, 840429528, 851772315, 859717719, 859763860, 867675943, 912124563, 914880620, 923914294, 930298008,
932610035, 937468680, 945565998, 949277691, 949397209, 951283050, 953249971, 953953188, 976210158, 982233484)]
932610035, 937468680, 945565998, 949277691, 949397209, 951283050, 953249971, 953953188, 976210158, 982233484, 982233485)]
public void Guids_Differing_By_Seconds_Should_Be_Sortable(GuidV8Entropy entropy, params int[] seconds)
{
var rng = new Random(25);
@@ -69,19 +143,22 @@ public class NewGuid
var sut = expected.Values.ToArray();
rng.Shuffle(sut);
sut.Order().Should().BeEquivalentTo(expected.Select(x => x.Value));
sut.OrderDescending().Should().BeEquivalentTo(expected.Reverse().Select(x => x.Value));
sut.Order().Should().Equal(expected.Select(x => x.Value));
sut.OrderBy(x => x.ToString()).Should().Equal(expected.Select(x => x.Value));
sut.OrderDescending().Should().Equal(expected.Reverse().Select(x => x.Value));
sut.OrderByDescending(x => x.ToString()).Should().Equal(expected.Reverse().Select(x => x.Value));
}
[Theory]
[InlineData(GuidV8Entropy.Weak,
-25000000 -10000000, -5000000, -2000000, -1000000, -500000, -250000, -100000, -25000, -10000, -5000,
-250000000, -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, 5000, 10000, 25000, 100000, 250000, 500000, 1000000, 2000000, 5000000, 10000000)]
2500, 5000, 10000, 25000, 100000, 250000, 500000, 1000000, 2000000, 5000000, 10000000, 100000000, 2100000000)]
[InlineData(GuidV8Entropy.Strong,
-25000000 -10000000, -5000000, -2000000, -1000000, -500000, -250000, -100000, -25000, -10000, -5000,
-250000000, -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, 5000, 10000, 25000, 100000, 250000, 500000, 1000000, 2000000, 5000000, 10000000)]
2500, 5000, 10000, 25000, 100000, 250000, 500000, 1000000, 2000000, 5000000, 10000000, 100000000, 2100000000)]
[InlineData(GuidV8Entropy.Weak,
-9863, -9740, -9214, -8878, -8674, -8652, -8640, -8565, -8518, -8449,
-8390, -8193, -8108, -7808, -7501, -7203, -7133, -7020, -6983, -6855,
@@ -114,7 +191,7 @@ public class NewGuid
636537435, 637241486, 676077268, 691630262, 696158602, 714007596, 715537265, 718873134, 724266320, 741049828,
749379956, 757561933, 758668417, 761735205, 770349479, 797570403, 805896481, 809050934, 821655964, 821980469,
830824227, 840429528, 851772315, 859717719, 859763860, 867675943, 912124563, 914880620, 923914294, 930298008,
932610035, 937468680, 945565998, 949277691, 949397209, 951283050, 953249971, 953953188, 976210158, 982233484)]
932610035, 937468680, 945565998, 949277691, 949397209, 951283050, 953249971, 953953188, 976210158, 982233484, 982233485)]
[InlineData(GuidV8Entropy.Strong,
6629058, 24114993, 40561510, 46245969, 46876997, 48747281, 80489854, 110237218, 117445694, 118974860,
135132579, 141760591, 149114066, 158322437, 159065333, 164925904, 173848639, 175086337, 175704556, 176335514,
@@ -125,10 +202,10 @@ public class NewGuid
636537435, 637241486, 676077268, 691630262, 696158602, 714007596, 715537265, 718873134, 724266320, 741049828,
749379956, 757561933, 758668417, 761735205, 770349479, 797570403, 805896481, 809050934, 821655964, 821980469,
830824227, 840429528, 851772315, 859717719, 859763860, 867675943, 912124563, 914880620, 923914294, 930298008,
932610035, 937468680, 945565998, 949277691, 949397209, 951283050, 953249971, 953953188, 976210158, 982233484)]
932610035, 937468680, 945565998, 949277691, 949397209, 951283050, 953249971, 953953188, 976210158, 982233484, 982233485)]
public void Guids_Differing_By_Milliseconds_Should_Be_Sortable(GuidV8Entropy entropy, params int[] seconds)
{
var rng = new Random(25);
var rng = new Random(26);
var referenceTime = new DateTime(2024, 05, 17, 15, 36, 13, 771, DateTimeKind.Utc);
SortedList<DateTime, Guid> expected = new(seconds.Length);
foreach (var s in seconds)
@@ -140,78 +217,10 @@ public class NewGuid
var sut = expected.Values.ToArray();
rng.Shuffle(sut);
sut.Order().Should().BeEquivalentTo(expected.Select(x => x.Value));
sut.OrderDescending().Should().BeEquivalentTo(expected.Reverse().Select(x => x.Value));
}
sut.Order().Should().Equal(expected.Select(x => x.Value));
sut.OrderBy(x => x.ToString()).Should().Equal(expected.Select(x => x.Value));
[Theory]
[InlineData(GuidV8Entropy.Weak,
-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, 5000, 10000, 25000, 100000, 250000, 500000, 1000000, 2000000, 5000000, 10000000)]
[InlineData(GuidV8Entropy.Strong,
-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, 5000, 10000, 25000, 100000, 250000, 500000, 1000000, 2000000, 5000000, 10000000)]
[InlineData(GuidV8Entropy.Weak,
-9863, -9740, -9214, -8878, -8674, -8652, -8640, -8565, -8518, -8449,
-8390, -8193, -8108, -7808, -7501, -7203, -7133, -7020, -6983, -6855,
-6576, -6162, -5630, -5505, -5472, -5382, -4706, -4680, -4509, -4454,
-4314, -3920, -3251, -3233, -3116, -2792, -2685, -2574, -2338, -2173,
-1934, -1914, -1528, -1483, -1410, -870, -757, -730, -263, -220,
151, 426, 588, 970, 1213, 1269, 1376, 1397, 1450, 1770,
2063, 2577, 2750, 2860, 3139, 3161, 3488, 3630, 3774, 4004,
4163, 4198, 4366, 4662, 4746, 4879, 5467, 5601, 5912, 5979,
6128, 6277, 6323, 6437, 6699, 6853, 7556, 7776, 7795, 8099,
8336, 8592, 8682, 8683, 8818, 8904, 9375, 9466, 9551, 9708)]
[InlineData(GuidV8Entropy.Strong,
-9863, -9740, -9214, -8878, -8674, -8652, -8640, -8565, -8518, -8449,
-8390, -8193, -8108, -7808, -7501, -7203, -7133, -7020, -6983, -6855,
-6576, -6162, -5630, -5505, -5472, -5382, -4706, -4680, -4509, -4454,
-4314, -3920, -3251, -3233, -3116, -2792, -2685, -2574, -2338, -2173,
-1934, -1914, -1528, -1483, -1410, -870, -757, -730, -263, -220,
151, 426, 588, 970, 1213, 1269, 1376, 1397, 1450, 1770,
2063, 2577, 2750, 2860, 3139, 3161, 3488, 3630, 3774, 4004,
4163, 4198, 4366, 4662, 4746, 4879, 5467, 5601, 5912, 5979,
6128, 6277, 6323, 6437, 6699, 6853, 7556, 7776, 7795, 8099,
8336, 8592, 8682, 8683, 8818, 8904, 9375, 9466, 9551, 9708)]
[InlineData(GuidV8Entropy.Weak,
6629058, 24114993, 40561510, 46245969, 46876997, 48747281, 80489854, 110237218, 117445694, 118974860,
135132579, 141760591, 149114066, 158322437, 159065333, 164925904, 173848639, 175086337, 175704556, 176335514,
200302773, 207133553, 230088723, 234521706, 239587338, 263755571, 264571928, 290118284, 292346548, 319322378,
320988273, 322638028, 324110126, 326855208, 332533719, 336668313, 350798512, 366520367, 380595181, 405033666,
410929500, 414099488, 417697882, 421269768, 431907031, 435262715, 442168482, 449797406, 458508845, 489039529,
503344305, 514934509, 537515867, 555210743, 563951463, 578783864, 580560518, 580902916, 605801607, 635231377,
636537435, 637241486, 676077268, 691630262, 696158602, 714007596, 715537265, 718873134, 724266320, 741049828,
749379956, 757561933, 758668417, 761735205, 770349479, 797570403, 805896481, 809050934, 821655964, 821980469,
830824227, 840429528, 851772315, 859717719, 859763860, 867675943, 912124563, 914880620, 923914294, 930298008,
932610035, 937468680, 945565998, 949277691, 949397209, 951283050, 953249971, 953953188, 976210158, 982233484)]
[InlineData(GuidV8Entropy.Strong,
6629058, 24114993, 40561510, 46245969, 46876997, 48747281, 80489854, 110237218, 117445694, 118974860,
135132579, 141760591, 149114066, 158322437, 159065333, 164925904, 173848639, 175086337, 175704556, 176335514,
200302773, 207133553, 230088723, 234521706, 239587338, 263755571, 264571928, 290118284, 292346548, 319322378,
320988273, 322638028, 324110126, 326855208, 332533719, 336668313, 350798512, 366520367, 380595181, 405033666,
410929500, 414099488, 417697882, 421269768, 431907031, 435262715, 442168482, 449797406, 458508845, 489039529,
503344305, 514934509, 537515867, 555210743, 563951463, 578783864, 580560518, 580902916, 605801607, 635231377,
636537435, 637241486, 676077268, 691630262, 696158602, 714007596, 715537265, 718873134, 724266320, 741049828,
749379956, 757561933, 758668417, 761735205, 770349479, 797570403, 805896481, 809050934, 821655964, 821980469,
830824227, 840429528, 851772315, 859717719, 859763860, 867675943, 912124563, 914880620, 923914294, 930298008,
932610035, 937468680, 945565998, 949277691, 949397209, 951283050, 953249971, 953953188, 976210158, 982233484)]
public void Guids_Differing_By_Microseconds_Should_Be_Sortable(GuidV8Entropy entropy, params int[] seconds)
{
var rng = new Random(25);
var referenceTime = new DateTime(2024, 05, 17, 15, 36, 13, 771, DateTimeKind.Utc);
SortedList<DateTime, Guid> expected = new(seconds.Length);
foreach (var s in seconds)
{
var timestamp = referenceTime.AddMicroseconds(s);
expected.Add(timestamp, GuidV8.NewGuid(timestamp, entropy));
}
var sut = expected.Values.ToArray();
rng.Shuffle(sut);
sut.Order().Should().BeEquivalentTo(expected.Select(x => x.Value));
sut.OrderDescending().Should().BeEquivalentTo(expected.Reverse().Select(x => x.Value));
sut.OrderDescending().Should().Equal(expected.Reverse().Select(x => x.Value));
sut.OrderByDescending(x => x.ToString()).Should().Equal(expected.Reverse().Select(x => x.Value));
}
}

View File

@@ -0,0 +1,92 @@
using System.Collections;
using System.Collections.Immutable;
using System.Numerics;
namespace Just.Core.Collections;
public class ImmutableSequence<T> :
IEnumerable<T>,
IReadOnlyList<T>,
IEquatable<ImmutableSequence<T>>,
IEqualityOperators<ImmutableSequence<T>, ImmutableSequence<T>, bool>
{
private static readonly int InitialHash = typeof(ImmutableSequence<T>).GetHashCode();
private static readonly Func<T?, T?, bool> CompareItem = EqualityComparer<T>.Default.Equals;
private readonly ImmutableList<T> _values;
public ImmutableSequence(ImmutableList<T> values) => _values = values;
public ImmutableSequence() : this(ImmutableArray<T>.Empty)
{
}
public ImmutableSequence(IEnumerable<T> values)
{
_values = [..values];
}
public ImmutableSequence(ReadOnlySpan<T> values) : this(ImmutableList.Create(values))
{
}
public bool IsEmpty => _values.IsEmpty;
public int Count => _values.Count;
public T this[int index] => _values[index];
public T this[Index index] => _values[index];
public ImmutableSequence<T> this[Range range]
{
get
{
var (offset, count) = range.GetOffsetAndLength(_values.Count);
return ConstructNew(_values.GetRange(offset, count));
}
}
protected virtual ImmutableSequence<T> ConstructNew(ImmutableList<T> values) => new(values);
public ImmutableSequence<T> Add(T value) => ConstructNew([.._values, value]);
public ImmutableSequence<T> AddFront(T value) => ConstructNew([value, .._values]);
public ImmutableList<T>.Enumerator GetEnumerator() => _values.GetEnumerator();
IEnumerator<T> IEnumerable<T>.GetEnumerator() => ((IEnumerable<T>)_values).GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)_values).GetEnumerator();
public override string ToString() => string.Join(Environment.NewLine, _values);
public virtual bool Equals([NotNullWhen(true)] ImmutableSequence<T>? other)
{
if (ReferenceEquals(this, other))
{
return true;
}
if (_values.Count != other?._values.Count)
{
return false;
}
for (int i = 0; i < _values.Count; i++)
{
if (!CompareItem(_values[i], other._values[i]))
{
return false;
}
}
return true;
}
public override bool Equals([NotNullWhen(true)] object? obj) => Equals(obj as ImmutableSequence<T>);
public override int GetHashCode()
{
HashCode hash = new();
hash.Add(InitialHash);
foreach (var value in _values)
{
hash.Add(value);
}
return hash.ToHashCode();
}
public static bool operator ==(ImmutableSequence<T>? left, ImmutableSequence<T>? right) => left is null ? right is null : left.Equals(right);
public static bool operator !=(ImmutableSequence<T>? left, ImmutableSequence<T>? right) => !(left == right);
}

View File

@@ -13,28 +13,28 @@ public static class GuidV8
[Pure]
public static Guid NewGuid(DateTime dateTime, GuidV8Entropy entropy = GuidV8Entropy.Strong)
{
var timestamp = dateTime.ToBinary() & 0x3FFF_FFFF_FFFF_FFFF;
var epoch = dateTime.Subtract(DateTime.UnixEpoch);
var timestamp = epoch.Ticks / (TimeSpan.TicksPerMillisecond / 10);
Span<byte> ts = stackalloc byte[8];
MemoryMarshal.Write(ts, timestamp);
Span<byte> bytes = stackalloc byte[16];
ts[4..].CopyTo(bytes[..4]);
ts[2..4].CopyTo(bytes[4..6]);
ts[..2].CopyTo(bytes[6..8]);
bytes[7] = (byte)((bytes[7] & 0x0f) | 0x80);
ts[0..2].CopyTo(bytes[4..6]);
ts[2..6].CopyTo(bytes[..4]);
if (entropy == GuidV8Entropy.Strong)
{
RandomNumberGenerator.Fill(bytes[8..]);
RandomNumberGenerator.Fill(bytes[6..]);
}
else
{
Random.Shared.NextBytes(bytes[8..]);
Random.Shared.NextBytes(bytes[6..]);
}
bytes[7] = (byte)((bytes[7] & 0x0F) | 0x80);
return new Guid(bytes);
}
}