using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using SemVer; using Version = SemVer.Version; namespace IPA.Utilities { public class AlmostVersion : IComparable, IComparable { private Version semverForm = null; private string strForm = null; private StoredAs storedAs; public enum StoredAs { SemVer, String } public AlmostVersion(string vertext) { if (!TryParseFrom(vertext, StoredAs.SemVer)) TryParseFrom(vertext, StoredAs.String); } public AlmostVersion(Version ver) { semverForm = ver; storedAs = StoredAs.SemVer; } public AlmostVersion(string vertext, StoredAs mode) { if (!TryParseFrom(vertext, mode)) throw new ArgumentException($"{nameof(vertext)} could not be stored as {mode}!"); } public AlmostVersion(string vertext, AlmostVersion copyMode) { if (copyMode == null) throw new ArgumentNullException(nameof(copyMode)); if (!TryParseFrom(vertext, copyMode.storedAs)) throw new ArgumentException($"{nameof(vertext)} could not be stored the same way as {copyMode}!"); } private bool TryParseFrom(string str, StoredAs mode) { if (mode == StoredAs.SemVer) try { semverForm = new Version(str, true); storedAs = StoredAs.SemVer; return true; } catch { return false; } else { strForm = str; storedAs = StoredAs.String; return true; } } public string StringValue => strForm; public Version SemverValue => semverForm; public override string ToString() => storedAs == StoredAs.SemVer ? semverForm.ToString() : strForm; public int CompareTo(AlmostVersion other) { if (other == null) return -1; if (storedAs != other.storedAs) throw new InvalidOperationException("Cannot compare AlmostVersions with different stores!"); if (storedAs == StoredAs.SemVer) return semverForm.CompareTo(other.semverForm); else return strForm.CompareTo(other.strForm); } public int CompareTo(Version other) { if (storedAs != StoredAs.SemVer) throw new InvalidOperationException("Cannot compare a SemVer version with an AlmostVersion stored as a string!"); return semverForm.CompareTo(other); } public override bool Equals(object obj) { return obj is AlmostVersion version && semverForm == version.semverForm && strForm == version.strForm && storedAs == version.storedAs; } public override int GetHashCode() { var hashCode = -126402897; hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(semverForm); hashCode = hashCode * -1521134295 + EqualityComparer.Default.GetHashCode(strForm); hashCode = hashCode * -1521134295 + storedAs.GetHashCode(); return hashCode; } public static bool operator==(AlmostVersion l, AlmostVersion r) { if (l.storedAs != r.storedAs) return false; if (l.storedAs == StoredAs.SemVer) return Utils.VersionCompareNoPrerelease(l.semverForm, r.semverForm) == 0; else return l.strForm == r.strForm; } public static bool operator!=(AlmostVersion l, AlmostVersion r) => !(l == r); // implicitly convertible from Version public static implicit operator AlmostVersion(Version ver) => new AlmostVersion(ver); // implicitly convertible to Version public static implicit operator Version(AlmostVersion av) => av.SemverValue; } }