You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

132 lines
4.2 KiB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Text;
  5. using System.Threading.Tasks;
  6. using SemVer;
  7. using Version = SemVer.Version;
  8. namespace IPA.Utilities
  9. {
  10. public class AlmostVersion : IComparable<AlmostVersion>, IComparable<Version>
  11. {
  12. private Version semverForm = null;
  13. private string strForm = null;
  14. private StoredAs storedAs;
  15. public enum StoredAs
  16. {
  17. SemVer,
  18. String
  19. }
  20. public AlmostVersion(string vertext)
  21. {
  22. if (!TryParseFrom(vertext, StoredAs.SemVer))
  23. TryParseFrom(vertext, StoredAs.String);
  24. }
  25. public AlmostVersion(Version ver)
  26. {
  27. semverForm = ver;
  28. storedAs = StoredAs.SemVer;
  29. }
  30. public AlmostVersion(string vertext, StoredAs mode)
  31. {
  32. if (!TryParseFrom(vertext, mode))
  33. throw new ArgumentException($"{nameof(vertext)} could not be stored as {mode}!");
  34. }
  35. public AlmostVersion(string vertext, AlmostVersion copyMode)
  36. {
  37. if (copyMode == null)
  38. throw new ArgumentNullException(nameof(copyMode));
  39. if (!TryParseFrom(vertext, copyMode.storedAs))
  40. throw new ArgumentException($"{nameof(vertext)} could not be stored the same way as {copyMode}!");
  41. }
  42. private bool TryParseFrom(string str, StoredAs mode)
  43. {
  44. if (mode == StoredAs.SemVer)
  45. try
  46. {
  47. semverForm = new Version(str, true);
  48. storedAs = StoredAs.SemVer;
  49. return true;
  50. }
  51. catch
  52. {
  53. return false;
  54. }
  55. else
  56. {
  57. strForm = str;
  58. storedAs = StoredAs.String;
  59. return true;
  60. }
  61. }
  62. public string StringValue => strForm;
  63. public Version SemverValue => semverForm;
  64. public override string ToString() =>
  65. storedAs == StoredAs.SemVer ? semverForm.ToString() : strForm;
  66. public int CompareTo(AlmostVersion other)
  67. {
  68. if (other == null) return -1;
  69. if (storedAs != other.storedAs)
  70. throw new InvalidOperationException("Cannot compare AlmostVersions with different stores!");
  71. if (storedAs == StoredAs.SemVer)
  72. return semverForm.CompareTo(other.semverForm);
  73. else
  74. return strForm.CompareTo(other.strForm);
  75. }
  76. public int CompareTo(Version other)
  77. {
  78. if (storedAs != StoredAs.SemVer)
  79. throw new InvalidOperationException("Cannot compare a SemVer version with an AlmostVersion stored as a string!");
  80. return semverForm.CompareTo(other);
  81. }
  82. public override bool Equals(object obj)
  83. {
  84. return obj is AlmostVersion version &&
  85. semverForm == version.semverForm &&
  86. strForm == version.strForm &&
  87. storedAs == version.storedAs;
  88. }
  89. public override int GetHashCode()
  90. {
  91. var hashCode = -126402897;
  92. hashCode = hashCode * -1521134295 + EqualityComparer<Version>.Default.GetHashCode(semverForm);
  93. hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(strForm);
  94. hashCode = hashCode * -1521134295 + storedAs.GetHashCode();
  95. return hashCode;
  96. }
  97. public static bool operator==(AlmostVersion l, AlmostVersion r)
  98. {
  99. if (l.storedAs != r.storedAs) return false;
  100. if (l.storedAs == StoredAs.SemVer)
  101. return Utils.VersionCompareNoPrerelease(l.semverForm, r.semverForm) == 0;
  102. else
  103. return l.strForm == r.strForm;
  104. }
  105. public static bool operator!=(AlmostVersion l, AlmostVersion r) => !(l == r);
  106. // implicitly convertible from Version
  107. public static implicit operator AlmostVersion(Version ver) => new AlmostVersion(ver);
  108. // implicitly convertible to Version
  109. public static implicit operator Version(AlmostVersion av) => av.SemverValue;
  110. }
  111. }