Mizuki/Helpers/Tid.cs
2025-01-12 20:17:43 +01:00

71 lines
No EOL
1.8 KiB
C#

using System.Security.Cryptography;
namespace Mizuki.Helpers;
/// <summary>
/// An AT protocol time-based ID.
/// </summary>
public readonly struct Tid
{
/// <summary>
/// The Base32 sort alphabet.
/// </summary>
private const string Base32SortAlphabet = "234567abcdefghijklmnopqrstuvwxyz";
/// <summary>
/// The TID value.
/// </summary>
public readonly string Value;
/// <summary>
/// Constructs a TID from an integer representation of the TID.
/// </summary>
/// <param name="tid">The TID value.</param>
private Tid(ulong tid)
{
Value = NumericTidToStringTid(tid);
}
/// <summary>
/// Constructs a new TID for the current time.
/// </summary>
/// <returns>The current time.</returns>
public static Tid NewTid()
{
var microseconds = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds() * 1000;
var randomness = (uint)RandomNumberGenerator.GetInt32(int.MaxValue);
var value = (ulong)(((microseconds & 0x1F_FFFF_FFFF_FFFF) << 10) | (randomness & 0x3FF));
return new Tid(value);
}
/// <summary>
/// An empty TID.
/// </summary>
public static Tid Empty => new Tid(0);
/// <summary>
/// Converts a numeric TID to a string TID.
/// </summary>
/// <param name="tid">The numeric TID.</param>
/// <returns>The string TID.</returns>
private static string NumericTidToStringTid(ulong tid)
{
var value = 0x7FFF_FFFF_FFFF_FFFF & tid;
var output = "";
for (var i = 0; i < 13; i++)
{
output = Base32SortAlphabet[(int)(value & 0x1F)] + output;
value >>= 5;
}
return output;
}
/// <inheritdoc />
public override string ToString()
{
return Value;
}
}