using System.Diagnostics.CodeAnalysis; using System.Text.Json; using System.Text.Json.Serialization; namespace Foxcord.Models; [JsonConverter(typeof(JsonConverter))] public readonly struct Snowflake(ulong value) : IEquatable { public const long Epoch = 1_420_070_400_000; // 2015-01-01 at 00:00:00 UTC public readonly ulong Value = value; /// /// The time this snowflake was created. /// public DateTimeOffset Time => DateTimeOffset.FromUnixTimeMilliseconds(Timestamp); /// /// The Unix timestamp embedded in this snowflake, in milliseconds. /// public long Timestamp => (long)((Value >> 22) + Epoch); /// /// The worker ID embedded in this snowflake. /// public byte WorkerId => (byte)((Value & 0x3E0000) >> 17); /// /// The process ID embedded in this snowflake. /// public byte ProcessId => (byte)((Value & 0x1F000) >> 12); /// /// The increment embedded in this snowflake. /// public short Increment => (short)(Value & 0xFFF); public static bool operator <(Snowflake arg1, Snowflake arg2) => arg1.Value < arg2.Value; public static bool operator >(Snowflake arg1, Snowflake arg2) => arg1.Value > arg2.Value; public static bool operator ==(Snowflake arg1, Snowflake arg2) => arg1.Value == arg2.Value; public static bool operator !=(Snowflake arg1, Snowflake arg2) => arg1.Value != arg2.Value; public static implicit operator ulong(Snowflake s) => s.Value; public static implicit operator long(Snowflake s) => (long)s.Value; public static implicit operator Snowflake(ulong n) => new(n); public static implicit operator Snowflake(long n) => new((ulong)n); public static bool TryParse(string? input, [NotNullWhen(true)] out Snowflake? snowflake) { snowflake = null; if (!ulong.TryParse(input, out var res)) return false; snowflake = new Snowflake(res); return true; } public override bool Equals(object? obj) => obj is Snowflake other && Value == other.Value; public bool Equals(Snowflake other) { return Value == other.Value; } public override int GetHashCode() => Value.GetHashCode(); public override string ToString() => Value.ToString(); public class JsonConverter : JsonConverter { public override Snowflake Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options) { var raw = reader.GetString(); if (!TryParse(raw, out var snowflake)) throw new FormatException("Snowflake is not a long within a string"); return snowflake.Value; } public override void Write(Utf8JsonWriter writer, Snowflake value, JsonSerializerOptions options) { writer.WriteStringValue(value.ToString()); } } }