sharp-chat/SharpChatCommon/Snowflake/SnowflakeGenerator.cs

35 lines
1.3 KiB
C#

namespace SharpChat.Snowflake;
public class SnowflakeGenerator {
public const long MASK = 0x7FFFFFFFFFFFFFFF;
// previous default epoch was 1588377600000, but snowflakes are much larger than SharpIds
public const long EPOCH = 1356998400000;
public const byte SHIFT = 16;
public readonly long Epoch;
public readonly byte Shift;
public readonly long TimestampMask;
public readonly long SequenceMask;
public SnowflakeGenerator(long epoch = EPOCH, byte shift = SHIFT) {
if(epoch is < 0 or > MASK)
throw new ArgumentException("Epoch must be a positive int64.", nameof(epoch));
if(shift is < 1 or > 63)
throw new ArgumentException("Shift must be between or equal to 1 and 63", nameof(shift));
Epoch = epoch;
Shift = shift;
// i think Index only does this as a hack for how integers work in PHP but its gonna run Once per application instance lol
TimestampMask = ~(~0L << (63 - shift));
SequenceMask = ~(~0L << shift);
}
public long Now(DateTimeOffset? at = null) {
return Math.Max(0, (at ?? DateTimeOffset.UtcNow).ToUnixTimeMilliseconds() - Epoch);
}
public long Next(long sequence, DateTimeOffset? at = null) {
return ((Now(at) & TimestampMask) << Shift) | (sequence & SequenceMask);
}
}