80 lines
		
	
	
	
		
			2.9 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
		
		
			
		
	
	
			80 lines
		
	
	
	
		
			2.9 KiB
		
	
	
	
		
			C#
		
	
	
	
	
	
|  | 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<Snowflake> | ||
|  | { | ||
|  |     public const long Epoch = 1_420_070_400_000; // 2015-01-01 at 00:00:00 UTC | ||
|  |     public readonly ulong Value = value; | ||
|  | 
 | ||
|  |     /// <summary> | ||
|  |     /// The time this snowflake was created. | ||
|  |     /// </summary> | ||
|  |     public DateTimeOffset Time => DateTimeOffset.FromUnixTimeMilliseconds(Timestamp); | ||
|  | 
 | ||
|  |     /// <summary> | ||
|  |     /// The Unix timestamp embedded in this snowflake, in milliseconds. | ||
|  |     /// </summary> | ||
|  |     public long Timestamp => (long)((Value >> 22) + Epoch); | ||
|  | 
 | ||
|  |     /// <summary> | ||
|  |     /// The worker ID embedded in this snowflake. | ||
|  |     /// </summary> | ||
|  |     public byte WorkerId => (byte)((Value & 0x3E0000) >> 17); | ||
|  | 
 | ||
|  |     /// <summary> | ||
|  |     /// The process ID embedded in this snowflake. | ||
|  |     /// </summary> | ||
|  |     public byte ProcessId => (byte)((Value & 0x1F000) >> 12); | ||
|  | 
 | ||
|  |     /// <summary> | ||
|  |     /// The increment embedded in this snowflake. | ||
|  |     /// </summary> | ||
|  |     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<Snowflake> | ||
|  |     { | ||
|  |         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()); | ||
|  |         } | ||
|  |     } | ||
|  | } |