at main 3.4 kB view raw
1using System.Diagnostics.CodeAnalysis; 2using System.Text.RegularExpressions; 3using Microsoft.Extensions.Logging; 4 5namespace AltBot.Core.Models; 6 7/// <summary> 8/// Represents a Decentralized Identifier (DID) 9/// </summary> 10public class Did : IParsable<Did> 11{ 12 //private static readonly ILogger<Did>? _logger; 13 private const int MaxLength = 2048; 14 15 // Internal constructor for EF Core 16 internal Did(string value) 17 { 18 Value = value; 19 } 20 21 public string Value { get; } 22 23 /// <summary> 24 /// Creates a new Did instance after validating the input string 25 /// </summary> 26 /// <param name="rawDid">The raw DID string to validate</param> 27 /// <returns>A new Did instance if valid, null otherwise</returns> 28 public static Did? Create(string rawDid) 29 { 30 return ValidateDid(rawDid) ? new Did(rawDid) : null; 31 } 32 33 // For use when the Did is known to be valid (e.g., loading from database) 34 public static Did Load(string rawDid) 35 { 36 return new Did(rawDid); 37 } 38 39 private static bool ValidateDid(string did) 40 { 41 if (string.IsNullOrWhiteSpace(did)) 42 { 43 //_logger?.LogError("DID cannot be null or empty"); 44 return false; 45 } 46 47 var parts = did.Split(':'); 48 if (parts.Length != 3) 49 { 50 //_logger?.LogError("DID requires prefix, method, and method-specific content"); 51 return false; 52 } 53 54 if (parts[0] != "did") 55 { 56 //_logger?.LogError("DID must start with 'did' prefix"); 57 return false; 58 }; 59 60 // Basic method name validation 61 if (parts[1] is not "plc" and not "web") 62 { 63 //_logger?.LogError("DID method must be 'plc' or 'web'"); 64 return false; 65 } 66 67 if (did.Length > MaxLength) 68 { 69 //_logger?.LogError("DID is too long ({MaxLength} chars max)", MaxLength); 70 return false; 71 } 72 73 return true; 74 } 75 76 public static Did Parse(string s, IFormatProvider? provider) 77 { 78 if (TryParse(s, provider, out var result)) 79 { 80 return result; 81 } 82 throw new FormatException($"Unable to parse DID: {s}"); 83 } 84 85 public static bool TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, [MaybeNullWhen(false)] out Did result) 86 { 87 if (s != null && ValidateDid(s)) 88 { 89 result = new Did(s); 90 return true; 91 } 92 result = null; 93 return false; 94 } 95 96 public override string ToString() => Value; 97 98 public override bool Equals(object? obj) 99 { 100 if (obj is Did other) 101 { 102 return Value.Equals(other.Value, StringComparison.Ordinal); 103 } 104 return false; 105 } 106 107 public override int GetHashCode() => Value.GetHashCode(StringComparison.Ordinal); 108 109 public static implicit operator string(Did did) => did.Value; 110 111 public static explicit operator Did(string s) => Parse(s, null); 112 113 public static bool operator ==(Did? left, Did? right) 114 { 115 if (ReferenceEquals(left, right)) 116 { 117 return true; 118 } 119 120 if (left is null || right is null) 121 { 122 return false; 123 } 124 125 return left.Equals(right); 126 } 127 128 public static bool operator !=(Did? left, Did? right) => !(left == right); 129}