Browse Source

Added documentation for AlmostVersion

pull/46/head
Anairkoen Schno 5 years ago
parent
commit
d70e2db258
1 changed files with 150 additions and 38 deletions
  1. +150
    -38
      IPA.Loader/Utilities/AlmostVersion.cs

+ 150
- 38
IPA.Loader/Utilities/AlmostVersion.cs View File

@ -1,49 +1,74 @@
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using SemVer;
using Version = SemVer.Version; using Version = SemVer.Version;
namespace IPA.Utilities namespace IPA.Utilities
{ {
/// <summary>
/// A type that wraps <see cref="Version"/> so that the string of the version is stored when the string is
/// not a valid <see cref="Version"/>.
/// </summary>
public class AlmostVersion : IComparable<AlmostVersion>, IComparable<Version> public class AlmostVersion : IComparable<AlmostVersion>, IComparable<Version>
{ {
private Version semverForm = null;
private string strForm = null;
private StoredAs storedAs;
/// <summary>
/// Represents a storage type of either parsed <see cref="Version"/> object or raw <see cref="String"/>.
/// </summary>
public enum StoredAs public enum StoredAs
{ {
/// <summary>
/// The version was stored as a <see cref="Version"/>.
/// </summary>
SemVer, SemVer,
/// <summary>
/// The version was stored as a <see cref="String"/>.
/// </summary>
String String
} }
/// <summary>
/// Creates a new <see cref="AlmostVersion"/> with the version string provided in <paramref name="vertext"/>.
/// </summary>
/// <param name="vertext">the version string to store</param>
public AlmostVersion(string vertext) public AlmostVersion(string vertext)
{ {
if (!TryParseFrom(vertext, StoredAs.SemVer)) if (!TryParseFrom(vertext, StoredAs.SemVer))
TryParseFrom(vertext, StoredAs.String); TryParseFrom(vertext, StoredAs.String);
} }
/// <summary>
/// Creates an <see cref="AlmostVersion"/> from the <see cref="Version"/> provided in <paramref name="ver"/>.
/// </summary>
/// <param name="ver">the <see cref="Version"/> to store</param>
public AlmostVersion(Version ver) public AlmostVersion(Version ver)
{ {
semverForm = ver;
storedAs = StoredAs.SemVer;
SemverValue = ver;
StorageMode = StoredAs.SemVer;
} }
/// <summary>
/// Creates an <see cref="AlmostVersion"/> from the version string in <paramref name="vertext"/> stored using
/// the storage mode specified in <paramref name="mode"/>.
/// </summary>
/// <param name="vertext">the text to parse as an <see cref="AlmostVersion"/></param>
/// <param name="mode">the storage mode to store the version in</param>
public AlmostVersion(string vertext, StoredAs mode) public AlmostVersion(string vertext, StoredAs mode)
{ {
if (!TryParseFrom(vertext, mode)) if (!TryParseFrom(vertext, mode))
throw new ArgumentException($"{nameof(vertext)} could not be stored as {mode}!"); throw new ArgumentException($"{nameof(vertext)} could not be stored as {mode}!");
} }
/// <summary>
/// Creates a new <see cref="AlmostVersion"/> from the version string in <paramref name="vertext"/> stored the
/// same way as the <see cref="AlmostVersion"/> passed in <paramref name="copyMode"/>.
/// </summary>
/// <param name="vertext">the text to parse as an <see cref="AlmostVersion"/></param>
/// <param name="copyMode">an <see cref="AlmostVersion"/> to copy the storage mode of</param>
public AlmostVersion(string vertext, AlmostVersion copyMode) public AlmostVersion(string vertext, AlmostVersion copyMode)
{ {
if (copyMode == null) if (copyMode == null)
throw new ArgumentNullException(nameof(copyMode)); throw new ArgumentNullException(nameof(copyMode));
if (!TryParseFrom(vertext, copyMode.storedAs))
if (!TryParseFrom(vertext, copyMode.StorageMode))
throw new ArgumentException($"{nameof(vertext)} could not be stored the same way as {copyMode}!"); throw new ArgumentException($"{nameof(vertext)} could not be stored the same way as {copyMode}!");
} }
@ -52,8 +77,8 @@ namespace IPA.Utilities
if (mode == StoredAs.SemVer) if (mode == StoredAs.SemVer)
try try
{ {
semverForm = new Version(str, true);
storedAs = StoredAs.SemVer;
SemverValue = new Version(str, true);
StorageMode = StoredAs.SemVer;
return true; return true;
} }
catch catch
@ -62,71 +87,158 @@ namespace IPA.Utilities
} }
else else
{ {
strForm = str;
storedAs = StoredAs.String;
StringValue = str;
StorageMode = StoredAs.String;
return true; return true;
} }
} }
public string StringValue => strForm;
public Version SemverValue => semverForm;
/// <summary>
/// The value of the <see cref="AlmostVersion"/> if it was stored as a <see cref="string"/>.
/// </summary>
/// <value>the stored value as a <see cref="string"/>, or <see langword="null"/> if not stored as a string.</value>
public string StringValue { get; private set; } = null;
/// <summary>
/// The value of the <see cref="AlmostVersion"/> if it was stored as a <see cref="Version"/>.
/// </summary>
/// <value>the stored value as a <see cref="Version"/>, or <see langword="null"/> if not stored as a version.</value>
public Version SemverValue { get; private set; } = null;
/// <summary>
/// The way the value is stored, whether it be as a <see cref="Version"/> or a <see cref="string"/>.
/// </summary>
/// <value>the storage mode used to store this value</value>
public StoredAs StorageMode { get; private set; }
// can I just <inheritdoc /> this?
/// <summary>
/// Gets a string representation of the current version. If the value is stored as a string, this returns it. If it is
/// stored as a <see cref="Version"/>, it is equivalent to calling <see cref="Version.ToString"/>.
/// </summary>
/// <returns>a string representation of the current version</returns>
/// <seealso cref="object.ToString"/>
public override string ToString() => public override string ToString() =>
storedAs == StoredAs.SemVer ? semverForm.ToString() : strForm;
StorageMode == StoredAs.SemVer ? SemverValue.ToString() : StringValue;
/// <summary>
/// Compares <see langword="this"/> to the <see cref="AlmostVersion"/> in <paramref name="other"/> using <see cref="Version.CompareTo(Version)"/>
/// or <see cref="string.CompareTo(string)"/>, depending on the current store.
/// </summary>
/// <remarks>
/// The storage methods of the two objects must be the same, or this will throw an <see cref="InvalidOperationException"/>.
/// </remarks>
/// <param name="other">the <see cref="AlmostVersion"/> to compare to</param>
/// <returns>less than 0 if <paramref name="other"/> is considered bigger than <see langword="this"/>, 0 if equal, and greater than zero if smaller</returns>
/// <seealso cref="CompareTo(Version)"/>
public int CompareTo(AlmostVersion other) public int CompareTo(AlmostVersion other)
{ {
if (other == null) return -1; if (other == null) return -1;
if (storedAs != other.storedAs)
if (StorageMode != other.StorageMode)
throw new InvalidOperationException("Cannot compare AlmostVersions with different stores!"); throw new InvalidOperationException("Cannot compare AlmostVersions with different stores!");
if (storedAs == StoredAs.SemVer)
return semverForm.CompareTo(other.semverForm);
if (StorageMode == StoredAs.SemVer)
return SemverValue.CompareTo(other.SemverValue);
else else
return strForm.CompareTo(other.strForm);
return StringValue.CompareTo(other.StringValue);
} }
/// <summary>
/// Compares <see langword="this"/> to the <see cref="Version"/> in <paramref name="other"/> using <see cref="Version.CompareTo(Version)"/>.
/// </summary>
/// <remarks>
/// The storage method of <see langword="this"/> must be <see cref="StoredAs.SemVer"/>, else an <see cref="InvalidOperationException"/> will
/// be thrown.
/// </remarks>
/// <param name="other">the <see cref="Version"/> to compare to</param>
/// <returns>less than 0 if <paramref name="other"/> is considered bigger than <see langword="this"/>, 0 if equal, and greater than zero if smaller</returns>
/// <seealso cref="CompareTo(AlmostVersion)"/>
public int CompareTo(Version other) public int CompareTo(Version other)
{ {
if (storedAs != StoredAs.SemVer)
if (StorageMode != StoredAs.SemVer)
throw new InvalidOperationException("Cannot compare a SemVer version with an AlmostVersion stored as a string!"); throw new InvalidOperationException("Cannot compare a SemVer version with an AlmostVersion stored as a string!");
return semverForm.CompareTo(other);
return SemverValue.CompareTo(other);
} }
/// <summary>
/// Performs a strict equality check between <see langword="this"/> and <paramref name="obj"/>.
/// </summary>
/// <remarks>
/// This may return <see langword="false"/> where <see cref="operator ==(AlmostVersion, AlmostVersion)"/> returns <see langword="true"/>
/// </remarks>
/// <param name="obj">the object to compare to</param>
/// <returns><see langword="true"/> if they are equal, <see langword="false"/> otherwise</returns>
/// <seealso cref="object.Equals(object)"/>
public override bool Equals(object obj) public override bool Equals(object obj)
{ {
return obj is AlmostVersion version && return obj is AlmostVersion version &&
semverForm == version.semverForm &&
strForm == version.strForm &&
storedAs == version.storedAs;
SemverValue == version.SemverValue &&
StringValue == version.StringValue &&
StorageMode == version.StorageMode;
} }
/// <summary>
/// Default generated hash code function generated by VS.
/// </summary>
/// <returns>a value unique to each object, except those that are considered equal by <see cref="Equals(object)"/></returns>
/// <seealso cref="object.GetHashCode"/>
public override int GetHashCode() public override int GetHashCode()
{ {
var hashCode = -126402897; var hashCode = -126402897;
hashCode = hashCode * -1521134295 + EqualityComparer<Version>.Default.GetHashCode(semverForm);
hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(strForm);
hashCode = hashCode * -1521134295 + storedAs.GetHashCode();
hashCode = hashCode * -1521134295 + EqualityComparer<Version>.Default.GetHashCode(SemverValue);
hashCode = hashCode * -1521134295 + EqualityComparer<string>.Default.GetHashCode(StringValue);
hashCode = hashCode * -1521134295 + StorageMode.GetHashCode();
return hashCode; return hashCode;
} }
/// <summary>
/// Compares two versions, only taking into account the numeric part of the version if they are stored as <see cref="Version"/><see langword="sealed"/>,
/// or strict equality if they are stored as <see cref="string"/>s.
/// </summary>
/// <remarks>
/// This is a looser equality than <see cref="Equals(object)"/>, meaning that this may return <see langword="true"/> where <see cref="Equals(object)"/>
/// does not.
/// </remarks>
/// <param name="l">the first value to compare</param>
/// <param name="r">the second value to compare</param>
/// <returns><see langword="true"/> if they are mostly equal, <see langword="false"/> otherwise</returns>
/// <seealso cref="Equals(object)"/>
public static bool operator==(AlmostVersion l, AlmostVersion r) 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;
if (l == null && r == null) return true;
if (l == null || r == null) return false;
if (l.StorageMode != r.StorageMode) return false;
if (l.StorageMode == StoredAs.SemVer)
return Utils.VersionCompareNoPrerelease(l.SemverValue, r.SemverValue) == 0;
else else
return l.strForm == r.strForm;
return l.StringValue == r.StringValue;
} }
/// <summary>
/// The opposite of <see cref="operator ==(AlmostVersion, AlmostVersion)"/>. Equivalent to <code>!(l == r)</code>.
/// </summary>
/// <param name="l">the first value to compare</param>
/// <param name="r">the second value to compare</param>
/// <returns><see langword="true"/> if they are not mostly equal, <see langword="false"/> otherwise</returns>
/// <seealso cref="operator ==(AlmostVersion, AlmostVersion)"/>
public static bool operator!=(AlmostVersion l, AlmostVersion r) => !(l == r); public static bool operator!=(AlmostVersion l, AlmostVersion r) => !(l == r);
// implicitly convertible from Version // implicitly convertible from Version
/// <summary>
/// Implicitly converts a <see cref="Version"/> to <see cref="AlmostVersion"/> using <see cref="AlmostVersion(Version)"/>.
/// </summary>
/// <param name="ver">the <see cref="Version"/> to convert</param>
/// <seealso cref="AlmostVersion(Version)"/>
public static implicit operator AlmostVersion(Version ver) => new AlmostVersion(ver); public static implicit operator AlmostVersion(Version ver) => new AlmostVersion(ver);
// implicitly convertible to Version // implicitly convertible to Version
public static implicit operator Version(AlmostVersion av) => av.SemverValue;
/// <summary>
/// Implicitly converts an <see cref="AlmostVersion"/> to <see cref="Version"/>, if applicable, using <see cref="SemverValue"/>.
/// If not applicable, returns <see langword="null"/>
/// </summary>
/// <param name="av">the <see cref="AlmostVersion"/> to convert to a <see cref="Version"/></param>
/// <seealso cref="SemverValue"/>
public static implicit operator Version(AlmostVersion av) => av?.SemverValue;
} }
} }

Loading…
Cancel
Save