mirror of
https://github.com/AssetRipper/AssetRipper.Primitives.git
synced 2026-11-13 04:26:30 -10:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3320be1312 | ||
|
|
659c382ff7 | ||
|
|
4aed9eb024 | ||
|
|
4e6f668e10 | ||
|
|
dc4e81eb28 | ||
|
|
0e2a37e920 | ||
|
|
b29d4a7a69 | ||
|
|
93ee2b0675 | ||
|
|
ebe6802570 | ||
|
|
97da17c016 | ||
|
|
475c27c28c | ||
|
|
fb0fb3f1c6 | ||
|
|
182fca60ca | ||
|
|
d4609533b2 | ||
|
|
46e53d834f | ||
|
|
99157d5433 | ||
|
|
5ec33f0518 | ||
|
|
c4a5ab77d4 | ||
|
|
ab4df10c87 | ||
|
|
2d00a1259a | ||
|
|
b65056d08f | ||
|
|
42c5957429 | ||
|
|
606e439721 | ||
|
|
b9a57bd765 | ||
|
|
0ed4298585 | ||
|
|
3e5ee80680 | ||
|
|
7325e30f1a | ||
|
|
6b87be6d8a | ||
|
|
92b8d127d3 | ||
|
|
045fe8cddc | ||
|
|
6e27480ba1 | ||
|
|
86eeee6194 | ||
|
|
5a5b5f9b30 | ||
|
|
a1b70935ad | ||
|
|
b46c8fbb9b | ||
|
|
f16703e850 | ||
|
|
ff61b6e467 | ||
|
|
59f6680b58 | ||
|
|
e47d41a95f | ||
|
|
488b2ede0c | ||
|
|
258ba8a688 | ||
|
|
a93d9b5439 | ||
|
|
064055ffc5 | ||
|
|
4a7f71fa57 | ||
|
|
aa79f9f987 | ||
|
|
bb0fbeb881 | ||
|
|
0fe5d800dc | ||
|
|
c9d5f8f43e | ||
|
|
80efcb915c | ||
|
|
e3ff418027 | ||
|
|
796efd3f55 | ||
|
|
c6bd1ca2e8 | ||
|
|
d2c656ff24 | ||
|
|
d254482fb7 | ||
|
|
d1b5be899a | ||
|
|
ec5b531448 | ||
|
|
ae69a49b4d | ||
|
|
4c164435b2 | ||
|
|
4cf22f6b44 | ||
|
|
1f49a61abe | ||
|
|
2bd7bb0914 | ||
|
|
27bb084d72 | ||
|
|
a03114987b | ||
|
|
54b5d01872 | ||
|
|
27583c9e44 | ||
|
|
7906d263b0 | ||
|
|
4e70cc8c58 | ||
|
|
8f58ce7a23 | ||
|
|
a7061ae190 | ||
|
|
a78136fcd6 | ||
|
|
5cd8f940e8 | ||
|
|
a3b6f7fdae | ||
|
|
01a05f9494 | ||
|
|
9fe6f0f7df | ||
|
|
683cee8da8 | ||
|
|
eae2f9438b | ||
|
|
b8b8bb94b0 | ||
|
|
9b60458f1d | ||
|
|
b80421fb6c | ||
|
|
ade88858b4 | ||
|
|
79940dc376 | ||
|
|
dddb3f98e1 | ||
|
|
616b101747 | ||
|
|
dba487c1e2 | ||
|
|
c506979787 | ||
|
|
e712430913 | ||
|
|
c48b62e600 | ||
|
|
6caf19db67 | ||
|
|
07c4f74cb3 | ||
|
|
6467eaf99f |
No files matched your search
@@ -0,0 +1,18 @@
|
||||
# To get started with Dependabot version updates, you'll need to specify which
|
||||
# package ecosystems to update and where the package manifests are located.
|
||||
# Please see the documentation for all configuration options:
|
||||
# https://help.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "nuget" # See documentation for possible values
|
||||
directory: "/" # Location of package manifests
|
||||
schedule:
|
||||
interval: "daily"
|
||||
|
||||
- package-ecosystem: "github-actions"
|
||||
# Workflow files stored in the
|
||||
# default location of `.github/workflows`
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: "daily"
|
||||
@@ -0,0 +1,61 @@
|
||||
name: .NET
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ master ]
|
||||
pull_request:
|
||||
branches: [ master ]
|
||||
|
||||
jobs:
|
||||
net7:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup .NET
|
||||
uses: actions/[email protected]
|
||||
with:
|
||||
dotnet-version: 7.0.x
|
||||
- name: Restore dependencies
|
||||
run: dotnet restore
|
||||
- name: Build
|
||||
run: dotnet build --framework net7.0 --no-restore
|
||||
- name: Test
|
||||
run: dotnet test --framework net7.0 --no-build --verbosity normal
|
||||
|
||||
net6:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup .NET
|
||||
uses: actions/[email protected]
|
||||
with:
|
||||
dotnet-version: 6.0.x
|
||||
- name: Restore dependencies
|
||||
run: dotnet restore
|
||||
- name: Build
|
||||
run: dotnet build --framework net6.0 --no-restore
|
||||
- name: Test
|
||||
run: dotnet test --framework net6.0 --no-build --verbosity normal
|
||||
|
||||
net5:
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Setup .NET
|
||||
uses: actions/[email protected]
|
||||
with:
|
||||
dotnet-version: |
|
||||
5.0.x
|
||||
6.0.x
|
||||
- name: Restore dependencies
|
||||
run: dotnet restore
|
||||
- name: Build
|
||||
run: dotnet build --framework net5.0 --no-restore
|
||||
- name: Test
|
||||
run: dotnet test --framework net5.0 --no-build --verbosity normal
|
||||
@@ -0,0 +1,75 @@
|
||||
namespace AssetRipper.VersionUtilities.Tests;
|
||||
|
||||
public class ComparisonTests
|
||||
{
|
||||
private static readonly UnityVersion lowValue = new UnityVersion(2017, 3, 0, UnityVersionType.Patch, 1);
|
||||
private static readonly UnityVersion mediumValue = new UnityVersion(2019, 4, 3, UnityVersionType.Final, 1);
|
||||
private static readonly UnityVersion highValue = new UnityVersion(2020, 2, 0, UnityVersionType.Final, 1);
|
||||
|
||||
[Test]
|
||||
public void LessThanIsTransitive()
|
||||
{
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(lowValue, Is.LessThan(mediumValue));
|
||||
Assert.That(mediumValue, Is.LessThan(highValue));
|
||||
Assert.That(lowValue, Is.LessThan(highValue));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void GreaterThanIsTransitive()
|
||||
{
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(mediumValue, Is.GreaterThan(lowValue));
|
||||
Assert.That(highValue, Is.GreaterThan(mediumValue));
|
||||
Assert.That(highValue, Is.GreaterThan(lowValue));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void WeakInequalityHolds()
|
||||
{
|
||||
UnityVersion low = lowValue;
|
||||
Assert.That(lowValue, Is.LessThanOrEqualTo(low));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MinimumValueDefinition()
|
||||
{
|
||||
Assert.That(UnityVersion.MinVersion, Is.EqualTo(new UnityVersion(ushort.MinValue, ushort.MinValue, ushort.MinValue, UnityVersionType.Alpha, byte.MinValue)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void MaximumValueDefinition()
|
||||
{
|
||||
Assert.That(UnityVersion.MaxVersion, Is.EqualTo(new UnityVersion(ushort.MaxValue, ushort.MaxValue, ushort.MaxValue, (UnityVersionType)byte.MaxValue, byte.MaxValue)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AnIncreaseOfTypeNumberMakesInequal()
|
||||
{
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(UnityVersion.MinVersion, Is.LessThan(new UnityVersion(ushort.MinValue, ushort.MinValue, ushort.MinValue, UnityVersionType.Alpha, 1)));
|
||||
Assert.That(lowValue, Is.LessThan(new UnityVersion(lowValue.Major, lowValue.Minor, lowValue.Build, lowValue.Type, (byte)(lowValue.TypeNumber + 1))));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void AlphaZeroIsTheDefault()
|
||||
{
|
||||
Assert.That(new UnityVersion(2019, 1, 0), Is.LessThan(new UnityVersion(2019, 1, 0, UnityVersionType.Final, 1)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ComparisonMethodsIgnoreUnspecifiedValues()
|
||||
{
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(new UnityVersion(2019, 1, 0, UnityVersionType.Final, 1).IsGreaterEqual(2019, 1, 0), Is.True);
|
||||
Assert.That(new UnityVersion(2019, 1, 0, UnityVersionType.Final, 1).IsLessEqual(2019, 1, 0), Is.True);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
namespace AssetRipper.VersionUtilities.Tests;
|
||||
|
||||
public class DistanceTests
|
||||
{
|
||||
private static readonly UnityVersion version3 = new UnityVersion(3, 0, 0, UnityVersionType.Final, 1);
|
||||
private static readonly UnityVersion version4 = new UnityVersion(4, 4, 0, UnityVersionType.Alpha, 1);
|
||||
private static readonly UnityVersion version5 = new UnityVersion(5, 6, 1, UnityVersionType.Final, 11);
|
||||
private static readonly UnityVersion version6 = new UnityVersion(6, 0, 0, UnityVersionType.Final, 1);
|
||||
private static readonly UnityVersion version7 = new UnityVersion(7, 0, 0, UnityVersionType.Final, 1);
|
||||
private static readonly UnityVersion version8 = new UnityVersion(8, 0, 0, UnityVersionType.Final, 1);
|
||||
private static readonly UnityVersion version9 = new UnityVersion(9, 0, 0, UnityVersionType.Final, 1);
|
||||
private static readonly UnityVersion[] versionArray = new UnityVersion[] { version3, version4, version5, version6, version7, version8, version9 };
|
||||
|
||||
[Test]
|
||||
public void DistanceFunctionIsSymmetric()
|
||||
{
|
||||
ulong distance1 = UnityVersion.Distance(version4, version5);
|
||||
ulong distance2 = UnityVersion.Distance(version5, version4);
|
||||
Assert.That(distance1, Is.EqualTo(distance2));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DistanceIsZeroForEquivalentVersions()
|
||||
{
|
||||
ulong distance = UnityVersion.Distance(version4, version4);
|
||||
Assert.That(distance, Is.EqualTo(0));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CorrectlyReturnsVersion6()
|
||||
{
|
||||
UnityVersion version = new UnityVersion(6, 1);
|
||||
UnityVersion closest = version.GetClosestVersion(versionArray);
|
||||
Assert.That(closest, Is.EqualTo(version6));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CorrectlyReturnsVersion5()
|
||||
{
|
||||
UnityVersion version = new UnityVersion(5, 4, 9);
|
||||
UnityVersion closest = version.GetClosestVersion(versionArray);
|
||||
Assert.That(closest, Is.EqualTo(version5));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,78 @@
|
||||
using NUnit.Framework.Internal;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace AssetRipper.VersionUtilities.Tests;
|
||||
|
||||
public class ParsingTests
|
||||
{
|
||||
[TestCase("4.2.2f1", 4, 2, 2, UnityVersionType.Final, 1, null, "Normal Unity 4 Version")]
|
||||
[TestCase("4.2.2f1\n1", 4, 2, 2, UnityVersionType.Final, 1, 1, "Custom Unity 4 Version")]
|
||||
[TestCase("2343.4.5f7", 2343, 4, 5, UnityVersionType.Final, 7, null, "Fictitious Future Version")]
|
||||
[TestCase("2019.2.2f1c2\n2", 2019, 2, 2, UnityVersionType.China, 2, 2, "Fake Custom Chinese Version")]
|
||||
[TestCase("2019.4", 2019, 4, 0, UnityVersionType.Final, 1, null, "Major Minor Only")]
|
||||
[TestCase("2019.4.3", 2019, 4, 3, UnityVersionType.Final, 1, null, "Major Minor Build Only")]
|
||||
public void UnityVersionParsesCorrectly(string versionString, int major, int minor, int build, UnityVersionType type, int typeNumber, int? customEngine, string name)
|
||||
{
|
||||
UnityVersion expected = new UnityVersion((ushort)major, (ushort)minor, (ushort)build, type, (byte)typeNumber);
|
||||
UnityVersion parsedVersion = UnityVersion.Parse(versionString, out int? parsedCustomEngine);
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(parsedCustomEngine, Is.EqualTo(customEngine), $"The custom engine boolean is incorrect for '{name}'");
|
||||
Assert.That(parsedVersion, Is.EqualTo(expected), $"The parsed version is incorrect for '{name}'");
|
||||
if (customEngine is not null || typeNumber is not 1)
|
||||
{
|
||||
Assert.That(parsedVersion.ToString(UnityVersionFormatFlags.Default, parsedCustomEngine), Is.EqualTo(versionString));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
[TestCaseSource(nameof(GenerateRandomVersions), new object[] { 20 })]
|
||||
public void UnityVersionToStringParsesCorrectly(UnityVersion version)
|
||||
{
|
||||
string versionString = version.ToString();
|
||||
UnityVersion parsedVersion = UnityVersion.Parse(versionString, out int? customEngine);
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(customEngine, Is.Null);
|
||||
Assert.That(parsedVersion, Is.EqualTo(version));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void LongChineseVersionFormat()
|
||||
{
|
||||
//This is an actual version from a game.
|
||||
//Versions like 2019.3.0f2 and 2020.3.15f2 don't have corresponding Chinese versions.
|
||||
//Source: https://unity.cn/releases
|
||||
string version = "2021.3.11f1c2";
|
||||
UnityVersion expected = new UnityVersion(2021, 3, 11, UnityVersionType.China, 2);
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(UnityVersion.Parse(version), Is.EqualTo(expected));
|
||||
Assert.That(expected.ToString(), Is.EqualTo(version));
|
||||
});
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ShortChineseVersionFormat()
|
||||
{
|
||||
//This is an actual version from a game.
|
||||
//Source: https://github.com/AssetRipper/AssetRipper/issues/841
|
||||
string version = "2017.4.40c1";
|
||||
UnityVersion expected = new UnityVersion(2017, 4, 40, UnityVersionType.China, 1);
|
||||
Assert.Multiple(() =>
|
||||
{
|
||||
Assert.That(UnityVersion.Parse(version), Is.EqualTo(expected));
|
||||
Assert.That(expected.ToString(UnityVersionFormatFlags.UseShortChineseFormat), Is.EqualTo(version));
|
||||
});
|
||||
}
|
||||
|
||||
private static IEnumerable<UnityVersion> GenerateRandomVersions(int count)
|
||||
{
|
||||
Randomizer random = TestContext.CurrentContext.Random;
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
yield return new UnityVersion(random.NextUShort(), random.NextUShort(), random.NextUShort(), random.NextEnum<UnityVersionType>(), random.NextByte());
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,39 +0,0 @@
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace AssetRipper.VersionUtilities.Tests
|
||||
{
|
||||
public class ParsingTests
|
||||
{
|
||||
[Test]
|
||||
public void UnityVersionParsesCorrectly()
|
||||
{
|
||||
string version = "2343.4.5f7";
|
||||
UnityVersion expected = new UnityVersion(2343, 4, 5, UnityVersionType.Final, 7);
|
||||
Assert.AreEqual(expected, UnityVersion.Parse(version));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void UnityVersionParsesDllCorrectly()
|
||||
{
|
||||
string dllName = "_2343_4_5f7.dll";
|
||||
UnityVersion expected = new UnityVersion(2343, 4, 5, UnityVersionType.Final, 7);
|
||||
Assert.AreEqual(expected, UnityVersion.ParseFromDllName(dllName));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void UnityVersionParsesDllCorrectlyWithoutExtension()
|
||||
{
|
||||
string dllName = "_2343_4_5f7";
|
||||
UnityVersion expected = new UnityVersion(2343, 4, 5, UnityVersionType.Final, 7);
|
||||
Assert.AreEqual(expected, UnityVersion.ParseFromDllName(dllName));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void UnityVersionParsesDllCorrectlyWithoutLeadingUnderscore()
|
||||
{
|
||||
string dllName = "2343_4_5f7.dll";
|
||||
UnityVersion expected = new UnityVersion(2343, 4, 5, UnityVersionType.Final, 7);
|
||||
Assert.AreEqual(expected, UnityVersion.ParseFromDllName(dllName));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
global using NUnit.Framework;
|
||||
@@ -1,24 +1,27 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netframework3.5;netframework4.0;netframework4.8;net5.0;net6.0</TargetFrameworks>
|
||||
<TargetFrameworks>netframework3.5;netframework4.0;netframework4.8;net5.0;net6.0;net7.0</TargetFrameworks>
|
||||
<LangVersion>Latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
<RootNamespace>AssetRipper.VersionUtilities.Tests</RootNamespace>
|
||||
|
||||
<IsPackable>false</IsPackable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.9.4" />
|
||||
<PackageReference Include="NUnit" Version="3.13.1" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="3.17.0" />
|
||||
<PackageReference Include="coverlet.collector" Version="3.0.2" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.1" />
|
||||
<PackageReference Include="NUnit" Version="3.13.3" />
|
||||
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0" />
|
||||
<PackageReference Include="NUnit.Analyzers" Version="3.6.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\VersionUtilities\VersionUtilities.csproj" />
|
||||
<ProjectReference Include="..\VersionUtilities\VersionUtilities.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -19,6 +19,11 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Licenses", "Licenses", "{4B
|
||||
Licenses\uTinyRipper.md = Licenses\uTinyRipper.md
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Workflows", "Workflows", "{B63714DC-6258-4032-9930-DFF0667624BC}"
|
||||
ProjectSection(SolutionItems) = preProject
|
||||
.github\workflows\dotnet.yml = .github\workflows\dotnet.yml
|
||||
EndProjectSection
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -39,6 +44,7 @@ Global
|
||||
EndGlobalSection
|
||||
GlobalSection(NestedProjects) = preSolution
|
||||
{4BE414B8-5B2D-40C1-BA3E-7DBBD6F7D854} = {36D291AB-E468-4CE7-8DB3-2C46639FE5AE}
|
||||
{B63714DC-6258-4032-9930-DFF0667624BC} = {36D291AB-E468-4CE7-8DB3-2C46639FE5AE}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {370218F4-B218-4C62-B7F7-D03B799F6349}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
using System;
|
||||
|
||||
namespace AssetRipper.VersionUtilities
|
||||
{
|
||||
internal static class CharacterExtensions
|
||||
{
|
||||
public static int ParseDigit(this char _this)
|
||||
{
|
||||
return _this - '0';
|
||||
}
|
||||
|
||||
public static UnityVersionType ToUnityVersionType(this char _this)
|
||||
{
|
||||
return _this switch
|
||||
{
|
||||
'a' => UnityVersionType.Alpha,
|
||||
'b' => UnityVersionType.Beta,
|
||||
'c' => UnityVersionType.China,
|
||||
'f' => UnityVersionType.Final,
|
||||
'p' => UnityVersionType.Patch,
|
||||
'x' => UnityVersionType.Experimental,
|
||||
_ => throw new Exception($"Unsupported version type {_this}"),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
namespace AssetRipper.VersionUtilities;
|
||||
|
||||
public partial struct CompactUnityVersion24 : IEquatable<CompactUnityVersion24>, IComparable, IComparable<CompactUnityVersion24>
|
||||
{
|
||||
/// <summary>
|
||||
/// Compare to another object
|
||||
/// </summary>
|
||||
/// <param name="obj">Another object</param>
|
||||
/// <returns>
|
||||
/// 1 if this is larger or the other is not a Unity version<br/>
|
||||
/// -1 if this is smaller<br/>
|
||||
/// 0 if equal
|
||||
/// </returns>
|
||||
public int CompareTo(object? obj)
|
||||
{
|
||||
return obj is CompactUnityVersion24 version ? CompareTo(version) : 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compare two Unity versions
|
||||
/// </summary>
|
||||
/// <param name="other">Another Unity version</param>
|
||||
/// <returns>
|
||||
/// 1 if this is larger<br/>
|
||||
/// -1 if this is smaller<br/>
|
||||
/// 0 if equal
|
||||
/// </returns>
|
||||
public int CompareTo(CompactUnityVersion24 other)
|
||||
{
|
||||
if (this > other)
|
||||
return 1;
|
||||
else if (this < other)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check equality with another object
|
||||
/// </summary>
|
||||
/// <param name="obj">Another object</param>
|
||||
/// <returns>True if they're equal; false otherwise</returns>
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return obj is CompactUnityVersion24 version && this == version;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check equality with another Unity version
|
||||
/// </summary>
|
||||
/// <param name="other">Another Unity version</param>
|
||||
/// <returns>True if they're equal; false otherwise</returns>
|
||||
public bool Equals(CompactUnityVersion24 other) => this == other;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return m_MajorMinorByte << 16 | m_BuildTypeShort;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
namespace AssetRipper.VersionUtilities;
|
||||
|
||||
public partial struct CompactUnityVersion24
|
||||
{
|
||||
/// <summary>
|
||||
/// Expand to 64 bits
|
||||
/// </summary>
|
||||
/// <param name="version">The version to convert</param>
|
||||
public static implicit operator UnityVersion(CompactUnityVersion24 version)
|
||||
{
|
||||
return new UnityVersion(version.Major, version.Minor, version.Build, version.Type, version.TypeNumber);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Expand to 32 bits
|
||||
/// </summary>
|
||||
/// <param name="version">The version to convert</param>
|
||||
public static implicit operator CompactUnityVersion32(CompactUnityVersion24 version)
|
||||
{
|
||||
return new CompactUnityVersion32(version.Major, version.Minor, version.Build, version.Type, version.TypeNumber);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compact to 24 bits
|
||||
/// </summary>
|
||||
/// <param name="version"></param>
|
||||
public static explicit operator CompactUnityVersion24(UnityVersion version)
|
||||
{
|
||||
return new CompactUnityVersion24(version.Major, (byte)version.Minor, (byte)version.Build, version.Type, version.TypeNumber);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compact to 24 bits
|
||||
/// </summary>
|
||||
/// <param name="version"></param>
|
||||
public static explicit operator CompactUnityVersion24(CompactUnityVersion32 version)
|
||||
{
|
||||
return new CompactUnityVersion24(version.Major, version.Minor, version.Build, version.Type, version.TypeNumber);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Equality operator
|
||||
/// </summary>
|
||||
/// <param name="left">The left Unity version</param>
|
||||
/// <param name="right">The right Unity version</param>
|
||||
/// <returns></returns>
|
||||
public static bool operator ==(CompactUnityVersion24 left, CompactUnityVersion24 right)
|
||||
{
|
||||
return left.m_MajorMinorByte == right.m_MajorMinorByte && left.m_BuildTypeShort == right.m_BuildTypeShort;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inequality operator
|
||||
/// </summary>
|
||||
/// <param name="left">The left Unity version</param>
|
||||
/// <param name="right">The right Unity version</param>
|
||||
/// <returns></returns>
|
||||
public static bool operator !=(CompactUnityVersion24 left, CompactUnityVersion24 right)
|
||||
{
|
||||
return left.m_MajorMinorByte != right.m_MajorMinorByte || left.m_BuildTypeShort != right.m_BuildTypeShort;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Greater than
|
||||
/// </summary>
|
||||
/// <param name="left">The left Unity version</param>
|
||||
/// <param name="right">The right Unity version</param>
|
||||
/// <returns></returns>
|
||||
public static bool operator >(CompactUnityVersion24 left, CompactUnityVersion24 right)
|
||||
{
|
||||
return (left.m_MajorMinorByte > right.m_MajorMinorByte) ||
|
||||
(left.m_MajorMinorByte == right.m_MajorMinorByte && left.m_BuildTypeShort > right.m_BuildTypeShort);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Greater than or equal to
|
||||
/// </summary>
|
||||
/// <param name="left">The left Unity version</param>
|
||||
/// <param name="right">The right Unity version</param>
|
||||
/// <returns></returns>
|
||||
public static bool operator >=(CompactUnityVersion24 left, CompactUnityVersion24 right)
|
||||
{
|
||||
return (left.m_MajorMinorByte > right.m_MajorMinorByte) ||
|
||||
(left.m_MajorMinorByte == right.m_MajorMinorByte && left.m_BuildTypeShort >= right.m_BuildTypeShort);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Less than
|
||||
/// </summary>
|
||||
/// <param name="left">The left Unity version</param>
|
||||
/// <param name="right">The right Unity version</param>
|
||||
/// <returns></returns>
|
||||
public static bool operator <(CompactUnityVersion24 left, CompactUnityVersion24 right)
|
||||
{
|
||||
return (left.m_MajorMinorByte < right.m_MajorMinorByte) ||
|
||||
(left.m_MajorMinorByte == right.m_MajorMinorByte && left.m_BuildTypeShort < right.m_BuildTypeShort);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Less than or equal to
|
||||
/// </summary>
|
||||
/// <param name="left">The left Unity version</param>
|
||||
/// <param name="right">The right Unity version</param>
|
||||
/// <returns></returns>
|
||||
public static bool operator <=(CompactUnityVersion24 left, CompactUnityVersion24 right)
|
||||
{
|
||||
return (left.m_MajorMinorByte < right.m_MajorMinorByte) ||
|
||||
(left.m_MajorMinorByte == right.m_MajorMinorByte && left.m_BuildTypeShort <= right.m_BuildTypeShort);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,202 @@
|
||||
namespace AssetRipper.VersionUtilities;
|
||||
|
||||
/// <summary>
|
||||
/// A compact value type for efficiently storing Unity versions inside 24 bits
|
||||
/// </summary>
|
||||
public partial struct CompactUnityVersion24
|
||||
{
|
||||
private const int majorOffset = 3;
|
||||
private const int buildOffset = 9;
|
||||
private const int typeOffset = 6;
|
||||
|
||||
private const uint bitMask3 = 0x0007U;
|
||||
private const uint bitMask5 = 0x001FU;
|
||||
private const uint bitMask6 = 0x003FU;
|
||||
private const uint bitMask7 = 0x007FU;
|
||||
|
||||
/// <summary>
|
||||
/// 5 bits for the major,
|
||||
/// 3 bits for the minor
|
||||
/// </summary>
|
||||
private readonly byte m_MajorMinorByte;
|
||||
|
||||
/// <summary>
|
||||
/// 7 bits for the build,
|
||||
/// 3 bits for the type,
|
||||
/// 6 bits for the type number
|
||||
/// </summary>
|
||||
private readonly ushort m_BuildTypeShort;
|
||||
|
||||
/// <summary>
|
||||
/// 2042
|
||||
/// </summary>
|
||||
public const ushort MajorMaxValue = (ushort)(31U + 2011U);
|
||||
|
||||
/// <summary>
|
||||
/// 5 bits
|
||||
/// </summary>
|
||||
private byte MajorRaw => unchecked((byte)((m_MajorMinorByte >> majorOffset) & bitMask5));
|
||||
|
||||
/// <summary>
|
||||
/// The first number in a Unity version string. 5 bits.
|
||||
/// Valid values inclusive: 0 - 5, 2017 - 2042
|
||||
/// </summary>
|
||||
public ushort Major => ConvertMajorRawToNormal(MajorRaw);
|
||||
|
||||
/// <summary>
|
||||
/// The second number in a Unity version string. 3 bits
|
||||
/// </summary>
|
||||
public byte Minor => unchecked((byte)(m_MajorMinorByte & bitMask3));
|
||||
|
||||
/// <summary>
|
||||
/// The third number in a Unity version string. 7 bits
|
||||
/// </summary>
|
||||
public byte Build => unchecked((byte)((m_BuildTypeShort >> buildOffset) & bitMask7));
|
||||
|
||||
/// <summary>
|
||||
/// The letter in a Unity version string. 3 bits
|
||||
/// </summary>
|
||||
public UnityVersionType Type => (UnityVersionType)unchecked((byte)((m_BuildTypeShort >> typeOffset) & bitMask3));
|
||||
|
||||
/// <summary>
|
||||
/// The last number in a Unity version string. 6 bits
|
||||
/// </summary>
|
||||
public byte TypeNumber => unchecked((byte)(m_BuildTypeShort & bitMask6));
|
||||
|
||||
/// <summary>
|
||||
/// The minimum value this type can have
|
||||
/// </summary>
|
||||
public static CompactUnityVersion24 MinVersion { get; } = new CompactUnityVersion24((byte)0, (ushort)0);
|
||||
|
||||
/// <summary>
|
||||
/// The maximum value this type can have
|
||||
/// </summary>
|
||||
public static CompactUnityVersion24 MaxVersion { get; } = new CompactUnityVersion24(byte.MaxValue, ushort.MaxValue);
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new Unity version
|
||||
/// </summary>
|
||||
public CompactUnityVersion24(ushort major)
|
||||
{
|
||||
m_MajorMinorByte = unchecked((byte)(ConvertMajorRawToNormal(major) << majorOffset));
|
||||
m_BuildTypeShort = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new Unity version
|
||||
/// </summary>
|
||||
public CompactUnityVersion24(ushort major, byte minor)
|
||||
{
|
||||
m_MajorMinorByte = unchecked((byte)((ConvertMajorRawToNormal(major) << majorOffset) | CastToThreeBits(minor)));
|
||||
m_BuildTypeShort = 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new Unity version
|
||||
/// </summary>
|
||||
public CompactUnityVersion24(ushort major, byte minor, byte build)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
m_MajorMinorByte = (byte)((ConvertMajorRawToNormal(major) << majorOffset) | CastToThreeBits(minor));
|
||||
m_BuildTypeShort = (ushort)(CastToSevenBits(build) << buildOffset);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new Unity version
|
||||
/// </summary>
|
||||
public CompactUnityVersion24(ushort major, byte minor, byte build, UnityVersionType type)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
m_MajorMinorByte = (byte)((ConvertMajorRawToNormal(major) << majorOffset) | CastToThreeBits(minor));
|
||||
m_BuildTypeShort = (ushort)(
|
||||
(CastToSevenBits(build) << buildOffset) |
|
||||
(CastToThreeBits((byte)type) << typeOffset));
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new Unity version
|
||||
/// </summary>
|
||||
public CompactUnityVersion24(ushort major, byte minor, byte build, UnityVersionType type, byte typeNumber)
|
||||
{
|
||||
unchecked
|
||||
{
|
||||
m_MajorMinorByte = (byte)((ConvertMajorRawToNormal(major) << majorOffset) | CastToThreeBits(minor));
|
||||
m_BuildTypeShort = (ushort)(
|
||||
(CastToSevenBits(build) << buildOffset) |
|
||||
(CastToThreeBits((byte)type) << typeOffset) |
|
||||
CastToSixBits(typeNumber));
|
||||
}
|
||||
}
|
||||
|
||||
private CompactUnityVersion24(byte majorMinorByte, ushort buildTypeShort)
|
||||
{
|
||||
m_MajorMinorByte = majorMinorByte;
|
||||
m_BuildTypeShort = buildTypeShort;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts this to its binary representation
|
||||
/// </summary>
|
||||
public void GetBits(out byte majorMinorByte, out ushort buildTypeShort)
|
||||
{
|
||||
majorMinorByte = m_MajorMinorByte;
|
||||
buildTypeShort = m_BuildTypeShort;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts a binary representation into its respective version
|
||||
/// </summary>
|
||||
/// <param name="majorMinorByte"></param>
|
||||
/// <param name="buildTypeShort"></param>
|
||||
/// <returns>A new Unity version with the cooresponding bits</returns>
|
||||
public static CompactUnityVersion24 FromBits(byte majorMinorByte, ushort buildTypeShort) => new CompactUnityVersion24(majorMinorByte, buildTypeShort);
|
||||
|
||||
private static ushort ConvertMajorRawToNormal(byte raw)
|
||||
{
|
||||
return raw < 6 ? raw : unchecked((ushort)(raw + 2011U));
|
||||
}
|
||||
|
||||
private static byte ConvertMajorRawToNormal(ushort major)
|
||||
{
|
||||
if (major < 6)
|
||||
{
|
||||
return unchecked((byte)major);
|
||||
}
|
||||
else if (major >= 2017 && major <= MajorMaxValue)
|
||||
{
|
||||
return unchecked((byte)(major - 2011U));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(major));
|
||||
}
|
||||
}
|
||||
|
||||
private static byte CastToThreeBits(byte b)
|
||||
{
|
||||
return b <= bitMask3 ? b : throw new ArgumentOutOfRangeException(nameof(b));
|
||||
}
|
||||
|
||||
private static byte CastToSixBits(byte b)
|
||||
{
|
||||
return b <= bitMask6 ? b : throw new ArgumentOutOfRangeException(nameof(b));
|
||||
}
|
||||
|
||||
private static byte CastToSevenBits(byte b)
|
||||
{
|
||||
return b <= bitMask7 ? b : throw new ArgumentOutOfRangeException(nameof(b));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Serialize the version as a string
|
||||
/// </summary>
|
||||
/// <returns>A new string like 2019.4.3f1</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return ((UnityVersion)this).ToString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
namespace AssetRipper.VersionUtilities;
|
||||
|
||||
public partial struct CompactUnityVersion32 : IEquatable<CompactUnityVersion32>, IComparable, IComparable<CompactUnityVersion32>
|
||||
{
|
||||
/// <summary>
|
||||
/// Compare to another object
|
||||
/// </summary>
|
||||
/// <param name="obj">Another object</param>
|
||||
/// <returns>
|
||||
/// 1 if this is larger or the other is not a Unity version<br/>
|
||||
/// -1 if this is smaller<br/>
|
||||
/// 0 if equal
|
||||
/// </returns>
|
||||
public int CompareTo(object? obj)
|
||||
{
|
||||
return obj is CompactUnityVersion32 version ? CompareTo(version) : 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compare two Unity versions
|
||||
/// </summary>
|
||||
/// <param name="other">Another Unity version</param>
|
||||
/// <returns>
|
||||
/// 1 if this is larger<br/>
|
||||
/// -1 if this is smaller<br/>
|
||||
/// 0 if equal
|
||||
/// </returns>
|
||||
public int CompareTo(CompactUnityVersion32 other)
|
||||
{
|
||||
if (this > other)
|
||||
return 1;
|
||||
else if (this < other)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check equality with another object
|
||||
/// </summary>
|
||||
/// <param name="obj">Another object</param>
|
||||
/// <returns>True if they're equal; false otherwise</returns>
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return obj is CompactUnityVersion32 version && this == version;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check equality with another Unity version
|
||||
/// </summary>
|
||||
/// <param name="other">Another Unity version</param>
|
||||
/// <returns>True if they're equal; false otherwise</returns>
|
||||
public bool Equals(CompactUnityVersion32 other) => this == other;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return m_data.GetHashCode();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,88 @@
|
||||
namespace AssetRipper.VersionUtilities;
|
||||
|
||||
public partial struct CompactUnityVersion32
|
||||
{
|
||||
/// <summary>
|
||||
/// Expand to 64 bits
|
||||
/// </summary>
|
||||
/// <param name="version">The version to convert</param>
|
||||
public static implicit operator UnityVersion(CompactUnityVersion32 version)
|
||||
{
|
||||
return new UnityVersion(version.Major, version.Minor, version.Build, version.Type, version.TypeNumber);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compact to 32 bits
|
||||
/// </summary>
|
||||
/// <param name="version"></param>
|
||||
public static explicit operator CompactUnityVersion32(UnityVersion version)
|
||||
{
|
||||
return new CompactUnityVersion32(version.Major, (byte)version.Minor, (byte)version.Build, version.Type, version.TypeNumber);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Equality operator
|
||||
/// </summary>
|
||||
/// <param name="left">The left Unity version</param>
|
||||
/// <param name="right">The right Unity version</param>
|
||||
/// <returns></returns>
|
||||
public static bool operator ==(CompactUnityVersion32 left, CompactUnityVersion32 right)
|
||||
{
|
||||
return left.m_data == right.m_data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inequality operator
|
||||
/// </summary>
|
||||
/// <param name="left">The left Unity version</param>
|
||||
/// <param name="right">The right Unity version</param>
|
||||
/// <returns></returns>
|
||||
public static bool operator !=(CompactUnityVersion32 left, CompactUnityVersion32 right)
|
||||
{
|
||||
return left.m_data != right.m_data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Greater than
|
||||
/// </summary>
|
||||
/// <param name="left">The left Unity version</param>
|
||||
/// <param name="right">The right Unity version</param>
|
||||
/// <returns></returns>
|
||||
public static bool operator >(CompactUnityVersion32 left, CompactUnityVersion32 right)
|
||||
{
|
||||
return left.m_data > right.m_data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Greater than or equal to
|
||||
/// </summary>
|
||||
/// <param name="left">The left Unity version</param>
|
||||
/// <param name="right">The right Unity version</param>
|
||||
/// <returns></returns>
|
||||
public static bool operator >=(CompactUnityVersion32 left, CompactUnityVersion32 right)
|
||||
{
|
||||
return left.m_data >= right.m_data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Less than
|
||||
/// </summary>
|
||||
/// <param name="left">The left Unity version</param>
|
||||
/// <param name="right">The right Unity version</param>
|
||||
/// <returns></returns>
|
||||
public static bool operator <(CompactUnityVersion32 left, CompactUnityVersion32 right)
|
||||
{
|
||||
return left.m_data < right.m_data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Less than or equal to
|
||||
/// </summary>
|
||||
/// <param name="left">The left Unity version</param>
|
||||
/// <param name="right">The right Unity version</param>
|
||||
/// <returns></returns>
|
||||
public static bool operator <=(CompactUnityVersion32 left, CompactUnityVersion32 right)
|
||||
{
|
||||
return left.m_data <= right.m_data;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
namespace AssetRipper.VersionUtilities;
|
||||
|
||||
/// <summary>
|
||||
/// A compact value type for efficiently storing Unity versions inside 32 bits
|
||||
/// </summary>
|
||||
public partial struct CompactUnityVersion32
|
||||
{
|
||||
private const int majorOffset = 24;
|
||||
private const int minorOffset = 20;
|
||||
private const int buildOffset = 12;
|
||||
private const int typeOffset = 8;
|
||||
|
||||
private const uint byteMask = 0x00FFU;
|
||||
private const uint bitMask4 = 0x000FU;
|
||||
|
||||
private readonly uint m_data;
|
||||
|
||||
/// <summary>
|
||||
/// 2266
|
||||
/// </summary>
|
||||
public const ushort MajorMaxValue = (ushort)(byte.MaxValue + 2011U);
|
||||
|
||||
/// <summary>
|
||||
/// 8 bits
|
||||
/// </summary>
|
||||
private byte MajorRaw => unchecked((byte)((m_data >> majorOffset) & byteMask));
|
||||
|
||||
/// <summary>
|
||||
/// The first number in a Unity version string. 8 bits.
|
||||
/// Valid values inclusive: 0 - 5, 2017 - 2266
|
||||
/// </summary>
|
||||
public ushort Major => ConvertMajorRawToNormal(MajorRaw);
|
||||
|
||||
/// <summary>
|
||||
/// The second number in a Unity version string. 4 bits
|
||||
/// </summary>
|
||||
public byte Minor => unchecked((byte)((m_data >> minorOffset) & bitMask4));
|
||||
|
||||
/// <summary>
|
||||
/// The third number in a Unity version string. 8 bits
|
||||
/// </summary>
|
||||
public byte Build => unchecked((byte)((m_data >> buildOffset) & byteMask));
|
||||
|
||||
/// <summary>
|
||||
/// The letter in a Unity version string. 4 bits
|
||||
/// </summary>
|
||||
public UnityVersionType Type => (UnityVersionType)unchecked((byte)((m_data >> typeOffset) & bitMask4));
|
||||
|
||||
/// <summary>
|
||||
/// The last number in a Unity version string. 8 bits
|
||||
/// </summary>
|
||||
public byte TypeNumber => unchecked((byte)(m_data & byteMask));
|
||||
|
||||
/// <summary>
|
||||
/// The minimum value this type can have
|
||||
/// </summary>
|
||||
public static CompactUnityVersion32 MinVersion { get; } = new CompactUnityVersion32(0U);
|
||||
|
||||
/// <summary>
|
||||
/// The maximum value this type can have
|
||||
/// </summary>
|
||||
public static CompactUnityVersion32 MaxVersion { get; } = new CompactUnityVersion32(uint.MaxValue);
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new Unity version
|
||||
/// </summary>
|
||||
public CompactUnityVersion32(ushort major)
|
||||
{
|
||||
m_data = (uint)ConvertMajorRawToNormal(major) << majorOffset;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new Unity version
|
||||
/// </summary>
|
||||
public CompactUnityVersion32(ushort major, byte minor)
|
||||
{
|
||||
m_data = ((uint)ConvertMajorRawToNormal(major) << majorOffset) | ((uint)CastToFourBits(minor) << minorOffset);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new Unity version
|
||||
/// </summary>
|
||||
public CompactUnityVersion32(ushort major, byte minor, byte build)
|
||||
{
|
||||
m_data = ((uint)ConvertMajorRawToNormal(major) << majorOffset) | ((uint)CastToFourBits(minor) << minorOffset) | ((uint)build << buildOffset);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new Unity version
|
||||
/// </summary>
|
||||
public CompactUnityVersion32(ushort major, byte minor, byte build, UnityVersionType type)
|
||||
{
|
||||
m_data = ((uint)ConvertMajorRawToNormal(major) << majorOffset) | ((uint)CastToFourBits(minor) << minorOffset) | ((uint)build << buildOffset)
|
||||
| ((uint)CastToFourBits(type) << typeOffset);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new Unity version
|
||||
/// </summary>
|
||||
public CompactUnityVersion32(ushort major, byte minor, byte build, UnityVersionType type, byte typeNumber)
|
||||
{
|
||||
m_data = ((uint)ConvertMajorRawToNormal(major) << majorOffset) | ((uint)CastToFourBits(minor) << minorOffset) | ((uint)build << buildOffset)
|
||||
| ((uint)CastToFourBits(type) << typeOffset) | typeNumber;
|
||||
}
|
||||
|
||||
private CompactUnityVersion32(uint data)
|
||||
{
|
||||
m_data = data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts this to its binary representation
|
||||
/// </summary>
|
||||
/// <returns>An unsigned integer having the same bits as this</returns>
|
||||
public uint GetBits() => m_data;
|
||||
|
||||
/// <summary>
|
||||
/// Converts a binary representation into its respective version
|
||||
/// </summary>
|
||||
/// <param name="bits">An unsigned integer having the relevant bits</param>
|
||||
/// <returns>A new Unity version with the cooresponding bits</returns>
|
||||
public static CompactUnityVersion32 FromBits(uint bits) => new CompactUnityVersion32(bits);
|
||||
|
||||
private static ushort ConvertMajorRawToNormal(byte raw)
|
||||
{
|
||||
return raw < 6 ? raw : unchecked((ushort)(raw + 2011U));
|
||||
}
|
||||
|
||||
private static byte ConvertMajorRawToNormal(ushort major)
|
||||
{
|
||||
if (major < 6)
|
||||
{
|
||||
return unchecked((byte)major);
|
||||
}
|
||||
else if (major >= 2017 && major <= MajorMaxValue)
|
||||
{
|
||||
return unchecked((byte)(major - 2011U));
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentOutOfRangeException(nameof(major));
|
||||
}
|
||||
}
|
||||
|
||||
private static byte CastToFourBits(byte b)
|
||||
{
|
||||
return b <= bitMask4 ? b : throw new ArgumentOutOfRangeException(nameof(b));
|
||||
}
|
||||
|
||||
private static UnityVersionType CastToFourBits(UnityVersionType type)
|
||||
{
|
||||
return (byte)type <= bitMask4 ? type : throw new ArgumentOutOfRangeException(nameof(type));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Serialize the version as a string
|
||||
/// </summary>
|
||||
/// <returns>A new string like 2019.4.3f1</returns>
|
||||
public override string ToString()
|
||||
{
|
||||
return ((UnityVersion)this).ToString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
namespace AssetRipper.VersionUtilities.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// Unity version extension methods for <see cref="BinaryReader"/>
|
||||
/// </summary>
|
||||
public static class BinaryReaderExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Reads a Unity version from the stream
|
||||
/// </summary>
|
||||
/// <param name="reader">A binary reader</param>
|
||||
/// <returns>The read Unity version</returns>
|
||||
public static UnityVersion ReadUnityVersion(this BinaryReader reader)
|
||||
{
|
||||
return UnityVersion.FromBits(reader.ReadUInt64());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a Unity version from the stream
|
||||
/// </summary>
|
||||
/// <param name="reader">A binary reader</param>
|
||||
/// <returns>The read Unity version</returns>
|
||||
public static CompactUnityVersion32 ReadCompactUnityVersion32(this BinaryReader reader)
|
||||
{
|
||||
return CompactUnityVersion32.FromBits(reader.ReadUInt32());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Reads a Unity version from the stream
|
||||
/// </summary>
|
||||
/// <param name="reader">A binary reader</param>
|
||||
/// <returns>The read Unity version</returns>
|
||||
public static CompactUnityVersion24 ReadCompactUnityVersion24(this BinaryReader reader)
|
||||
{
|
||||
byte b = reader.ReadByte();
|
||||
ushort s = reader.ReadUInt16();
|
||||
return CompactUnityVersion24.FromBits(b, s);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
namespace AssetRipper.VersionUtilities.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// Unity version extension methods for <see cref="BinaryWriter"/>
|
||||
/// </summary>
|
||||
public static class BinaryWriterExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Write a Unity version to the stream
|
||||
/// </summary>
|
||||
/// <param name="writer">A binary writer</param>
|
||||
/// <param name="version">A Unity version</param>
|
||||
public static void Write(this BinaryWriter writer, UnityVersion version)
|
||||
{
|
||||
writer.Write(version.GetBits());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write a Unity version to the stream
|
||||
/// </summary>
|
||||
/// <param name="writer">A binary writer</param>
|
||||
/// <param name="version">A Unity version</param>
|
||||
public static void Write(this BinaryWriter writer, CompactUnityVersion32 version)
|
||||
{
|
||||
writer.Write(version.GetBits());
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Write a Unity version to the stream
|
||||
/// </summary>
|
||||
/// <param name="writer">A binary writer</param>
|
||||
/// <param name="version">A Unity version</param>
|
||||
public static void Write(this BinaryWriter writer, CompactUnityVersion24 version)
|
||||
{
|
||||
version.GetBits(out byte b, out ushort s);
|
||||
writer.Write(b);
|
||||
writer.Write(s);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
namespace AssetRipper.VersionUtilities.Extensions;
|
||||
|
||||
/// <summary>
|
||||
/// Extensions for <see cref="char"/>
|
||||
/// </summary>
|
||||
public static class CharacterExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Parse a character into a Unity Version Type
|
||||
/// </summary>
|
||||
/// <param name="c">The character</param>
|
||||
/// <returns></returns>
|
||||
/// <exception cref="ArgumentException">No version type for character</exception>
|
||||
public static UnityVersionType ToUnityVersionType(this char c)
|
||||
{
|
||||
return c switch
|
||||
{
|
||||
'a' => UnityVersionType.Alpha,
|
||||
'b' => UnityVersionType.Beta,
|
||||
'c' => UnityVersionType.China,
|
||||
'f' => UnityVersionType.Final,
|
||||
'p' => UnityVersionType.Patch,
|
||||
'x' => UnityVersionType.Experimental,
|
||||
_ => throw new ArgumentException($"There is no version type {c}", nameof(c)),
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace AssetRipper.VersionUtilities.Extensions;
|
||||
|
||||
internal static class RegexExtensions
|
||||
{
|
||||
public static bool TryMatch(this Regex regex, string input, [NotNullWhen(true)] out Match? match)
|
||||
{
|
||||
match = regex.Match(input);
|
||||
if (match.Success)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
match = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
[assembly: InternalsVisibleTo("VersionUtilities.Tests")]
|
||||
@@ -1,71 +1,68 @@
|
||||
namespace AssetRipper.VersionUtilities
|
||||
namespace AssetRipper.VersionUtilities;
|
||||
|
||||
public readonly partial struct UnityVersion
|
||||
{
|
||||
public readonly partial struct UnityVersion
|
||||
{
|
||||
private const ulong subMajorMask = 0x0000FFFFFFFFFFFFUL;
|
||||
private const ulong subMinorMask = 0x00000000FFFFFFFFUL;
|
||||
private const ulong subBuildMask = 0x000000000000FFFFUL;
|
||||
private const ulong subTypeMask = 0x00000000000000FFUL;
|
||||
#pragma warning disable CS1591 // Missing XML comment for publicly visible type or member
|
||||
public bool IsEqual(int major) => this == From(major);
|
||||
public bool IsEqual(int major, int minor) => this == From(major, minor);
|
||||
public bool IsEqual(int major, int minor, int build) => this == From(major, minor, build);
|
||||
public bool IsEqual(int major, int minor, int build, UnityVersionType type) => this == From(major, minor, build, type);
|
||||
public bool IsEqual(int major, int minor, int build, UnityVersionType type, int typeNumber) => this == new UnityVersion(major, minor, build, type, typeNumber);
|
||||
public bool IsEqual(string version) => this == Parse(version);
|
||||
public bool IsEqual(ushort major) => this == From(major);
|
||||
public bool IsEqual(ushort major, ushort minor) => this == From(major, minor);
|
||||
public bool IsEqual(ushort major, ushort minor, ushort build) => this == From(major, minor, build);
|
||||
public bool IsEqual(ushort major, ushort minor, ushort build, UnityVersionType type) => this == From(major, minor, build, type);
|
||||
public bool IsEqual(ushort major, ushort minor, ushort build, UnityVersionType type, byte typeNumber) => this == new UnityVersion(major, minor, build, type, typeNumber);
|
||||
public bool IsEqual(string version) => this == Parse(version);
|
||||
|
||||
public bool IsLess(int major) => this < From(major);
|
||||
public bool IsLess(int major, int minor) => this < From(major, minor);
|
||||
public bool IsLess(int major, int minor, int build) => this < From(major, minor, build);
|
||||
public bool IsLess(int major, int minor, int build, UnityVersionType type) => this < From(major, minor, build, type);
|
||||
public bool IsLess(int major, int minor, int build, UnityVersionType type, int typeNumber) => this < new UnityVersion(major, minor, build, type, typeNumber);
|
||||
public bool IsLess(string version) => this < Parse(version);
|
||||
public bool IsLess(ushort major) => this < From(major);
|
||||
public bool IsLess(ushort major, ushort minor) => this < From(major, minor);
|
||||
public bool IsLess(ushort major, ushort minor, ushort build) => this < From(major, minor, build);
|
||||
public bool IsLess(ushort major, ushort minor, ushort build, UnityVersionType type) => this < From(major, minor, build, type);
|
||||
public bool IsLess(ushort major, ushort minor, ushort build, UnityVersionType type, byte typeNumber) => this < new UnityVersion(major, minor, build, type, typeNumber);
|
||||
public bool IsLess(string version) => this < Parse(version);
|
||||
|
||||
public bool IsLessEqual(int major) => this <= From(major);
|
||||
public bool IsLessEqual(int major, int minor) => this <= From(major, minor);
|
||||
public bool IsLessEqual(int major, int minor, int build) => this <= From(major, minor, build);
|
||||
public bool IsLessEqual(int major, int minor, int build, UnityVersionType type) => this <= From(major, minor, build, type);
|
||||
public bool IsLessEqual(int major, int minor, int build, UnityVersionType type, int typeNumber) => this <= new UnityVersion(major, minor, build, type, typeNumber);
|
||||
public bool IsLessEqual(string version) => this <= Parse(version);
|
||||
public bool IsLessEqual(ushort major) => this <= From(major);
|
||||
public bool IsLessEqual(ushort major, ushort minor) => this <= From(major, minor);
|
||||
public bool IsLessEqual(ushort major, ushort minor, ushort build) => this <= From(major, minor, build);
|
||||
public bool IsLessEqual(ushort major, ushort minor, ushort build, UnityVersionType type) => this <= From(major, minor, build, type);
|
||||
public bool IsLessEqual(ushort major, ushort minor, ushort build, UnityVersionType type, byte typeNumber) => this <= new UnityVersion(major, minor, build, type, typeNumber);
|
||||
public bool IsLessEqual(string version) => this <= Parse(version);
|
||||
|
||||
public bool IsGreater(int major) => this > From(major);
|
||||
public bool IsGreater(int major, int minor) => this > From(major, minor);
|
||||
public bool IsGreater(int major, int minor, int build) => this > From(major, minor, build);
|
||||
public bool IsGreater(int major, int minor, int build, UnityVersionType type) => this > From(major, minor, build, type);
|
||||
public bool IsGreater(int major, int minor, int build, UnityVersionType type, int typeNumber) => this > new UnityVersion(major, minor, build, type, typeNumber);
|
||||
public bool IsGreater(string version) => this > Parse(version);
|
||||
public bool IsGreater(ushort major) => this > From(major);
|
||||
public bool IsGreater(ushort major, ushort minor) => this > From(major, minor);
|
||||
public bool IsGreater(ushort major, ushort minor, ushort build) => this > From(major, minor, build);
|
||||
public bool IsGreater(ushort major, ushort minor, ushort build, UnityVersionType type) => this > From(major, minor, build, type);
|
||||
public bool IsGreater(ushort major, ushort minor, ushort build, UnityVersionType type, byte typeNumber) => this > new UnityVersion(major, minor, build, type, typeNumber);
|
||||
public bool IsGreater(string version) => this > Parse(version);
|
||||
|
||||
public bool IsGreaterEqual(int major) => this >= From(major);
|
||||
public bool IsGreaterEqual(int major, int minor) => this >= From(major, minor);
|
||||
public bool IsGreaterEqual(int major, int minor, int build) => this >= From(major, minor, build);
|
||||
public bool IsGreaterEqual(int major, int minor, int build, UnityVersionType type) => this >= From(major, minor, build, type);
|
||||
public bool IsGreaterEqual(int major, int minor, int build, UnityVersionType type, int typeNumber) => this >= new UnityVersion(major, minor, build, type, typeNumber);
|
||||
public bool IsGreaterEqual(string version) => this >= Parse(version);
|
||||
|
||||
private UnityVersion From(int major)
|
||||
{
|
||||
ulong data = ((ulong)(major & 0xFFFF) << 48) | (0x0000FFFFFFFFFFFFUL & m_data);
|
||||
return new UnityVersion(data);
|
||||
}
|
||||
private UnityVersion From(int major, int minor)
|
||||
{
|
||||
ulong data = ((ulong)(major & 0xFFFF) << 48) | ((ulong)(minor & 0xFF) << 40) | (0x000000FFFFFFFFFFUL & m_data);
|
||||
return new UnityVersion(data);
|
||||
}
|
||||
private UnityVersion From(int major, int minor, int build)
|
||||
{
|
||||
ulong data = ((ulong)(major & 0xFFFF) << 48) | ((ulong)(minor & 0xFF) << 40) | ((ulong)(build & 0xFF) << 32) |
|
||||
(0x00000000FFFFFFFFUL & m_data);
|
||||
return new UnityVersion(data);
|
||||
}
|
||||
private UnityVersion From(int major, int minor, int build, UnityVersionType type)
|
||||
{
|
||||
ulong data = ((ulong)(major & 0xFFFF) << 48) | ((ulong)(minor & 0xFF) << 40) | ((ulong)(build & 0xFF) << 32) |
|
||||
((ulong)((int)type & 0xFF) << 24) | (0x0000000000FFFFFFUL & m_data);
|
||||
return new UnityVersion(data);
|
||||
}
|
||||
private UnityVersion From(int major, int minor, int build, UnityVersionType type, int typeNumber)
|
||||
{
|
||||
ulong data = ((ulong)(major & 0xFFFF) << 48) | ((ulong)(minor & 0xFF) << 40) | ((ulong)(build & 0xFF) << 32)
|
||||
| ((ulong)((int)type & 0xFF) << 24) | ((ulong)(typeNumber & 0xFF) << 16) | (0x000000000000FFFFUL & m_data);
|
||||
return new UnityVersion(data);
|
||||
}
|
||||
#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member
|
||||
public bool IsGreaterEqual(ushort major) => this >= From(major);
|
||||
public bool IsGreaterEqual(ushort major, ushort minor) => this >= From(major, minor);
|
||||
public bool IsGreaterEqual(ushort major, ushort minor, ushort build) => this >= From(major, minor, build);
|
||||
public bool IsGreaterEqual(ushort major, ushort minor, ushort build, UnityVersionType type) => this >= From(major, minor, build, type);
|
||||
public bool IsGreaterEqual(ushort major, ushort minor, ushort build, UnityVersionType type, byte typeNumber) => this >= new UnityVersion(major, minor, build, type, typeNumber);
|
||||
public bool IsGreaterEqual(string version) => this >= Parse(version);
|
||||
|
||||
private UnityVersion From(ushort major)
|
||||
{
|
||||
ulong data = ((ulong)major << majorOffset) | subMajorMask & m_data;
|
||||
return new UnityVersion(data);
|
||||
}
|
||||
private UnityVersion From(ushort major, ushort minor)
|
||||
{
|
||||
ulong data = ((ulong)major << majorOffset) | ((ulong)minor << minorOffset) | subMinorMask & m_data;
|
||||
return new UnityVersion(data);
|
||||
}
|
||||
private UnityVersion From(ushort major, ushort minor, ushort build)
|
||||
{
|
||||
ulong data = ((ulong)major << majorOffset) | ((ulong)minor << minorOffset) | ((ulong)build << buildOffset) |
|
||||
subBuildMask & m_data;
|
||||
return new UnityVersion(data);
|
||||
}
|
||||
private UnityVersion From(ushort major, ushort minor, ushort build, UnityVersionType type)
|
||||
{
|
||||
ulong data = ((ulong)major << majorOffset) | ((ulong)minor << minorOffset) | ((ulong)build << buildOffset) |
|
||||
((ulong)(ushort)type << typeOffset) | subTypeMask & m_data;
|
||||
return new UnityVersion(data);
|
||||
}
|
||||
#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
#if NET7_0_OR_GREATER
|
||||
using System.Numerics;
|
||||
|
||||
namespace AssetRipper.VersionUtilities;
|
||||
partial struct UnityVersion : IComparisonOperators<UnityVersion, UnityVersion, bool>, IEqualityOperators<UnityVersion, UnityVersion, bool>, IMinMaxValue<UnityVersion>
|
||||
{
|
||||
static UnityVersion IMinMaxValue<UnityVersion>.MaxValue => MaxVersion;
|
||||
|
||||
static UnityVersion IMinMaxValue<UnityVersion>.MinValue => MinVersion;
|
||||
}
|
||||
#endif
|
||||
@@ -1,63 +1,60 @@
|
||||
using System;
|
||||
namespace AssetRipper.VersionUtilities;
|
||||
|
||||
namespace AssetRipper.VersionUtilities
|
||||
public readonly partial struct UnityVersion : IEquatable<UnityVersion>, IComparable, IComparable<UnityVersion>
|
||||
{
|
||||
public readonly partial struct UnityVersion : IEquatable<UnityVersion>, IComparable, IComparable<UnityVersion>
|
||||
/// <summary>
|
||||
/// Compare to another object
|
||||
/// </summary>
|
||||
/// <param name="obj">Another object</param>
|
||||
/// <returns>
|
||||
/// 1 if this is larger or the other is not a Unity version<br/>
|
||||
/// -1 if this is smaller<br/>
|
||||
/// 0 if equal
|
||||
/// </returns>
|
||||
public int CompareTo(object? obj)
|
||||
{
|
||||
/// <summary>
|
||||
/// Compare to another object
|
||||
/// </summary>
|
||||
/// <param name="obj">Another object</param>
|
||||
/// <returns>
|
||||
/// 1 if this is larger or the other is not a Unity version<br/>
|
||||
/// -1 if this is smaller<br/>
|
||||
/// 0 if equal
|
||||
/// </returns>
|
||||
public int CompareTo(object? obj)
|
||||
{
|
||||
return obj is UnityVersion version ? CompareTo(version) : 1;
|
||||
}
|
||||
return obj is UnityVersion version ? CompareTo(version) : 1;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compare two Unity versions
|
||||
/// </summary>
|
||||
/// <param name="other">Another Unity version</param>
|
||||
/// <returns>
|
||||
/// 1 if this is larger<br/>
|
||||
/// -1 if this is smaller<br/>
|
||||
/// 0 if equal
|
||||
/// </returns>
|
||||
public int CompareTo(UnityVersion other)
|
||||
{
|
||||
if (this > other)
|
||||
return 1;
|
||||
else if (this < other)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
/// <summary>
|
||||
/// Compare two Unity versions
|
||||
/// </summary>
|
||||
/// <param name="other">Another Unity version</param>
|
||||
/// <returns>
|
||||
/// 1 if this is larger<br/>
|
||||
/// -1 if this is smaller<br/>
|
||||
/// 0 if equal
|
||||
/// </returns>
|
||||
public int CompareTo(UnityVersion other)
|
||||
{
|
||||
if (this > other)
|
||||
return 1;
|
||||
else if (this < other)
|
||||
return -1;
|
||||
else
|
||||
return 0;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check equality with another object
|
||||
/// </summary>
|
||||
/// <param name="obj">Another object</param>
|
||||
/// <returns>True if they're equal; false otherwise</returns>
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return obj is UnityVersion version && this == version;
|
||||
}
|
||||
/// <summary>
|
||||
/// Check equality with another object
|
||||
/// </summary>
|
||||
/// <param name="obj">Another object</param>
|
||||
/// <returns>True if they're equal; false otherwise</returns>
|
||||
public override bool Equals(object? obj)
|
||||
{
|
||||
return obj is UnityVersion version && this == version;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Check equality with another Unity version
|
||||
/// </summary>
|
||||
/// <param name="other">Another Unity version</param>
|
||||
/// <returns>True if they're equal; false otherwise</returns>
|
||||
public bool Equals(UnityVersion other) => this == other;
|
||||
/// <summary>
|
||||
/// Check equality with another Unity version
|
||||
/// </summary>
|
||||
/// <param name="other">Another Unity version</param>
|
||||
/// <returns>True if they're equal; false otherwise</returns>
|
||||
public bool Equals(UnityVersion other) => this == other;
|
||||
|
||||
/// <inheritdoc/>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return unchecked(827 + 911 * m_data.GetHashCode());
|
||||
}
|
||||
/// <inheritdoc/>
|
||||
public override int GetHashCode()
|
||||
{
|
||||
return unchecked(827 + 911 * m_data.GetHashCode());
|
||||
}
|
||||
}
|
||||
@@ -1,47 +1,80 @@
|
||||
namespace AssetRipper.VersionUtilities
|
||||
namespace AssetRipper.VersionUtilities;
|
||||
|
||||
public readonly partial struct UnityVersion
|
||||
{
|
||||
public readonly partial struct UnityVersion
|
||||
/// <summary>
|
||||
/// A maximizing function for Unity versions
|
||||
/// </summary>
|
||||
/// <param name="left">A Unity version</param>
|
||||
/// <param name="right">A Unity version</param>
|
||||
/// <returns>The larger Unity version</returns>
|
||||
public static UnityVersion Max(UnityVersion left, UnityVersion right)
|
||||
{
|
||||
/// <summary>
|
||||
/// A maximizing function for Unity versions
|
||||
/// </summary>
|
||||
/// <param name="left">A Unity version</param>
|
||||
/// <param name="right">A Unity version</param>
|
||||
/// <returns>The larger Unity version</returns>
|
||||
public static UnityVersion Max(UnityVersion left, UnityVersion right)
|
||||
return left > right ? left : right;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A minimizing function for Unity versions
|
||||
/// </summary>
|
||||
/// <param name="left">A Unity version</param>
|
||||
/// <param name="right">A Unity version</param>
|
||||
/// <returns>The smaller Unity version</returns>
|
||||
public static UnityVersion Min(UnityVersion left, UnityVersion right)
|
||||
{
|
||||
return left < right ? left : right;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A distance function for measuring version proximity
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The returned value is ordinal and should not be saved anywhere.
|
||||
/// It's only for runtime comparisons, such as finding the closest version in a list.
|
||||
/// </remarks>
|
||||
/// <param name="left">A Unity version</param>
|
||||
/// <param name="right">A Unity version</param>
|
||||
/// <returns>
|
||||
/// An ordinal number representing the distance between 2 versions.
|
||||
/// A value of zero means they're equal.
|
||||
/// </returns>
|
||||
public static ulong Distance(UnityVersion left, UnityVersion right)
|
||||
{
|
||||
return left.m_data < right.m_data
|
||||
? right.m_data - left.m_data
|
||||
: left.m_data - right.m_data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the closest Unity version in an array of versions using <see cref="Distance(UnityVersion, UnityVersion)"/>
|
||||
/// </summary>
|
||||
/// <param name="versions">The Unity version array</param>
|
||||
/// <returns>The closest Unity version</returns>
|
||||
/// <exception cref="ArgumentNullException">The array is null</exception>
|
||||
/// <exception cref="ArgumentException">The array is empty</exception>
|
||||
public UnityVersion GetClosestVersion(UnityVersion[] versions)
|
||||
{
|
||||
if (versions is null)
|
||||
{
|
||||
return left > right ? left : right;
|
||||
throw new ArgumentNullException(nameof(versions));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A minimizing function for Unity versions
|
||||
/// </summary>
|
||||
/// <param name="left">A Unity version</param>
|
||||
/// <param name="right">A Unity version</param>
|
||||
/// <returns>The smaller Unity version</returns>
|
||||
public static UnityVersion Min(UnityVersion left, UnityVersion right)
|
||||
if (versions.Length == 0)
|
||||
{
|
||||
return left < right ? left : right;
|
||||
throw new ArgumentException("Length cannot be zero", nameof(versions));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// A distance function for measuring version proximity
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The returned value is ordinal and should not be saved anywhere.
|
||||
/// It's only for runtime comparisons, such as finding the closest version in a list.
|
||||
/// </remarks>
|
||||
/// <param name="left">A Unity version</param>
|
||||
/// <param name="right">A Unity version</param>
|
||||
/// <returns>
|
||||
/// An ordinal number representing the distance between 2 versions.
|
||||
/// A value of zero means they're equal.
|
||||
/// </returns>
|
||||
public static ulong Distance(UnityVersion left, UnityVersion right)
|
||||
UnityVersion result = versions[0];
|
||||
ulong currentDistance = Distance(this, result);
|
||||
for(int i = 1; i < versions.Length; i++)
|
||||
{
|
||||
return left.m_data < right.m_data
|
||||
? right.m_data - left.m_data
|
||||
: left.m_data - right.m_data;
|
||||
ulong newDistance = Distance(this, versions[i]);
|
||||
if (newDistance < currentDistance)
|
||||
{
|
||||
currentDistance = newDistance;
|
||||
result = versions[i];
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
namespace AssetRipper.VersionUtilities;
|
||||
partial struct UnityVersion
|
||||
{
|
||||
/// <summary>
|
||||
/// Change <see cref="Major"/>.
|
||||
/// </summary>
|
||||
/// <param name="value">The new value</param>
|
||||
/// <returns>A new <see cref="UnityVersion"/> with the changed value.</returns>
|
||||
public UnityVersion ChangeMajor(ushort value) => new UnityVersion(value, Minor, Build, Type, TypeNumber);
|
||||
|
||||
/// <summary>
|
||||
/// Change <see cref="Minor"/>.
|
||||
/// </summary>
|
||||
/// <param name="value">The new value</param>
|
||||
/// <returns>A new <see cref="UnityVersion"/> with the changed value.</returns>
|
||||
public UnityVersion ChangeMinor(ushort value) => new UnityVersion(Major, value, Build, Type, TypeNumber);
|
||||
|
||||
/// <summary>
|
||||
/// Change <see cref="Build"/>.
|
||||
/// </summary>
|
||||
/// <param name="value">The new value</param>
|
||||
/// <returns>A new <see cref="UnityVersion"/> with the changed value.</returns>
|
||||
public UnityVersion ChangeBuild(ushort value) => new UnityVersion(Major, Minor, value, Type, TypeNumber);
|
||||
|
||||
/// <summary>
|
||||
/// Change <see cref="Type"/>.
|
||||
/// </summary>
|
||||
/// <param name="value">The new value</param>
|
||||
/// <returns>A new <see cref="UnityVersion"/> with the changed value.</returns>
|
||||
public UnityVersion ChangeType(UnityVersionType value) => new UnityVersion(Major, Minor, Build, value, TypeNumber);
|
||||
|
||||
/// <summary>
|
||||
/// Change <see cref="TypeNumber"/>.
|
||||
/// </summary>
|
||||
/// <param name="value">The new value</param>
|
||||
/// <returns>A new <see cref="UnityVersion"/> with the changed value.</returns>
|
||||
public UnityVersion ChangeTypeNumber(byte value) => new UnityVersion(Major, Minor, Build, Type, value);
|
||||
}
|
||||
@@ -1,71 +1,70 @@
|
||||
namespace AssetRipper.VersionUtilities
|
||||
namespace AssetRipper.VersionUtilities;
|
||||
|
||||
public readonly partial struct UnityVersion
|
||||
{
|
||||
public readonly partial struct UnityVersion
|
||||
/// <summary>
|
||||
/// Equality operator
|
||||
/// </summary>
|
||||
/// <param name="left">The left Unity version</param>
|
||||
/// <param name="right">The right Unity version</param>
|
||||
/// <returns></returns>
|
||||
public static bool operator ==(UnityVersion left, UnityVersion right)
|
||||
{
|
||||
/// <summary>
|
||||
/// Equality operator
|
||||
/// </summary>
|
||||
/// <param name="left">The left Unity version</param>
|
||||
/// <param name="right">The right Unity version</param>
|
||||
/// <returns></returns>
|
||||
public static bool operator ==(UnityVersion left, UnityVersion right)
|
||||
{
|
||||
return left.m_data == right.m_data;
|
||||
}
|
||||
return left.m_data == right.m_data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Inequality operator
|
||||
/// </summary>
|
||||
/// <param name="left">The left Unity version</param>
|
||||
/// <param name="right">The right Unity version</param>
|
||||
/// <returns></returns>
|
||||
public static bool operator !=(UnityVersion left, UnityVersion right)
|
||||
{
|
||||
return left.m_data != right.m_data;
|
||||
}
|
||||
/// <summary>
|
||||
/// Inequality operator
|
||||
/// </summary>
|
||||
/// <param name="left">The left Unity version</param>
|
||||
/// <param name="right">The right Unity version</param>
|
||||
/// <returns></returns>
|
||||
public static bool operator !=(UnityVersion left, UnityVersion right)
|
||||
{
|
||||
return left.m_data != right.m_data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Greater than
|
||||
/// </summary>
|
||||
/// <param name="left">The left Unity version</param>
|
||||
/// <param name="right">The right Unity version</param>
|
||||
/// <returns></returns>
|
||||
public static bool operator >(UnityVersion left, UnityVersion right)
|
||||
{
|
||||
return left.m_data > right.m_data;
|
||||
}
|
||||
/// <summary>
|
||||
/// Greater than
|
||||
/// </summary>
|
||||
/// <param name="left">The left Unity version</param>
|
||||
/// <param name="right">The right Unity version</param>
|
||||
/// <returns></returns>
|
||||
public static bool operator >(UnityVersion left, UnityVersion right)
|
||||
{
|
||||
return left.m_data > right.m_data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Greater than or equal to
|
||||
/// </summary>
|
||||
/// <param name="left">The left Unity version</param>
|
||||
/// <param name="right">The right Unity version</param>
|
||||
/// <returns></returns>
|
||||
public static bool operator >=(UnityVersion left, UnityVersion right)
|
||||
{
|
||||
return left.m_data >= right.m_data;
|
||||
}
|
||||
/// <summary>
|
||||
/// Greater than or equal to
|
||||
/// </summary>
|
||||
/// <param name="left">The left Unity version</param>
|
||||
/// <param name="right">The right Unity version</param>
|
||||
/// <returns></returns>
|
||||
public static bool operator >=(UnityVersion left, UnityVersion right)
|
||||
{
|
||||
return left.m_data >= right.m_data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Less than
|
||||
/// </summary>
|
||||
/// <param name="left">The left Unity version</param>
|
||||
/// <param name="right">The right Unity version</param>
|
||||
/// <returns></returns>
|
||||
public static bool operator <(UnityVersion left, UnityVersion right)
|
||||
{
|
||||
return left.m_data < right.m_data;
|
||||
}
|
||||
/// <summary>
|
||||
/// Less than
|
||||
/// </summary>
|
||||
/// <param name="left">The left Unity version</param>
|
||||
/// <param name="right">The right Unity version</param>
|
||||
/// <returns></returns>
|
||||
public static bool operator <(UnityVersion left, UnityVersion right)
|
||||
{
|
||||
return left.m_data < right.m_data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Less than or equal to
|
||||
/// </summary>
|
||||
/// <param name="left">The left Unity version</param>
|
||||
/// <param name="right">The right Unity version</param>
|
||||
/// <returns></returns>
|
||||
public static bool operator <=(UnityVersion left, UnityVersion right)
|
||||
{
|
||||
return left.m_data <= right.m_data;
|
||||
}
|
||||
/// <summary>
|
||||
/// Less than or equal to
|
||||
/// </summary>
|
||||
/// <param name="left">The left Unity version</param>
|
||||
/// <param name="right">The right Unity version</param>
|
||||
/// <returns></returns>
|
||||
public static bool operator <=(UnityVersion left, UnityVersion right)
|
||||
{
|
||||
return left.m_data <= right.m_data;
|
||||
}
|
||||
}
|
||||
@@ -1,167 +1,124 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Text;
|
||||
using AssetRipper.VersionUtilities.Extensions;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
namespace AssetRipper.VersionUtilities
|
||||
namespace AssetRipper.VersionUtilities;
|
||||
|
||||
public readonly partial struct UnityVersion
|
||||
{
|
||||
public readonly partial struct UnityVersion
|
||||
private static readonly Regex majorMinorRegex = new Regex(@"^([0-9]+)\.([0-9]+)$", RegexOptions.Compiled);
|
||||
private static readonly Regex majorMinorBuildRegex = new Regex(@"^([0-9]+)\.([0-9]+)\.([0-9]+)$", RegexOptions.Compiled);
|
||||
private static readonly Regex normalRegex = new Regex(@"^([0-9]+)\.([0-9]+)\.([0-9]+)\.?([abcfpx])([0-9]+)(\n[0-9]+)?$", RegexOptions.Compiled);
|
||||
private static readonly Regex chinaRegex = new Regex(@"^([0-9]+)\.([0-9]+)\.([0-9]+)\.?f1c([0-9]+)(\n[0-9]+)?$", RegexOptions.Compiled);
|
||||
|
||||
/// <summary>
|
||||
/// Serialize the version as a string using <see cref="UnityVersionFormatFlags.Default"/>.
|
||||
/// </summary>
|
||||
/// <returns>A new string like 2019.4.3f1</returns>
|
||||
public override string ToString() => ToString(UnityVersionFormatFlags.Default);
|
||||
|
||||
/// <summary>
|
||||
/// Serialize the version as a string
|
||||
/// </summary>
|
||||
/// <param name="flags">The flags to control how the version is formatted</param>
|
||||
/// <returns>A new string containing the formatted version.</returns>
|
||||
public string ToString(UnityVersionFormatFlags flags)
|
||||
{
|
||||
/// <summary>
|
||||
/// Serialize the version as a string
|
||||
/// </summary>
|
||||
/// <returns>A new string like 2019.4.3f1</returns>
|
||||
public override string ToString()
|
||||
return (flags & UnityVersionFormatFlags.ExcludeType) != 0
|
||||
? ToStringWithoutType()
|
||||
: Type is not UnityVersionType.China || (flags & UnityVersionFormatFlags.UseShortChineseFormat) != 0
|
||||
? $"{Major}.{Minor}.{Build}{Type.ToCharacter()}{TypeNumber}"
|
||||
: $"{Major}.{Minor}.{Build}f1c{TypeNumber}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Serialize the version as a string
|
||||
/// </summary>
|
||||
/// <param name="flags">The flags to control how the version is formatted</param>
|
||||
/// <param name="customEngineNumber">The custom engine number to be appended</param>
|
||||
/// <returns>A new string containing the formatted version.</returns>
|
||||
public string ToString(UnityVersionFormatFlags flags, int? customEngineNumber)
|
||||
{
|
||||
return customEngineNumber is null
|
||||
? ToString(flags)
|
||||
: (flags & UnityVersionFormatFlags.ExcludeType) != 0
|
||||
? ToStringWithoutType()
|
||||
: Type is not UnityVersionType.China || (flags & UnityVersionFormatFlags.UseShortChineseFormat) != 0
|
||||
? $"{Major}.{Minor}.{Build}{Type.ToCharacter()}{TypeNumber}\n{customEngineNumber}"
|
||||
: $"{Major}.{Minor}.{Build}f1c{TypeNumber}\n{customEngineNumber}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Serialize the version as a string using only <see cref="Major"/>, <see cref="Minor"/>, and <see cref="Build"/>.
|
||||
/// </summary>
|
||||
/// <returns>A new string like 2019.4.3</returns>
|
||||
public string ToStringWithoutType()
|
||||
{
|
||||
return $"{Major}.{Minor}.{Build}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a normal Unity version string
|
||||
/// </summary>
|
||||
/// <param name="version">A string to parse</param>
|
||||
/// <returns>The parsed Unity version</returns>
|
||||
/// <exception cref="ArgumentNullException">If the string is null or empty</exception>
|
||||
/// <exception cref="ArgumentException">If the string is in an invalid format</exception>
|
||||
public static UnityVersion Parse(string version) => Parse(version, out _);
|
||||
|
||||
/// <summary>
|
||||
/// Parse a normal Unity version string
|
||||
/// </summary>
|
||||
/// <param name="version">A string to parse</param>
|
||||
/// <param name="customEngine">True if this version was generated by a custom Unity Engine.</param>
|
||||
/// <returns>The parsed Unity version</returns>
|
||||
/// <exception cref="ArgumentNullException">If the string is null or empty</exception>
|
||||
/// <exception cref="ArgumentException">If the string is in an invalid format</exception>
|
||||
public static UnityVersion Parse(string version, out int? customEngine)
|
||||
{
|
||||
if (string.IsNullOrEmpty(version))
|
||||
{
|
||||
return $"{Major}.{Minor}.{Build}{Type.ToLiteral()}{TypeNumber}";
|
||||
throw new ArgumentNullException(nameof(version));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Serialize the version as a string
|
||||
/// </summary>
|
||||
/// <param name="hasUnderscorePrefix">Include the _ prefix</param>
|
||||
/// <param name="useUnderscores">Use underscores as separators instead of periods</param>
|
||||
/// <param name="hasExtension">Include the .dll extension</param>
|
||||
/// <returns>A new string generated with those parameters</returns>
|
||||
public string ToString(bool hasUnderscorePrefix, bool useUnderscores, bool hasExtension)
|
||||
if (normalRegex.TryMatch(version, out Match? match))
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
char separator = useUnderscores ? '_' : '.';
|
||||
|
||||
if(hasUnderscorePrefix)
|
||||
sb.Append('_');
|
||||
|
||||
sb.Append(Major);
|
||||
sb.Append(separator);
|
||||
sb.Append(Minor);
|
||||
sb.Append(separator);
|
||||
sb.Append(Build);
|
||||
sb.Append(separator);
|
||||
sb.Append(Type.ToLiteral());
|
||||
sb.Append(TypeNumber);
|
||||
|
||||
if(hasExtension)
|
||||
sb.Append(".dll");
|
||||
|
||||
return sb.ToString();
|
||||
int major = int.Parse(match.Groups[1].Value);
|
||||
int minor = int.Parse(match.Groups[2].Value);
|
||||
int build = int.Parse(match.Groups[3].Value);
|
||||
char type = match.Groups[4].Value[0];
|
||||
int typeNumber = int.Parse(match.Groups[5].Value);
|
||||
customEngine = ParseNullableInteger(match.Groups[6]);
|
||||
return new UnityVersion((ushort)major, (ushort)minor, (ushort)build, type.ToUnityVersionType(), (byte)typeNumber);
|
||||
}
|
||||
else if (majorMinorBuildRegex.TryMatch(version, out match))
|
||||
{
|
||||
int major = int.Parse(match.Groups[1].Value);
|
||||
int minor = int.Parse(match.Groups[2].Value);
|
||||
int build = int.Parse(match.Groups[3].Value);
|
||||
customEngine = null;
|
||||
return new UnityVersion((ushort)major, (ushort)minor, (ushort)build, UnityVersionType.Final, 1);
|
||||
}
|
||||
else if (majorMinorRegex.TryMatch(version, out match))
|
||||
{
|
||||
int major = int.Parse(match.Groups[1].Value);
|
||||
int minor = int.Parse(match.Groups[2].Value);
|
||||
customEngine = null;
|
||||
return new UnityVersion((ushort)major, (ushort)minor, 0, UnityVersionType.Final, 1);
|
||||
}
|
||||
else if (chinaRegex.TryMatch(version, out match))
|
||||
{
|
||||
int major = int.Parse(match.Groups[1].Value);
|
||||
int minor = int.Parse(match.Groups[2].Value);
|
||||
int build = int.Parse(match.Groups[3].Value);
|
||||
int typeNumber = int.Parse(match.Groups[4].Value);
|
||||
customEngine = ParseNullableInteger(match.Groups[5]);
|
||||
return new UnityVersion((ushort)major, (ushort)minor, (ushort)build, UnityVersionType.China, (byte)typeNumber);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new ArgumentException($"Invalid version format: {version}", nameof(version));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Serialize the version as a string
|
||||
/// </summary>
|
||||
/// <returns>A new string like 2019.4.3</returns>
|
||||
public string ToStringWithoutType()
|
||||
{
|
||||
return $"{Major}.{Minor}.{Build}";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a dll name like _2019_4_3f1.dll
|
||||
/// </summary>
|
||||
/// <param name="dllName">The name of a dll file</param>
|
||||
/// <returns>The parsed Unity version</returns>
|
||||
/// <exception cref="ArgumentNullException">If the string is null or empty</exception>
|
||||
public static UnityVersion ParseFromDllName(string dllName)
|
||||
{
|
||||
if (string.IsNullOrEmpty(dllName))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(dllName));
|
||||
}
|
||||
if (dllName[0] == '_')
|
||||
{
|
||||
dllName = dllName.Substring(1);
|
||||
}
|
||||
|
||||
return Parse(dllName.Replace('_', '.').Replace(".dll", ""));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Parse a normal Unity version string
|
||||
/// </summary>
|
||||
/// <param name="version">A string to parse</param>
|
||||
/// <returns>The parsed Unity version</returns>
|
||||
/// <exception cref="ArgumentNullException">If the string is null or empty</exception>
|
||||
/// <exception cref="ArgumentException">If the string is in an invalid format</exception>
|
||||
public static UnityVersion Parse(string version)
|
||||
{
|
||||
if (string.IsNullOrEmpty(version))
|
||||
{
|
||||
throw new ArgumentNullException(nameof(version));
|
||||
}
|
||||
|
||||
int major = 0;
|
||||
int minor = 0;
|
||||
int build = 0;
|
||||
UnityVersionType versionType = UnityVersionType.Final;
|
||||
int typeNumber = 0;
|
||||
|
||||
using StringReader reader = new StringReader(version);
|
||||
|
||||
while (true)
|
||||
{
|
||||
int symb = reader.Read();
|
||||
if (symb == -1)
|
||||
{
|
||||
throw new ArgumentException($"Invalid version formatting: {version}", nameof(version));
|
||||
}
|
||||
char c = (char)symb;
|
||||
if (c == '.')
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
major = major * 10 + c.ParseDigit();
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
int symb = reader.Read();
|
||||
if (symb == -1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
char c = (char)symb;
|
||||
if (c == '.')
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
minor = minor * 10 + c.ParseDigit();
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
int symb = reader.Read();
|
||||
if (symb == -1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
char c = (char)symb;
|
||||
if (char.IsDigit(c))
|
||||
{
|
||||
build = build * 10 + c.ParseDigit();
|
||||
}
|
||||
else
|
||||
{
|
||||
versionType = c.ToUnityVersionType();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
while (true)
|
||||
{
|
||||
int symb = reader.Read();
|
||||
if (symb == -1)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
char c = (char)symb;
|
||||
typeNumber = typeNumber * 10 + c.ParseDigit();
|
||||
}
|
||||
|
||||
return new UnityVersion(major, minor, build, versionType, typeNumber);
|
||||
}
|
||||
static int? ParseNullableInteger(Capture capture) => capture.Length == 0 ? null : int.Parse(capture.Value);
|
||||
}
|
||||
}
|
||||
@@ -1,92 +1,112 @@
|
||||
namespace AssetRipper.VersionUtilities
|
||||
namespace AssetRipper.VersionUtilities;
|
||||
|
||||
/// <summary>
|
||||
/// A value type for holding Unity versions
|
||||
/// </summary>
|
||||
public readonly partial struct UnityVersion
|
||||
{
|
||||
private const int majorOffset = 48;
|
||||
private const int minorOffset = 32;
|
||||
private const int buildOffset = 16;
|
||||
private const int typeOffset = 8;
|
||||
|
||||
private const ulong byteMask = 0xFFUL;
|
||||
private const ulong ushortMask = 0xFFFFUL;
|
||||
|
||||
private readonly ulong m_data;
|
||||
|
||||
/// <summary>
|
||||
/// A value type for holding Unity versions
|
||||
/// The first number in a Unity version string
|
||||
/// </summary>
|
||||
public readonly partial struct UnityVersion
|
||||
public ushort Major => unchecked((ushort)((m_data >> majorOffset) & ushortMask));
|
||||
|
||||
/// <summary>
|
||||
/// The second number in a Unity version string
|
||||
/// </summary>
|
||||
public ushort Minor => unchecked((ushort)((m_data >> minorOffset) & ushortMask));
|
||||
|
||||
/// <summary>
|
||||
/// The third number in a Unity version string
|
||||
/// </summary>
|
||||
public ushort Build => unchecked((ushort)((m_data >> buildOffset) & ushortMask));
|
||||
|
||||
/// <summary>
|
||||
/// The letter in a Unity version string
|
||||
/// </summary>
|
||||
public UnityVersionType Type => (UnityVersionType)unchecked((byte)((m_data >> typeOffset) & byteMask));
|
||||
|
||||
/// <summary>
|
||||
/// The last number in a Unity version string
|
||||
/// </summary>
|
||||
public byte TypeNumber => unchecked((byte)(m_data & byteMask));
|
||||
|
||||
/// <summary>
|
||||
/// The minimum value this type can have
|
||||
/// </summary>
|
||||
public static UnityVersion MinVersion { get; } = new UnityVersion(0UL);
|
||||
|
||||
/// <summary>
|
||||
/// The maximum value this type can have
|
||||
/// </summary>
|
||||
public static UnityVersion MaxVersion { get; } = new UnityVersion(ulong.MaxValue);
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new Unity version
|
||||
/// </summary>
|
||||
public UnityVersion(ushort major)
|
||||
{
|
||||
private readonly ulong m_data;
|
||||
|
||||
/// <summary>
|
||||
/// The first number in a Unity version string
|
||||
/// </summary>
|
||||
public int Major => unchecked((int)((m_data >> 48) & 0xFFFFUL));
|
||||
|
||||
/// <summary>
|
||||
/// The second number in a Unity version string
|
||||
/// </summary>
|
||||
public int Minor => unchecked((int)((m_data >> 40) & 0xFFUL));
|
||||
|
||||
/// <summary>
|
||||
/// The third number in a Unity version string
|
||||
/// </summary>
|
||||
public int Build => unchecked((int)((m_data >> 32) & 0xFFUL));
|
||||
|
||||
/// <summary>
|
||||
/// The letter in a Unity version string
|
||||
/// </summary>
|
||||
public UnityVersionType Type => (UnityVersionType)unchecked((int)((m_data >> 24) & 0xFFUL));
|
||||
|
||||
/// <summary>
|
||||
/// The last number in a Unity version string
|
||||
/// </summary>
|
||||
public int TypeNumber => unchecked((int)((m_data >> 16) & 0xFFUL));
|
||||
|
||||
/// <summary>
|
||||
/// The minimum value this type can have
|
||||
/// </summary>
|
||||
public static UnityVersion MinVersion { get; } = new UnityVersion(0UL);
|
||||
|
||||
/// <summary>
|
||||
/// The maximum value this type can have
|
||||
/// </summary>
|
||||
public static UnityVersion MaxVersion { get; } = new UnityVersion(ulong.MaxValue);
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new Unity version
|
||||
/// </summary>
|
||||
public UnityVersion(int major)
|
||||
{
|
||||
m_data = (ulong)(major & 0xFFFF) << 48;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new Unity version
|
||||
/// </summary>
|
||||
public UnityVersion(int major, int minor)
|
||||
{
|
||||
m_data = ((ulong)(major & 0xFFFF) << 48) | ((ulong)(minor & 0xFF) << 40);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new Unity version
|
||||
/// </summary>
|
||||
public UnityVersion(int major, int minor, int build)
|
||||
{
|
||||
m_data = ((ulong)(major & 0xFFFF) << 48) | ((ulong)(minor & 0xFF) << 40) | ((ulong)(build & 0xFF) << 32);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new Unity version
|
||||
/// </summary>
|
||||
public UnityVersion(int major, int minor, int build, UnityVersionType type)
|
||||
{
|
||||
m_data = ((ulong)(major & 0xFFFF) << 48) | ((ulong)(minor & 0xFF) << 40) | ((ulong)(build & 0xFF) << 32)
|
||||
| ((ulong)((int)type & 0xFF) << 24);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new Unity version
|
||||
/// </summary>
|
||||
public UnityVersion(int major, int minor, int build, UnityVersionType type, int typeNumber)
|
||||
{
|
||||
m_data = ((ulong)(major & 0xFFFF) << 48) | ((ulong)(minor & 0xFF) << 40) | ((ulong)(build & 0xFF) << 32)
|
||||
| ((ulong)((int)type & 0xFF) << 24) | ((ulong)(typeNumber & 0xFF) << 16);
|
||||
}
|
||||
|
||||
private UnityVersion(ulong data)
|
||||
{
|
||||
m_data = data;
|
||||
}
|
||||
m_data = (ulong)major << majorOffset;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new Unity version
|
||||
/// </summary>
|
||||
public UnityVersion(ushort major, ushort minor)
|
||||
{
|
||||
m_data = ((ulong)major << majorOffset) | ((ulong)minor << minorOffset);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new Unity version
|
||||
/// </summary>
|
||||
public UnityVersion(ushort major, ushort minor, ushort build)
|
||||
{
|
||||
m_data = ((ulong)major << majorOffset) | ((ulong)minor << minorOffset) | ((ulong)build << buildOffset);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new Unity version
|
||||
/// </summary>
|
||||
public UnityVersion(ushort major, ushort minor, ushort build, UnityVersionType type)
|
||||
{
|
||||
m_data = ((ulong)major << majorOffset) | ((ulong)minor << minorOffset) | ((ulong)build << buildOffset)
|
||||
| ((ulong)type << typeOffset);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Construct a new Unity version
|
||||
/// </summary>
|
||||
public UnityVersion(ushort major, ushort minor, ushort build, UnityVersionType type, byte typeNumber)
|
||||
{
|
||||
m_data = ((ulong)major << majorOffset) | ((ulong)minor << minorOffset) | ((ulong)build << buildOffset)
|
||||
| ((ulong)type << typeOffset) | typeNumber;
|
||||
}
|
||||
|
||||
private UnityVersion(ulong data)
|
||||
{
|
||||
m_data = data;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Converts this to its binary representation
|
||||
/// </summary>
|
||||
/// <returns>An unsigned long integer having the same bits as this</returns>
|
||||
public ulong GetBits() => m_data;
|
||||
|
||||
/// <summary>
|
||||
/// Converts a binary representation into its respective version
|
||||
/// </summary>
|
||||
/// <param name="bits">An unsigned long integer having the relevant bits</param>
|
||||
/// <returns>A new Unity version with the cooresponding bits</returns>
|
||||
public static UnityVersion FromBits(ulong bits) => new UnityVersion(bits);
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
namespace AssetRipper.VersionUtilities;
|
||||
|
||||
/// <summary>
|
||||
/// Flags used when formatting a <see cref="UnityVersion"/>
|
||||
/// </summary>
|
||||
[Flags]
|
||||
public enum UnityVersionFormatFlags
|
||||
{
|
||||
/// <summary>
|
||||
/// The default flags when formatting.
|
||||
/// </summary>
|
||||
Default = 0,
|
||||
/// <summary>
|
||||
/// Exclude <see cref="UnityVersion.Type"/>, <see cref="UnityVersion.TypeNumber"/>, and the custom engine number when formatting.
|
||||
/// </summary>
|
||||
ExcludeType = 1 << 0,
|
||||
/// <summary>
|
||||
/// Format chinese versions as 2019.4.3c1 rather than 2019.4.3f1c1
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// An example of the long version can be found in 'unity editor resources' and 'unity_builtin_extra' for the <see href="https://unity.cn/release-notes/full/2019/2019.4.40f1">2019.4.40f1c1</see> version.<br/>
|
||||
/// An example of the short version can be found in <see href="https://github.com/AssetRipper/AssetRipper/issues/841"/>.
|
||||
/// </remarks>
|
||||
UseShortChineseFormat = 1 << 1,
|
||||
}
|
||||
@@ -1,70 +1,67 @@
|
||||
using System;
|
||||
namespace AssetRipper.VersionUtilities;
|
||||
|
||||
namespace AssetRipper.VersionUtilities
|
||||
/// <summary>
|
||||
/// An enumeration representing the letter in a Unity Version string
|
||||
/// </summary>
|
||||
public enum UnityVersionType : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// An enumeration representing the letter in a Unity Version string
|
||||
/// a
|
||||
/// </summary>
|
||||
public enum UnityVersionType
|
||||
{
|
||||
/// <summary>
|
||||
/// a
|
||||
/// </summary>
|
||||
Alpha = 0,
|
||||
/// <summary>
|
||||
/// b
|
||||
/// </summary>
|
||||
Beta,
|
||||
/// <summary>
|
||||
/// c
|
||||
/// </summary>
|
||||
China,
|
||||
/// <summary>
|
||||
/// f
|
||||
/// </summary>
|
||||
Final,
|
||||
/// <summary>
|
||||
/// p
|
||||
/// </summary>
|
||||
Patch,
|
||||
/// <summary>
|
||||
/// x
|
||||
/// </summary>
|
||||
Experimental,
|
||||
|
||||
/// <summary>
|
||||
/// The minimum valid value for this enumeration
|
||||
/// </summary>
|
||||
MinValue = Alpha,
|
||||
/// <summary>
|
||||
/// The maximum valid value for this enumeration
|
||||
/// </summary>
|
||||
MaxValue = Experimental,
|
||||
}
|
||||
Alpha = 0,
|
||||
/// <summary>
|
||||
/// b
|
||||
/// </summary>
|
||||
Beta,
|
||||
/// <summary>
|
||||
/// c
|
||||
/// </summary>
|
||||
China,
|
||||
/// <summary>
|
||||
/// f
|
||||
/// </summary>
|
||||
Final,
|
||||
/// <summary>
|
||||
/// p
|
||||
/// </summary>
|
||||
Patch,
|
||||
/// <summary>
|
||||
/// x
|
||||
/// </summary>
|
||||
Experimental,
|
||||
|
||||
/// <summary>
|
||||
/// Extension methods for <see cref="UnityVersionType"/>
|
||||
/// The minimum valid value for this enumeration
|
||||
/// </summary>
|
||||
public static class UnityVersionTypeExtentions
|
||||
MinValue = Alpha,
|
||||
/// <summary>
|
||||
/// The maximum valid value for this enumeration
|
||||
/// </summary>
|
||||
MaxValue = Experimental,
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extension methods for <see cref="UnityVersionType"/>
|
||||
/// </summary>
|
||||
public static class UnityVersionTypeExtentions
|
||||
{
|
||||
/// <summary>
|
||||
/// Convert to the relevant character
|
||||
/// </summary>
|
||||
/// <param name="type">A Unity version type</param>
|
||||
/// <returns>The character this value represents</returns>
|
||||
/// <exception cref="ArgumentOutOfRangeException">The type is not a valid value</exception>
|
||||
public static char ToCharacter(this UnityVersionType type)
|
||||
{
|
||||
/// <summary>
|
||||
/// Convert to the relevant character
|
||||
/// </summary>
|
||||
/// <param name="_this">A Unity version type</param>
|
||||
/// <returns>The character this value represents</returns>
|
||||
/// <exception cref="ArgumentOutOfRangeException">The type is not a valid value</exception>
|
||||
public static char ToLiteral(this UnityVersionType _this)
|
||||
return type switch
|
||||
{
|
||||
return _this switch
|
||||
{
|
||||
UnityVersionType.Alpha => 'a',
|
||||
UnityVersionType.Beta => 'b',
|
||||
UnityVersionType.China => 'c',
|
||||
UnityVersionType.Final => 'f',
|
||||
UnityVersionType.Patch => 'p',
|
||||
UnityVersionType.Experimental => 'x',
|
||||
_ => throw new ArgumentOutOfRangeException(nameof(_this), $"Unsupported version type {_this}"),
|
||||
};
|
||||
}
|
||||
UnityVersionType.Alpha => 'a',
|
||||
UnityVersionType.Beta => 'b',
|
||||
UnityVersionType.China => 'c',
|
||||
UnityVersionType.Final => 'f',
|
||||
UnityVersionType.Patch => 'p',
|
||||
UnityVersionType.Experimental => 'x',
|
||||
_ => 'u',//unknown
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,2 @@
|
||||
global using System;
|
||||
global using System.IO;
|
||||
@@ -1,26 +1,41 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFrameworks>netframework3.5;netframework4.0;netstandard2.0;net5.0;net6.0</TargetFrameworks>
|
||||
<TargetFrameworks>netframework3.5;netframework4.0;netstandard2.0;net5.0;net6.0;net7.0</TargetFrameworks>
|
||||
<LangVersion>Latest</LangVersion>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>disable</ImplicitUsings>
|
||||
<RootNamespace>AssetRipper.VersionUtilities</RootNamespace>
|
||||
<AssemblyName>AssetRipper.VersionUtilities</AssemblyName>
|
||||
<Authors>ds5678</Authors>
|
||||
<Company>AssetRipper</Company>
|
||||
<Version>1.0.1.0</Version>
|
||||
<AssemblyVersion>1.0.1.0</AssemblyVersion>
|
||||
<Version>1.5.0.0</Version>
|
||||
<AssemblyVersion>$(Version)</AssemblyVersion>
|
||||
<PackageId>AssetRipper.VersionUtilities</PackageId>
|
||||
<PackageTags>C# version unity unity3d</PackageTags>
|
||||
<RepositoryUrl>https://github.com/AssetRipper/VersionUtilities</RepositoryUrl>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<RepositoryType>git</RepositoryType>
|
||||
<PackageProjectUrl>https://github.com/AssetRipper/VersionUtilities</PackageProjectUrl>
|
||||
<Copyright>Copyright (c) 2022 ds5678</Copyright>
|
||||
<Copyright>Copyright (c) 2022-$([System.DateTime]::Now.Year) ds5678</Copyright>
|
||||
<Description>Managed library for handling Unity versions</Description>
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<DocumentationFile>bin\VersionUtilities.xml</DocumentationFile>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(TargetFramework)' != 'netframework3.5' and '$(TargetFramework)' != 'netframework4.0' ">
|
||||
<IsTrimmable>true</IsTrimmable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="PolySharp" Version="1.13.2">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
Reference in new issue
Block a user