using System.Diagnostics.CodeAnalysis; using System.Text.RegularExpressions; using Microsoft.Extensions.Logging; namespace AltBot.Core.Models; /// /// Represents a Decentralized Identifier (DID) /// public class Did : IParsable { //private static readonly ILogger? _logger; private const int MaxLength = 2048; // Internal constructor for EF Core internal Did(string value) { Value = value; } public string Value { get; } /// /// Creates a new Did instance after validating the input string /// /// The raw DID string to validate /// A new Did instance if valid, null otherwise public static Did? Create(string rawDid) { return ValidateDid(rawDid) ? new Did(rawDid) : null; } // For use when the Did is known to be valid (e.g., loading from database) public static Did Load(string rawDid) { return new Did(rawDid); } private static bool ValidateDid(string did) { if (string.IsNullOrWhiteSpace(did)) { //_logger?.LogError("DID cannot be null or empty"); return false; } var parts = did.Split(':'); if (parts.Length != 3) { //_logger?.LogError("DID requires prefix, method, and method-specific content"); return false; } if (parts[0] != "did") { //_logger?.LogError("DID must start with 'did' prefix"); return false; }; // Basic method name validation if (parts[1] is not "plc" and not "web") { //_logger?.LogError("DID method must be 'plc' or 'web'"); return false; } if (did.Length > MaxLength) { //_logger?.LogError("DID is too long ({MaxLength} chars max)", MaxLength); return false; } return true; } public static Did Parse(string s, IFormatProvider? provider) { if (TryParse(s, provider, out var result)) { return result; } throw new FormatException($"Unable to parse DID: {s}"); } public static bool TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, [MaybeNullWhen(false)] out Did result) { if (s != null && ValidateDid(s)) { result = new Did(s); return true; } result = null; return false; } public override string ToString() => Value; public override bool Equals(object? obj) { if (obj is Did other) { return Value.Equals(other.Value, StringComparison.Ordinal); } return false; } public override int GetHashCode() => Value.GetHashCode(StringComparison.Ordinal); public static implicit operator string(Did did) => did.Value; public static explicit operator Did(string s) => Parse(s, null); public static bool operator ==(Did? left, Did? right) { if (ReferenceEquals(left, right)) { return true; } if (left is null || right is null) { return false; } return left.Equals(right); } public static bool operator !=(Did? left, Did? right) => !(left == right); }