//
// Licensed under the MIT License. See LICENSE file in the project root for full license information.
//
namespace MUnique.OpenMU.Persistence;
using System.Security.Cryptography;
///
/// A generator for version 7 GUIDs. Layout:
/// The first 6 bytes is a unix timestamp in milliseconds.
/// The 7th byte contains the version number (7) in the upper 4 bits.
/// The rest is random.
///
public static class GuidV7
{
///
/// Creates a new random guid.
///
/// The new guid.
public static Guid NewGuid() => NewGuid(DateTimeOffset.UtcNow);
///
/// Creates a new random guid for the specified date.
///
/// The date time offset which is the prefix of the id.
/// The new guid.
public static Guid NewGuid(DateTimeOffset dateTimeOffset)
{
// We create a buffer which is two bytes bigger than the Guid,
// because we don't need the first two bytes of the timestamp.
Span buffer = stackalloc byte[18];
var uuidAsBytes = buffer[2..];
var currentTimestamp = dateTimeOffset.ToUnixTimeMilliseconds();
if (!BitConverter.TryWriteBytes(buffer, currentTimestamp))
{
throw new InvalidOperationException("Could not convert the timestamp to bytes.");
}
RandomNumberGenerator.Fill(uuidAsBytes[6..]);
uuidAsBytes[6] &= 0x0F;
uuidAsBytes[6] |= 0x70;
return new Guid(uuidAsBytes, true);
}
}