diff --git a/Explorer/Assets/DCL/CommunicationData/URLHelpers/URN.cs b/Explorer/Assets/DCL/CommunicationData/URLHelpers/URN.cs index c74a11bd17..8d28459372 100644 --- a/Explorer/Assets/DCL/CommunicationData/URLHelpers/URN.cs +++ b/Explorer/Assets/DCL/CommunicationData/URLHelpers/URN.cs @@ -12,17 +12,27 @@ public readonly struct URN private readonly string lowercaseUrn; private readonly string originalUrn; + private readonly int hash; public URN(string urn) { - this.originalUrn = urn; - this.lowercaseUrn = this.originalUrn.ToLower(); + originalUrn = urn; + lowercaseUrn = originalUrn.ToLower(); + hash = originalUrn != null ? lowercaseUrn.GetHashCode() : 0; } - public URN(int urn) + private URN(URN urn, int shortenIndex) { - this.originalUrn = urn.ToString(); - this.lowercaseUrn = this.originalUrn.ToLower(); + bool hasSameLength = shortenIndex == urn.originalUrn.Length; + + originalUrn = hasSameLength ? urn.originalUrn : urn.originalUrn[..shortenIndex]; + lowercaseUrn = hasSameLength ? urn.lowercaseUrn : urn.lowercaseUrn[..shortenIndex]; + + hash = hasSameLength + ? urn.hash + : originalUrn != null + ? lowercaseUrn.GetHashCode() + : 0; } public bool IsNullOrEmpty() => @@ -31,13 +41,9 @@ public bool IsNullOrEmpty() => public bool IsValid() => !IsNullOrEmpty() && originalUrn.StartsWith("urn"); - public bool Equals(int other) => Equals(other.ToString()); - public bool Equals(URN other) => - Equals(other.lowercaseUrn); - - public bool Equals(string other) => - string.Equals(lowercaseUrn, other); + hash == other.hash && // "fail fast" check + lowercaseUrn == other.lowercaseUrn; // check to avoid false positives from hash collisions public override bool Equals(object obj) => obj is URN other && Equals(other); @@ -47,7 +53,8 @@ public override string ToString() => public URLAddress ToUrlOrEmpty(URLAddress baseUrl) { - string currentUrn = this.originalUrn; + string currentUrn = originalUrn; + ReadOnlySpan CutBeforeColon(ref int endIndex, out bool success) { int atBeginning = endIndex; @@ -115,13 +122,20 @@ void LogError() } public override int GetHashCode() => - originalUrn != null ? StringComparer.OrdinalIgnoreCase.GetHashCode(originalUrn) : 0; + hash; public URN Shorten() { if (string.IsNullOrEmpty(originalUrn)) return this; if (CountParts() <= SHORTEN_URN_PARTS) return this; + int shortenIndex = GetShortenIndex(); + + return shortenIndex != -1 ? new URN(this, shortenIndex) : this; + } + + private int GetShortenIndex() + { int index; if (IsThirdPartyCollection()) @@ -137,13 +151,13 @@ public URN Shorten() if (index == -1) break; } - return index != -1 ? originalUrn[..index] : originalUrn; + return index; } // TokenId is always placed in the last part for regular nfts index = originalUrn.LastIndexOf(':'); - return index != -1 ? originalUrn[..index] : this; + return index; } public static implicit operator URN(int urn) => @@ -160,7 +174,7 @@ public bool IsThirdPartyCollection() => private int CountParts() { - int count = 1; + var count = 1; int index = originalUrn.IndexOf(':'); while (index != -1)