Skip to content

Commit 4deda09

Browse files
authored
Ferature/UUID version 8 (#22)
* Adding V8 * Fixing batch generation issues * Adding UUID Max * Unified slice for bytes to uuids * Adding or extending tests
1 parent 5103cf3 commit 4deda09

18 files changed

Lines changed: 232 additions & 44 deletions

File tree

Library/Enumerators/Version.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,10 @@ public enum Version {
1212
V4 = 0b0100_0000,
1313
/// <summary>The <see cref="UUID"/> version that hashes (SHA1) given data into <see cref="UUID"/></summary>
1414
V5 = 0b0101_0000,
15+
/// <summary>The <see cref="UUID"/> version that is reordered Gregorian time-based UUID specified in this document.</summary></summary>
16+
V6 = 0b0110_0000,
17+
/// <summary>The <see cref="UUID"/> version that exposes Unix Epoch time-based UUID specified in this document.</summary>
18+
V7 = 0b0111_0000,
19+
/// <summary>The <see cref="UUID"/> version that allows for custom data of 122 bits of data</summary>
20+
V8 = 0b1000_0000,
1521
}
Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
using System.Runtime.CompilerServices;
2+
using System.Runtime.Intrinsics;
3+
4+
namespace DaanV2.UUID;
5+
6+
public static partial class Convert {
7+
/// <summary>Slices the given bytes into UUIDs</summary>
8+
/// <param name="bytes">The bytes to slice</param>
9+
/// <param name="version">The version to stamp in the UUID</param>
10+
/// <param name="variant">The variant to stamp in the UUID</param>
11+
/// <returns>A collection of <see cref="UUID"/></returns>
12+
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
13+
public static UUID[] Slice(ReadOnlySpan<Byte> bytes, Version version, Variant variant) {
14+
Vector128<Byte> mask = Format.VersionVariantMaskNot(version, variant);
15+
Vector128<Byte> overlay = Format.VersionVariantOverlayer(version, variant);
16+
17+
return Slice(bytes, mask, overlay);
18+
}
19+
20+
/// <summary>Slices the given bytes into UUIDs</summary>
21+
/// <param name="bytes">The bytes to slice</param>
22+
/// <param name="mask">The mask to apply</param>
23+
/// <param name="overlay">The overlay to add to the <see cref="UUID"/> usually version and variant</param>
24+
/// <returns>A collection of <see cref="UUID"/></returns>
25+
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
26+
public static UUID[] Slice(ReadOnlySpan<Byte> bytes, Vector128<Byte> mask, Vector128<Byte> overlay) {
27+
Int32 count = bytes.Length;
28+
Int32 amount = count / Format.UUID_BYTE_LENGTH;
29+
Int32 max = count - Format.UUID_BYTE_LENGTH;
30+
var uuids = new UUID[amount];
31+
32+
Int32 J = 0;
33+
for (Int32 I = 0; I <= max; I += Format.UUID_BYTE_LENGTH) {
34+
var data = Vector128.Create(bytes.Slice(I, Format.UUID_BYTE_LENGTH));
35+
Vector128<Byte> uuid = Format.StampVersion(mask, overlay, data);
36+
uuids[J++] = new UUID(uuid);
37+
}
38+
39+
return uuids;
40+
}
41+
}

Library/Static Classes/Format/Format - Create.cs

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
using System.Runtime.CompilerServices;
2-
using System.Runtime.Intrinsics;
1+
using System.Runtime.Intrinsics;
32

43
namespace DaanV2.UUID;
54

@@ -28,15 +27,20 @@ public static Vector128<Byte> Create(Version version, Variant variant, Vector128
2827
return StampVersion(mask, overlay, data);
2928
}
3029

31-
/// <summary>Uses the given mask and overlay to insert the version and variant onto the data</summary>
32-
/// <param name="versionMask">The mask of the versions and variants</param>
33-
/// <param name="versionOverlay">The overlay of the versions and variants</param>
34-
/// <param name="data">The data to stamp the version and variant onto</param>
35-
/// <returns>Returns a <see cref="Vector128{T}"/></returns>
36-
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
37-
public static Vector128<Byte> StampVersion(Vector128<Byte> versionMask, Vector128<Byte> versionOverlay, Vector128<Byte> data) {
38-
var result = Vector128.BitwiseAnd(data, versionMask);
39-
result = Vector128.BitwiseOr(result, versionOverlay);
40-
return result;
30+
/// <summary>Creates a layout of the data along with version and variant, the provided data will be placed around the version and variant</summary>
31+
/// <param name="version">The version to set</param>
32+
/// <param name="variant">The variant to set</param>
33+
/// <param name="dataA">48 bits of data, top 16 will be removed</param>
34+
/// <param name="dataB">12 bits of data, top 4 will be removed</param>
35+
/// <param name="dataC">62 bits of data, top 2 will be removed</param>
36+
/// <returns></returns>
37+
public static Vector128<Byte> Create(Version version, Variant variant, UInt64 dataA, UInt16 dataB, UInt64 dataC) {
38+
// 48 bits of data in the top, 16 bits will be removed
39+
UInt64 upper = dataA << 16;
40+
// 12 bits in the lower, 4 bits in the middle for the version.
41+
upper |= dataB;
42+
43+
// 62 bits of data in the lower, 2 bits in the top for the variant.
44+
return Create(version, variant, upper, dataC);
4145
}
4246
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
using System.Runtime.CompilerServices;
2+
using System.Runtime.Intrinsics;
3+
4+
namespace DaanV2.UUID;
5+
6+
public static partial class Format {
7+
/// <summary>Uses the given mask and overlay to insert the version and variant onto the data</summary>
8+
/// <param name="versionMask">The mask of the versions and variants</param>
9+
/// <param name="versionOverlay">The overlay of the versions and variants</param>
10+
/// <param name="data">The data to stamp the version and variant onto</param>
11+
/// <returns>Returns a <see cref="Vector128{T}"/></returns>
12+
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
13+
public static Vector128<Byte> StampVersion(Vector128<Byte> versionMask, Vector128<Byte> versionOverlay, ReadOnlySpan<Byte> data) {
14+
var temp = Vector128.Create(data);
15+
return StampVersion(versionMask, versionOverlay, temp);
16+
}
17+
18+
/// <inheritdoc cref="StampVersion(Vector128{Byte},Vector128{Byte},ReadOnlySpan{Byte})"/>
19+
[MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)]
20+
public static Vector128<Byte> StampVersion(Vector128<Byte> versionMask, Vector128<Byte> versionOverlay, Vector128<Byte> data) {
21+
var result = Vector128.BitwiseAnd(data, versionMask);
22+
result = Vector128.BitwiseOr(result, versionOverlay);
23+
return result;
24+
}
25+
}

Library/Static Classes/V3/V3 - Batch.cs

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -31,18 +31,6 @@ public static UUID[] Batch(Int32 amount, String source, Encoding encoding) {
3131
return Batch(amount, bytes);
3232
}
3333

34-
/// <inheritdoc cref="Batch(Int32, ReadOnlySpan{Byte})"/>
35-
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
36-
public static UUID[] Batch(Byte[] source) {
37-
return Batch(source.AsSpan());
38-
}
39-
40-
/// <inheritdoc cref="Batch(Int32, ReadOnlySpan{Byte})"/>
41-
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
42-
public static UUID[] Batch(Int32 amount, Byte[] source) {
43-
return Batch(amount, source.AsSpan());
44-
}
45-
4634
/// <inheritdoc cref="Batch(Int32, ReadOnlySpan{Byte})"/>
4735
[MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)]
4836
public static UUID[] Batch(ReadOnlySpan<Byte> source) {
@@ -57,9 +45,9 @@ public static UUID[] Batch(ReadOnlySpan<Byte> source) {
5745
[MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)]
5846
public static UUID[] Batch(Int32 amount, ReadOnlySpan<Byte> source) {
5947
Int32 step = source.Length / amount;
60-
Int32 max = source.Length - step;
48+
Int32 max = (source.Length - step + 1);
6149

62-
Span<Byte> hash = stackalloc Byte[MD5.HashSizeInBytes];
50+
Span<Byte> hash = stackalloc Byte[Math.Max(MD5.HashSizeInBytes, UUID.BYTE_LENGTH)];
6351

6452
var uuids = new UUID[amount];
6553
Int32 J = 0;

Library/Static Classes/V4/V4 - Batch.cs

Lines changed: 1 addition & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -36,19 +36,7 @@ public static UUID[] Batch(Int32 amount, Random rnd) {
3636
/// <returns>A collection of <see cref="UUID"/></returns>
3737
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
3838
public static UUID[] Batch(ReadOnlySpan<Byte> bytes) {
39-
Int32 count = bytes.Length;
40-
Int32 amount = count / Format.UUID_BYTE_LENGTH;
41-
Int32 max = count - Format.UUID_BYTE_LENGTH;
42-
var uuids = new UUID[amount];
43-
44-
Int32 J = 0;
45-
for (Int32 I = 0; I <= max; I += Format.UUID_BYTE_LENGTH) {
46-
var data = Vector128.Create(bytes.Slice(I, Format.UUID_BYTE_LENGTH));
47-
Vector128<Byte> uuid = Format.StampVersion(_VersionMask, _VersionOverlay, data);
48-
uuids[J++] = new UUID(uuid);
49-
}
50-
51-
return uuids;
39+
return Convert.Slice(bytes, _VersionMask, _VersionOverlay);
5240
}
5341

5442
/// <summary>Uses a user specified function to generate more <see cref="UUID"/></summary>

Library/Static Classes/V5/V5 - Batch.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public static UUID[] Batch(Int32 amount, Byte[] source) {
6060
[MethodImpl(MethodImplOptions.AggressiveOptimization | MethodImplOptions.AggressiveInlining)]
6161
public static UUID[] Batch(Int32 amount, ReadOnlySpan<Byte> source) {
6262
Int32 step = source.Length / amount;
63-
Int32 max = source.Length - step;
63+
Int32 max = (source.Length - step) + 1;
6464

6565
Span<Byte> hash = stackalloc Byte[SHA1.HashSizeInBytes];
6666

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System.Runtime.CompilerServices;
2+
3+
namespace DaanV2.UUID;
4+
5+
public static partial class V8 {
6+
/// <summary>Turns the entire bytes collection into UUIDs</summary>
7+
/// <param name="bytes">The byte to chunk into <see cref="UUID"/></param>
8+
/// <returns>A collection of <see cref="UUID"/></returns>
9+
[MethodImpl(MethodImplOptions.AggressiveOptimization)]
10+
public static UUID[] Batch(ReadOnlySpan<Byte> bytes) {
11+
return Convert.Slice(bytes, _VersionMask, _VersionOverlay);
12+
}
13+
}
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
using System.Runtime.Intrinsics;
2+
using System.Security.Cryptography;
3+
4+
namespace DaanV2.UUID;
5+
public static partial class V8 {
6+
/// <inheritdoc cref="V1.Version"/>
7+
public const Version Version = DaanV2.UUID.Version.V8;
8+
/// <inheritdoc cref="V1.Variant"/>
9+
public const Variant Variant = DaanV2.UUID.Variant.V1;
10+
11+
private static readonly Vector128<Byte> _VersionMask = Format.VersionVariantMaskNot(V8.Version, V8.Variant);
12+
private static readonly Vector128<Byte> _VersionOverlay = Format.VersionVariantOverlayer(V8.Version, V8.Variant);
13+
}
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
using System.Runtime.Intrinsics;
2+
3+
namespace DaanV2.UUID;
4+
5+
public static partial class V8 {
6+
/// <summary>Extracts the three given data set that UUID 8 holds</summary>
7+
/// <param name="uuid">The UUID to extract the data from</param>
8+
/// <returns>48 bits of data, 12 bits of data, and 62 bits data</returns>
9+
public static (UInt64 bits48, UInt16 bits12, UInt64 bits62) Extract(UUID uuid) {
10+
Vector128<UInt64> d = uuid._Data.AsUInt64();
11+
12+
UInt64 dataA = d.GetElement(0);
13+
UInt64 dataC = d.GetElement(1);
14+
// Lower 12 bits of the first 64 bits
15+
UInt16 dataB = (UInt16)(dataA & 0b1111_1111_1111);
16+
17+
// Remove the lower 16 bits, so we have 48 bits of data
18+
dataA >>= 16;
19+
20+
// Remove top 2 bits, so we have 62 bits of data
21+
const UInt64 mask = 0b11u << 62;
22+
dataC &= mask;
23+
24+
return (dataA, dataB, dataC);
25+
}
26+
}

0 commit comments

Comments
 (0)