using System.Security.Cryptography;
namespace Fleet.Core;
/// 26 个字符的 ULID(Crockford base32,前 48 位为毫秒时间戳),按时间可排序。
public static class Ulid
{
private const string Alphabet = "0123456789ABCDEFGHJKMNPQRSTVWXYZ";
public static string New(TimeProvider time)
{
long ms = time.GetUtcNow().ToUnixTimeMilliseconds();
Span random = stackalloc byte[10];
RandomNumberGenerator.Fill(random);
Span chars = stackalloc char[26];
for (int i = 9; i >= 0; i--)
{
chars[i] = Alphabet[(int)(ms & 31)];
ms >>= 5;
}
// 80 位随机数 → 16 个 base32 字符
UInt128 r = 0;
foreach (byte b in random)
{
r = (r << 8) | b;
}
for (int i = 25; i >= 10; i--)
{
chars[i] = Alphabet[(int)(r & 31)];
r >>= 5;
}
return new string(chars);
}
/// 带类型前缀的 ID,例如 agt_01J…。
public static string NewPrefixed(string prefix, TimeProvider time) => prefix + "_" + New(time);
}