using System;
using UnityEngine;
namespace Artees.UnitySemVer
{
///
/// A semantic version based on the Semantic Versioning 2.0.0 specification.
///
[Serializable]
public class SemVer : IComparable, IEquatable
{
public const char IdentifiersSeparator = '.';
public const char PreReleasePrefix = '-';
public const char BuildPrefix = '+';
public static bool operator ==(SemVer left, SemVer right)
{
return Equals(left, right);
}
public static bool operator !=(SemVer left, SemVer right)
{
return !Equals(left, right);
}
public static bool operator >(SemVer left, SemVer right)
{
return left.CompareTo(right) > 0;
}
public static bool operator <(SemVer left, SemVer right)
{
return left.CompareTo(right) < 0;
}
public static bool operator >=(SemVer left, SemVer right)
{
return left.CompareTo(right) >= 0;
}
public static bool operator <=(SemVer left, SemVer right)
{
return left.CompareTo(right) <= 0;
}
public static implicit operator string(SemVer s)
{
return s.ToString();
}
public static implicit operator SemVer(string s)
{
return Parse(s);
}
public static SemVer Parse(string semVer)
{
return SemVerConverter.FromString(semVer);
}
///
/// Major version X (X.y.z | X > 0) MUST be incremented if any backwards incompatible changes are introduced
/// to the public API. It MAY include minor and patch level changes. Patch and minor version MUST be reset to 0
/// when major version is incremented.
///
///
public uint major;
///
/// Minor version Y (x.Y.z | x > 0) MUST be incremented if new, backwards compatible functionality is
/// introduced to the public API. It MUST be incremented if any public API functionality is marked as
/// deprecated. It MAY be incremented if substantial new functionality or improvements are introduced within
/// the private code. It MAY include patch level changes. Patch version MUST be reset to 0 when minor version
/// is incremented.
///
///
public uint minor;
///
/// Patch version Z (x.y.Z | x > 0) MUST be incremented if only backwards compatible bug fixes are introduced.
///
public uint patch;
///
/// A pre-release version indicates that the version is unstable and might not satisfy the intended
/// compatibility requirements as denoted by its associated normal version.
///
/// 1.0.0-alpha, 1.0.0-alpha.1, 1.0.0-0.3.7, 1.0.0-x.7.z.92
public string preRelease;
///
/// Set the build metadata automatically
///
///
public SemVerAutoBuild.Type autoBuild;
[SerializeField] private string build = string.Empty;
///
/// Build metadata MUST be ignored when determining version precedence. Thus two versions that differ only in
/// the build metadata, have the same precedence.
///
/// 1.0.0-alpha+001, 1.0.0+20130313144700, 1.0.0-beta+exp.sha.5114f85
public string Build
{
get => SemVerAutoBuild.Instances[autoBuild].Get(build);
set => build = SemVerAutoBuild.Instances[autoBuild].Set(value);
}
///
/// The base part of the version number (Major.Minor.Patch).
///
/// 1.9.0
/// Major.Minor.Patch
public string Core => $"{major}.{minor}.{patch}";
///
/// An internal version number. This number is used only to determine whether one version is more recent than
/// another, with higher numbers indicating more recent versions.
///
///
/// Major * 10000 + Minor * 100 + Patch
public int AndroidBundleVersionCode
{
get
{
var clampedPatch = ClampAndroidBundleVersionCode(patch, "Patch");
var clampedMinor = ClampAndroidBundleVersionCode(minor, "Minor");
return (int) (major * 10000 + clampedMinor * 100 + clampedPatch);
}
}
private static uint ClampAndroidBundleVersionCode(uint value, string name)
{
uint clamped;
const uint max = 100;
if (value >= max)
{
clamped = max - 1;
Debug.LogWarning(name + " should be less than " + max);
}
else
{
clamped = value;
}
return clamped;
}
public SemVer()
{
minor = 1;
preRelease = string.Empty;
autoBuild = SemVerAutoBuild.Type.Manual;
}
///
/// Increment the major version, reset the patch and the minor version to 0.
///
public void IncrementMajor()
{
major++;
minor = patch = 0;
}
///
/// Increment the minor version, reset the patch version to 0.
///
public void IncrementMinor()
{
minor++;
patch = 0;
}
///
/// Increment the patch version.
///
public void IncrementPatch()
{
patch++;
}
///
/// Check if this semantic version meets the Semantic Versioning 2.0.0
/// specification.
///
/// The result of validation and automatically corrected version number.
public SemVerValidationResult Validate()
{
return new SemVerValidator().Validate(this);
}
///
/// Creates a copy of this semantic version.
///
public SemVer Clone()
{
return new SemVer
{
major = major,
minor = minor,
patch = patch,
preRelease = preRelease,
Build = Build,
autoBuild = autoBuild,
};
}
public int CompareTo(SemVer other)
{
return new SemVerComparer().Compare(this, other);
}
public bool Equals(SemVer other)
{
if (ReferenceEquals(null, other)) return false;
if (ReferenceEquals(this, other)) return true;
return CompareTo(other) == 0;
}
public override bool Equals(object obj)
{
if (ReferenceEquals(null, obj)) return false;
if (ReferenceEquals(this, obj)) return true;
return obj.GetType() == GetType() && Equals((SemVer) obj);
}
public override int GetHashCode()
{
throw new NotImplementedException();
}
public override string ToString()
{
return SemVerConverter.ToString(this);
}
}
}