Created
June 15, 2024 20:38
-
-
Save vcsjones/7e893b22555331d86698148d39b40235 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Diagnostics.CodeAnalysis; | |
using System.Runtime.CompilerServices; | |
using System.Runtime.InteropServices; | |
using System.Security.Cryptography; | |
UUIDv7 uuid = new UUIDv7(); | |
Console.WriteLine(uuid.ToString()); | |
public readonly struct UUIDv7 { | |
private readonly InteriorStruct _interior; | |
public UUIDv7() { | |
InteriorStruct.Fill(ref _interior); | |
} | |
public byte[] GetBytes() => _interior.AsReadOnlySpan().ToArray(); | |
public void CopyTo(Span<byte> destination) => _interior.AsReadOnlySpan().CopyTo(destination); | |
public override string ToString() => Convert.ToHexString(_interior.AsReadOnlySpan()); | |
public readonly override int GetHashCode() { | |
HashCode hc = new(); | |
hc.AddBytes(_interior.AsReadOnlySpan()); | |
return hc.ToHashCode(); | |
} | |
[InlineArray(SIZE)] | |
private struct InteriorStruct { | |
private const int SIZE = 16; | |
private byte _element; | |
public static void Fill(ref InteriorStruct uuid) { | |
Span<byte> value = MemoryMarshal.CreateSpan(ref uuid._element, SIZE); | |
RandomNumberGenerator.Fill(value); | |
long timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); | |
value[0] = (byte)((timestamp >> 40) & 0xFF); | |
value[1] = (byte)((timestamp >> 32) & 0xFF); | |
value[2] = (byte)((timestamp >> 24) & 0xFF); | |
value[3] = (byte)((timestamp >> 16) & 0xFF); | |
value[4] = (byte)((timestamp >> 8) & 0xFF); | |
value[5] = (byte)(timestamp & 0xFF); | |
// version and variant | |
value[6] = (byte)((value[6] & 0x0F) | 0x70); | |
value[8] = (byte)((value[8] & 0x3F) | 0x80); | |
} | |
[UnscopedRef] | |
internal ReadOnlySpan<byte> AsReadOnlySpan() => MemoryMarshal.CreateReadOnlySpan(ref _element, SIZE); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment