Compare commits

...
55 Commits
Author SHA1 Message Date
ds5678 ca701a43dc Bump version 2024-12-19 13:51:34 -08:00
ds5678 f478cd8015 Make regexes more strict 2024-12-19 13:50:51 -08:00
dependabot[bot] 8cd69e8946 Bump actions/setup-dotnet from 4.0.1 to 4.1.0
Bumps [actions/setup-dotnet](https://github.com/actions/setup-dotnet) from 4.0.1 to 4.1.0.
- [Release notes](https://github.com/actions/setup-dotnet/releases)
- [Commits](https://github.com/actions/setup-dotnet/compare/v4.0.1...v4.1.0)

---
updated-dependencies:
- dependency-name: actions/setup-dotnet
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-12-19 13:32:52 -08:00
dependabot[bot] 3cba893ff2 Bump actions/setup-dotnet from 4.0.0 to 4.0.1
Bumps [actions/setup-dotnet](https://github.com/actions/setup-dotnet) from 4.0.0 to 4.0.1.
- [Release notes](https://github.com/actions/setup-dotnet/releases)
- [Commits](https://github.com/actions/setup-dotnet/compare/v4.0.0...v4.0.1)

---
updated-dependencies:
- dependency-name: actions/setup-dotnet
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-08-06 21:29:50 -07:00
ds5678 9c4a7d8127 Bump version 2024-08-06 19:42:08 -07:00
ds5678 fd3590ad52 Tiered Regex compilation 2024-08-06 19:37:36 -07:00
ds5678 3ef5dae9d4 IEqualityOperators 2024-06-09 16:57:21 -07:00
ds5678 78ecfb7de4 Bump version 2024-05-31 07:23:23 -07:00
ds5678 5080b7eb29 Add net461 target 2024-05-31 07:17:06 -07:00
ds5678 2e8940973f Bump version 2024-05-19 17:40:14 -04:00
ds5678 64f50b46fb Add .NET 8 to the CI workflow 2024-05-19 17:34:41 -04:00
ds5678 fbdda777ac Remove package reference to System.Text.Json 2024-05-19 17:32:46 -04:00
ds5678 2de06bfaf4 .NET target 2024-05-19 17:28:57 -04:00
ds5678 c7a8932863 Remove benchmarks 2024-05-19 17:25:33 -04:00
ds5678 4bcc823371 Bump version 2024-04-20 15:55:53 -07:00
ds5678 7630da6da0 Improve parsing of version zero 2024-04-20 15:55:14 -07:00
ds5678 e5802e39ee Parse with only the major version 2024-04-20 15:44:19 -07:00
ds5678 c663c68124 Bump version 2024-04-15 19:51:42 -07:00
dependabot[bot] fa2458cfae Bump Microsoft.NET.Test.Sdk from 17.8.0 to 17.9.0
Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 17.8.0 to 17.9.0.
- [Release notes](https://github.com/microsoft/vstest/releases)
- [Changelog](https://github.com/microsoft/vstest/blob/main/docs/releases.md)
- [Commits](https://github.com/microsoft/vstest/compare/v17.8.0...v17.9.0)

---
updated-dependencies:
- dependency-name: Microsoft.NET.Test.Sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-04-15 08:04:23 -07:00
dependabot[bot] ee923d8e9b Bump coverlet.collector from 6.0.0 to 6.0.2
Bumps [coverlet.collector](https://github.com/coverlet-coverage/coverlet) from 6.0.0 to 6.0.2.
- [Release notes](https://github.com/coverlet-coverage/coverlet/releases)
- [Commits](https://github.com/coverlet-coverage/coverlet/compare/v6.0.0...v6.0.2)

---
updated-dependencies:
- dependency-name: coverlet.collector
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-04-15 08:04:14 -07:00
dependabot[bot] 8b23a0c671 Bump NUnit.Analyzers from 3.10.0 to 4.1.0
Bumps [NUnit.Analyzers](https://github.com/nunit/nunit.analyzers) from 3.10.0 to 4.1.0.
- [Release notes](https://github.com/nunit/nunit.analyzers/releases)
- [Changelog](https://github.com/nunit/nunit.analyzers/blob/master/CHANGES.txt)
- [Commits](https://github.com/nunit/nunit.analyzers/compare/3.10.0...4.1.0)

---
updated-dependencies:
- dependency-name: NUnit.Analyzers
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-04-15 08:04:04 -07:00
ds5678 f56feaf217 Remove incorrect code for Unity 6 2024-04-14 22:20:30 -07:00
ds5678 bd575f0063 Bump Version
* Expand support for UnityGuid and Utf8String to .NET Standard
2024-01-15 00:19:28 -05:00
dependabot[bot] 0a6b003bf2 Bump BenchmarkDotNet from 0.13.11 to 0.13.12
Bumps [BenchmarkDotNet](https://github.com/dotnet/BenchmarkDotNet) from 0.13.11 to 0.13.12.
- [Release notes](https://github.com/dotnet/BenchmarkDotNet/releases)
- [Commits](https://github.com/dotnet/BenchmarkDotNet/compare/v0.13.11...v0.13.12)

---
updated-dependencies:
- dependency-name: BenchmarkDotNet
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2024-01-09 09:38:48 -05:00
dependabot[bot] f4026adfd0 Bump PolySharp from 1.14.0 to 1.14.1
Bumps [PolySharp](https://github.com/Sergio0694/PolySharp) from 1.14.0 to 1.14.1.
- [Release notes](https://github.com/Sergio0694/PolySharp/releases)
- [Commits](https://github.com/Sergio0694/PolySharp/compare/1.14.0...1.14.1)

---
updated-dependencies:
- dependency-name: PolySharp
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2023-12-18 15:14:12 -05:00
Jeremy Pritts 8954b81f81 Bump version 2023-12-12 02:15:13 -05:00
Jeremy Pritts 856d05dafe Add UnityGuid.ToString(Span) 2023-12-12 02:13:45 -05:00
dependabot[bot] b88ae7c46f Bump BenchmarkDotNet from 0.13.10 to 0.13.11
Bumps [BenchmarkDotNet](https://github.com/dotnet/BenchmarkDotNet) from 0.13.10 to 0.13.11.
- [Release notes](https://github.com/dotnet/BenchmarkDotNet/releases)
- [Commits](https://github.com/dotnet/BenchmarkDotNet/compare/v0.13.10...v0.13.11)

---
updated-dependencies:
- dependency-name: BenchmarkDotNet
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2023-12-08 15:04:58 -05:00
dependabot[bot] 4c4289fddd Bump actions/setup-dotnet from 3.2.0 to 4.0.0
Bumps [actions/setup-dotnet](https://github.com/actions/setup-dotnet) from 3.2.0 to 4.0.0.
- [Release notes](https://github.com/actions/setup-dotnet/releases)
- [Commits](https://github.com/actions/setup-dotnet/compare/v3.2.0...v4.0.0)

---
updated-dependencies:
- dependency-name: actions/setup-dotnet
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
2023-12-04 14:22:13 -05:00
dependabot[bot] 379034a536 Bump NUnit.Analyzers from 3.9.0 to 3.10.0
Bumps [NUnit.Analyzers](https://github.com/nunit/nunit.analyzers) from 3.9.0 to 3.10.0.
- [Release notes](https://github.com/nunit/nunit.analyzers/releases)
- [Changelog](https://github.com/nunit/nunit.analyzers/blob/master/CHANGES.txt)
- [Commits](https://github.com/nunit/nunit.analyzers/compare/3.9.0...3.10.0)

---
updated-dependencies:
- dependency-name: NUnit.Analyzers
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2023-11-28 15:46:52 -05:00
dependabot[bot] 428756101a Bump PolySharp from 1.13.2 to 1.14.0
Bumps [PolySharp](https://github.com/Sergio0694/PolySharp) from 1.13.2 to 1.14.0.
- [Release notes](https://github.com/Sergio0694/PolySharp/releases)
- [Commits](https://github.com/Sergio0694/PolySharp/commits)

---
updated-dependencies:
- dependency-name: PolySharp
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2023-11-28 15:46:37 -05:00
Jeremy Pritts dc15723135 Update AssetRipper.Primitives.Benckmarks.csproj 2023-11-28 15:46:11 -05:00
Jeremy Pritts 6452151c5c Update AssetRipper.Primitives.Benckmarks.csproj 2023-11-28 15:44:31 -05:00
Jeremy Pritts 3bbd130e76 Add benchmarks project 2023-11-21 17:14:59 -05:00
Jeremy Pritts 2ab6b413c4 Handle 2017 - 2023 being between 5 and 6 2023-11-20 14:54:28 -05:00
Jeremy Pritts 29fc3f655c Rename comparison methods 2023-11-20 13:51:33 -05:00
Jeremy Pritts 71efe9e898 Add overloads 2023-11-17 11:18:11 -05:00
Jeremy Pritts c51c22a15c SequentialUnityVersionComparer 2023-11-17 09:05:07 -05:00
dependabot[bot] 83d16e30d0 Bump Microsoft.SourceLink.GitHub from 1.1.1 to 8.0.0
Bumps [Microsoft.SourceLink.GitHub](https://github.com/dotnet/sourcelink) from 1.1.1 to 8.0.0.
- [Release notes](https://github.com/dotnet/sourcelink/releases)
- [Commits](https://github.com/dotnet/sourcelink/commits)

---
updated-dependencies:
- dependency-name: Microsoft.SourceLink.GitHub
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
2023-11-16 13:30:42 -05:00
dependabot[bot] 0fe68a61ba Bump Microsoft.NET.Test.Sdk from 17.7.2 to 17.8.0
Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 17.7.2 to 17.8.0.
- [Release notes](https://github.com/microsoft/vstest/releases)
- [Changelog](https://github.com/microsoft/vstest/blob/main/docs/releases.md)
- [Commits](https://github.com/microsoft/vstest/compare/v17.7.2...v17.8.0)

---
updated-dependencies:
- dependency-name: Microsoft.NET.Test.Sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2023-11-08 15:46:53 -05:00
dependabot[bot] 964baafad1 Bump NUnit from 3.13.3 to 3.14.0
Bumps [NUnit](https://github.com/nunit/nunit) from 3.13.3 to 3.14.0.
- [Release notes](https://github.com/nunit/nunit/releases)
- [Changelog](https://github.com/nunit/nunit/blob/master/CHANGES.md)
- [Commits](https://github.com/nunit/nunit/compare/v3.13.3...v3.14.0)

---
updated-dependencies:
- dependency-name: NUnit
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2023-11-06 13:54:57 -05:00
dependabot[bot] 264694de87 Bump NUnit.Analyzers from 3.8.0 to 3.9.0
Bumps [NUnit.Analyzers](https://github.com/nunit/nunit.analyzers) from 3.8.0 to 3.9.0.
- [Release notes](https://github.com/nunit/nunit.analyzers/releases)
- [Changelog](https://github.com/nunit/nunit.analyzers/blob/master/CHANGES.txt)
- [Commits](https://github.com/nunit/nunit.analyzers/compare/3.8.0...3.9.0)

---
updated-dependencies:
- dependency-name: NUnit.Analyzers
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2023-10-30 16:09:01 -04:00
dependabot[bot] 406bc21ad8 Bump NUnit.Analyzers from 3.7.0 to 3.8.0
Bumps [NUnit.Analyzers](https://github.com/nunit/nunit.analyzers) from 3.7.0 to 3.8.0.
- [Release notes](https://github.com/nunit/nunit.analyzers/releases)
- [Changelog](https://github.com/nunit/nunit.analyzers/blob/master/CHANGES.txt)
- [Commits](https://github.com/nunit/nunit.analyzers/compare/3.7.0...3.8.0)

---
updated-dependencies:
- dependency-name: NUnit.Analyzers
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2023-09-25 16:21:26 -04:00
dependabot[bot] f852851d24 Bump NUnit.Analyzers from 3.6.1 to 3.7.0
Bumps [NUnit.Analyzers](https://github.com/nunit/nunit.analyzers) from 3.6.1 to 3.7.0.
- [Release notes](https://github.com/nunit/nunit.analyzers/releases)
- [Changelog](https://github.com/nunit/nunit.analyzers/blob/master/CHANGES.txt)
- [Commits](https://github.com/nunit/nunit.analyzers/compare/3.6.1...3.7.0)

---
updated-dependencies:
- dependency-name: NUnit.Analyzers
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2023-09-18 14:43:44 -04:00
Jeremy Pritts d9b73345a6 Update Parse documentation 2023-09-14 23:07:34 -04:00
Jeremy Pritts 167d4242b0 TryParse 2023-09-14 23:06:41 -04:00
Jeremy Pritts 87a0f969a5 Bump version to 2.0.1 2023-09-13 22:22:05 -04:00
dependabot[bot] f499511551 Bump actions/checkout from 3 to 4
Bumps [actions/checkout](https://github.com/actions/checkout) from 3 to 4.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v3...v4)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <[email protected]>
2023-09-04 18:21:21 -04:00
dependabot[bot] 94ad139e22 Bump Microsoft.NET.Test.Sdk from 17.7.1 to 17.7.2
Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 17.7.1 to 17.7.2.
- [Release notes](https://github.com/microsoft/vstest/releases)
- [Changelog](https://github.com/microsoft/vstest/blob/main/docs/releases.md)
- [Commits](https://github.com/microsoft/vstest/compare/v17.7.1...v17.7.2)

---
updated-dependencies:
- dependency-name: Microsoft.NET.Test.Sdk
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2023-08-29 14:54:24 -04:00
Jeremy Pritts 3b8d4eb470 Resolve #40 2023-08-22 10:24:26 -04:00
dependabot[bot] a96a32e87e Bump Microsoft.NET.Test.Sdk from 17.7.0 to 17.7.1
Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 17.7.0 to 17.7.1.
- [Release notes](https://github.com/microsoft/vstest/releases)
- [Changelog](https://github.com/microsoft/vstest/blob/main/docs/releases.md)
- [Commits](https://github.com/microsoft/vstest/compare/v17.7.0...v17.7.1)

---
updated-dependencies:
- dependency-name: Microsoft.NET.Test.Sdk
  dependency-type: direct:production
  update-type: version-update:semver-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2023-08-16 18:16:11 -04:00
Jeremy Pritts e9d121c927 Fix test 2023-08-07 11:22:46 -04:00
Jeremy Pritts eedce8a128 Utf8String concatenation 2023-08-07 10:41:28 -04:00
Jeremy Pritts f67c61a3d5 Check for emptiness when converting to Utf8String 2023-08-07 10:40:56 -04:00
dependabot[bot] 878aa3d815 Bump Microsoft.NET.Test.Sdk from 17.6.3 to 17.7.0
Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 17.6.3 to 17.7.0.
- [Release notes](https://github.com/microsoft/vstest/releases)
- [Changelog](https://github.com/microsoft/vstest/blob/main/docs/releases.md)
- [Commits](https://github.com/microsoft/vstest/compare/v17.6.3...v17.7.0)

---
updated-dependencies:
- dependency-name: Microsoft.NET.Test.Sdk
  dependency-type: direct:production
  update-type: version-update:semver-minor
...

Signed-off-by: dependabot[bot] <[email protected]>
2023-08-04 14:49:42 -04:00
14 changed files with 607 additions and 128 deletions

No files matched your search

+24 -9
View File
@@ -7,14 +7,31 @@ on:
branches: [ master ]
jobs:
net8:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/[email protected]
with:
dotnet-version: 8.0.x
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build --framework net8.0 --no-restore
- name: Test
run: dotnet test --framework net8.0 --no-build --verbosity normal
net7:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v3.2.0
uses: actions/setup-dotnet@v4.1.0
with:
dotnet-version: 7.0.x
- name: Restore dependencies
@@ -29,9 +46,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v3.2.0
uses: actions/setup-dotnet@v4.1.0
with:
dotnet-version: 6.0.x
- name: Restore dependencies
@@ -46,13 +63,11 @@ jobs:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/setup-dotnet@v3.2.0
uses: actions/setup-dotnet@v4.1.0
with:
dotnet-version: |
5.0.x
6.0.x
dotnet-version: 5.0.x
- name: Restore dependencies
run: dotnet restore
- name: Build
@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netframework3.5;netframework4.0;netframework4.8;net5.0;net6.0;net7.0</TargetFrameworks>
<TargetFrameworks>net35;net40;net48;net5.0;net6.0;net7.0;net8.0</TargetFrameworks>
<LangVersion>Latest</LangVersion>
<Nullable>enable</Nullable>
@@ -9,14 +9,14 @@
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.6.3" />
<PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.9.0" />
<PackageReference Include="NUnit" Version="3.14.0" />
<PackageReference Include="NUnit3TestAdapter" Version="4.5.0" />
<PackageReference Include="NUnit.Analyzers" Version="3.6.1">
<PackageReference Include="NUnit.Analyzers" Version="4.1.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="6.0.0" />
<PackageReference Include="coverlet.collector" Version="6.0.2" />
</ItemGroup>
<ItemGroup>
@@ -68,8 +68,8 @@ public class ComparisonTests
{
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);
Assert.That(new UnityVersion(2019, 1, 0, UnityVersionType.Final, 1).GreaterThanOrEquals(2019, 1, 0));
Assert.That(new UnityVersion(2019, 1, 0, UnityVersionType.Final, 1).LessThanOrEquals(2019, 1, 0));
});
}
}
+29 -7
View File
@@ -6,22 +6,28 @@ namespace AssetRipper.Primitives.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("4.2.2f1\n1", 4, 2, 2, UnityVersionType.Final, 1, "\n1", "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.2.2f1c2\n2", 2019, 2, 2, UnityVersionType.China, 2, "\n2", "Fake Custom Chinese Version")]
[TestCase("2019", 2019, 0, 0, UnityVersionType.Final, 1, null, "Major Only")]
[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)
[TestCase("0", 0, 0, 0, UnityVersionType.Alpha, 0, null, "Zero, Major Only")]
[TestCase("0.0", 0, 0, 0, UnityVersionType.Alpha, 0, null, "Zero, Major Minor Only")]
[TestCase("0.0.0", 0, 0, 0, UnityVersionType.Alpha, 0, null, "Zero, Major Minor Build Only")]
[TestCase("0.0.0b2", 0, 0, 0, UnityVersionType.Beta, 2, null, "Zero, Full")]
[TestCase("2019.2.2f1-letters", 2019, 2, 2, UnityVersionType.Final, 1, "-letters", "Issue #40 - Appended Custom Characters")]
public void UnityVersionParsesCorrectly(string versionString, int major, int minor, int build, UnityVersionType type, int typeNumber, string? customEngine, string name)
{
UnityVersion expected = new UnityVersion((ushort)major, (ushort)minor, (ushort)build, type, (byte)typeNumber);
UnityVersion parsedVersion = UnityVersion.Parse(versionString, out int? parsedCustomEngine);
UnityVersion parsedVersion = UnityVersion.Parse(versionString, out string? 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)
if (customEngine is not null || typeNumber is not 0 and not 1)
{
Assert.That(parsedVersion.ToString(UnityVersionFormatFlags.Default, parsedCustomEngine), Is.EqualTo(versionString));
Assert.That(parsedVersion.ToString(UnityVersionFormatFlags.Default, parsedCustomEngine ?? ""), Is.EqualTo(versionString));
}
});
}
@@ -30,7 +36,7 @@ public class ParsingTests
public void UnityVersionToStringParsesCorrectly(UnityVersion version)
{
string versionString = version.ToString();
UnityVersion parsedVersion = UnityVersion.Parse(versionString, out int? customEngine);
UnityVersion parsedVersion = UnityVersion.Parse(versionString, out string? customEngine);
Assert.Multiple(() =>
{
Assert.That(customEngine, Is.Null);
@@ -67,6 +73,22 @@ public class ParsingTests
});
}
[TestCase("g2019")]
[TestCase("g2019.4")]
[TestCase("g2019.4.3")]
[TestCase("g2019.4.3f")]
[TestCase("g2019.4.3f1")]
[TestCase("g2019.4.3f1c1")]
[TestCase("2019g")]
[TestCase("2019.4g")]
[TestCase("2019.4.3g")]
[TestCase("2019.4.3fg")]
// "2019.4.3f1g" and "2019.4.3f1c1g" are technically valid because custom engines often append some text to the version string.
public void InvalidVersionStringFailsToParse(string versionString)
{
Assert.That(UnityVersion.TryParse(versionString, out _, out _), Is.False);
}
private static IEnumerable<UnityVersion> GenerateRandomVersions(int count)
{
Randomizer random = TestContext.CurrentContext.Random;
@@ -1,4 +1,4 @@
#if NET7_0_OR_GREATER
#if NET5_0_OR_GREATER
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
@@ -83,7 +83,7 @@ public class UnityGuidTests
{
Guid originalGuid = Guid.NewGuid();
UnityGuid tobyteArrayGuid = new UnityGuid(originalGuid.ToByteArray());
UnityGuid memoryMarshallGuid = new UnityGuid(MemoryMarshal.Cast<Guid, byte>(new ReadOnlySpan<Guid>(in originalGuid)));
UnityGuid memoryMarshallGuid = Unsafe.As<Guid, UnityGuid>(ref originalGuid);
Assert.That(memoryMarshallGuid, Is.EqualTo(tobyteArrayGuid));
}
}
@@ -1,8 +1,17 @@
#if NET7_0_OR_GREATER
#if NET5_0_OR_GREATER
namespace AssetRipper.Primitives.Tests;
public class Utf8StringTests
{
[Test]
public void Utf8StringEqualityWorks()
{
Utf8String utf8Str = new Utf8String("AssetRipperTestString");
Utf8String utf8Str2 = new Utf8String(utf8Str.Data.ToArray());
Assert.That(utf8Str2, Is.EqualTo(utf8Str));
}
[Test]
public void StringEmptyIsEquivalentToUtf8StringEmpty()
{
@@ -28,5 +37,51 @@ public class Utf8StringTests
Utf8String systemString = "AssetRipperTestString";
Assert.That(dataString, Is.EqualTo(systemString));
}
[Test]
public void ConcatenationBetweenTwoUtf8StringsWorks()
{
Utf8String dataString = "AssetRipperTestString"u8;
Utf8String systemString = "AssetRipperTestString";
Utf8String concatenated = dataString + systemString;
Assert.That(concatenated, Is.EqualTo((Utf8String)"AssetRipperTestStringAssetRipperTestString"u8));
}
[Test]
public void ConcatenationBetweenThreeUtf8StringsWorksTheSameAsAddition()
{
Utf8String added = "String1"u8 + new Utf8String("2") + "3"u8;
Utf8String concatenated = Utf8String.Concat("String1"u8, "2"u8, "3"u8);
Assert.That(added, Is.EqualTo(concatenated));
}
[Test]
public void ConcatenationBetweenFourUtf8StringsWorks()
{
Utf8String string1 = "hello"u8;
Utf8String string2 = " world"u8;
Utf8String string3 = "!"u8;
Utf8String string4 = ", how are you?"u8;
Utf8String concatenated = Utf8String.Concat(string1, string2, string3, string4);
Assert.That(concatenated, Is.EqualTo((Utf8String)"hello world!, how are you?"u8));
}
[Test]
public void IsNullOrEmptyReturnsTrueForEmptyString()
{
Assert.That(Utf8String.IsNullOrEmpty(Utf8String.Empty), Is.True);
}
[Test]
public void IsNullOrEmptyReturnsTrueForNullString()
{
Assert.That(Utf8String.IsNullOrEmpty(null), Is.True);
}
[Test]
public void IsNullOrEmptyReturnsFalseForNonEmptyString()
{
Assert.That(Utf8String.IsNullOrEmpty("AssetRipperTestString"u8), Is.False);
}
}
#endif
@@ -1,12 +1,12 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netframework3.5;netframework4.0;netstandard2.0;net5.0;net6.0;net7.0</TargetFrameworks>
<TargetFrameworks>net35;net40;net461;netstandard2.0;net5.0;net6.0;net7.0;net8.0</TargetFrameworks>
<LangVersion>Latest</LangVersion>
<Nullable>enable</Nullable>
<Authors>ds5678</Authors>
<Company>AssetRipper</Company>
<Version>2.0.0.0</Version>
<Version>3.1.4</Version>
<AssemblyVersion>$(Version)</AssemblyVersion>
<PackageId>AssetRipper.Primitives</PackageId>
<PackageTags>C# assetripper unity unity3d</PackageTags>
@@ -14,26 +14,45 @@
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<RepositoryType>git</RepositoryType>
<PackageProjectUrl>https://github.com/AssetRipper/AssetRipper.Primitives</PackageProjectUrl>
<Copyright>Copyright (c) 2022-2023 ds5678</Copyright>
<Copyright>Copyright (c) 2022-2024 ds5678</Copyright>
<Description>Managed library for primitive types used in AssetRipper.</Description>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>1591</NoWarn>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' != 'netframework3.5' and '$(TargetFramework)' != 'netframework4.0' ">
<PropertyGroup Condition=" '$(TargetFramework)' != 'net35' and '$(TargetFramework)' != 'net40' ">
<IsTrimmable>true</IsTrimmable>
</PropertyGroup>
<PropertyGroup Condition=" '$(TargetFramework)' == 'net8.0' ">
<IsAotCompatible>true</IsAotCompatible>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1">
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="PolySharp" Version="1.13.2">
<PackageReference Include="PolySharp" Version="1.14.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard2.0' or '$(TargetFramework)' == 'net461'">
<PackageReference Include="Microsoft.Bcl.HashCode">
<Version>1.1.1</Version>
</PackageReference>
<PackageReference Include="System.Memory">
<Version>4.5.5</Version>
</PackageReference>
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net461'">
<PackageReference Include="System.ValueTuple">
<Version>4.5.0</Version>
</PackageReference>
</ItemGroup>
</Project>
+73 -13
View File
@@ -1,21 +1,31 @@
#if NET7_0_OR_GREATER
#if NET5_0_OR_GREATER || NETSTANDARD2_0_OR_GREATER || NET461_OR_GREATER
using System.Buffers.Binary;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json.Serialization;
namespace AssetRipper.Primitives;
[JsonConverter(typeof(UnityGuidJsonConverter))]
#if NET5_0_OR_GREATER
[System.Text.Json.Serialization.JsonConverter(typeof(UnityGuidJsonConverter))]
#endif
public readonly record struct UnityGuid
#if NET7_0_OR_GREATER
: System.Numerics.IEqualityOperators<UnityGuid, UnityGuid, bool>
#endif
{
public UnityGuid(Guid guid)
{
#if NET5_0_OR_GREATER
Span<byte> guidData = stackalloc byte[16];
bool success = guid.TryWriteBytes(guidData);
Debug.Assert(success);
#else
Span<byte> guidData = guid.ToByteArray();
#endif
ConvertSystemOrUnityBytes(guidData, guidData);
Data0 = ReadUInt32LittleEndian(guidData, 0);
Data1 = ReadUInt32LittleEndian(guidData, 1);
@@ -44,10 +54,24 @@ public readonly record struct UnityGuid
//This is not an acceptable way to convert between Unity and System Guids.
//We only do it this way to efficiently get 16 random bytes.
//We don't care about official Guid validity because Unity does not care either.
Guid guid = Guid.NewGuid();
ReadOnlySpan<Guid> guidSpan = new ReadOnlySpan<Guid>(in guid);
ReadOnlySpan<byte> byteSpan = MemoryMarshal.AsBytes(guidSpan);
return new UnityGuid(byteSpan);
if (Unsafe.SizeOf<Guid>() == Unsafe.SizeOf<UnityGuid>())
{
Guid guid = Guid.NewGuid();
return Unsafe.As<Guid, UnityGuid>(ref guid);
}
else
{
return ThrowOrReturnDefault();
}
static UnityGuid ThrowOrReturnDefault()
{
#if DEBUG
throw new InvalidCastException($"{nameof(UnityGuid)} struct size does not match {nameof(Guid)}.");
#else
return default;
#endif
}
}
public static explicit operator UnityGuid(Guid systemGuid) => new UnityGuid(systemGuid);
@@ -57,7 +81,11 @@ public readonly record struct UnityGuid
Span<byte> span = stackalloc byte[16];
unityGuid.Write(span);
ConvertSystemOrUnityBytes(span, span);
#if NET5_0_OR_GREATER
return new Guid(span);
#else
return new Guid(span.ToArray());
#endif
}
private void Write(Span<byte> span)
@@ -77,7 +105,23 @@ public readonly record struct UnityGuid
public override string ToString()
{
Span<char> span = stackalloc char[32]
Span<char> span = stackalloc char[32];
ToString(span);
return CreateString(span);
static string CreateString(Span<char> span)
{
#if NET5_0_OR_GREATER
return new string(span);
#else
return new string(span.ToArray());
#endif
}
}
public void ToString(Span<char> buffer)
{
ReadOnlySpan<char> span = stackalloc char[32]
{
GetHexChar(Data0, 0),
GetHexChar(Data0, 4),
@@ -113,7 +157,7 @@ public readonly record struct UnityGuid
GetHexChar(Data3, 28),
};
return new string(span);
span.CopyTo(buffer);
static char GetHexChar(uint value, int offset)
{
@@ -186,15 +230,31 @@ public readonly record struct UnityGuid
/// <returns>A stable guid corresponding to the <paramref name="input"/>.</returns>
public static UnityGuid Md5Hash(scoped ReadOnlySpan<byte> input)
{
byte[] hashBytes = MD5.HashData(input);
ConvertSystemOrUnityBytes(hashBytes, hashBytes);
return new UnityGuid(hashBytes);
Span<byte> buffer = stackalloc byte[16];
HashData(input, buffer);
ConvertSystemOrUnityBytes(buffer, buffer);
return new UnityGuid(buffer);
}
private static void HashData(ReadOnlySpan<byte> data, Span<byte> buffer)
{
#if NET5_0_OR_GREATER
MD5.HashData(data, buffer);
#else
MD5.Create().ComputeHash(data.ToArray()).AsSpan().CopyTo(buffer);
#endif
}
public static UnityGuid Md5Hash(scoped ReadOnlySpan<byte> assemblyName, scoped ReadOnlySpan<byte> @namespace, scoped ReadOnlySpan<byte> className)
{
int length = assemblyName.Length + @namespace.Length + className.Length;
Span<byte> input = length < 1024 ? stackalloc byte[length] : GC.AllocateUninitializedArray<byte>(length);
Span<byte> input = length < 1024
? stackalloc byte[length]
#if NET5_0_OR_GREATER
: GC.AllocateUninitializedArray<byte>(length);
#else
: new byte[length];
#endif
assemblyName.CopyTo(input);
@namespace.CopyTo(input.Slice(assemblyName.Length));
className.CopyTo(input.Slice(assemblyName.Length + @namespace.Length));
@@ -1,4 +1,4 @@
#if NET7_0_OR_GREATER
#if NET5_0_OR_GREATER
using System.Text.Json;
using System.Text.Json.Serialization;
@@ -6,41 +6,41 @@ public readonly partial struct UnityVersion
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(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(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 Equals(ushort major) => this == From(major);
public bool Equals(ushort major, ushort minor) => this == From(major, minor);
public bool Equals(ushort major, ushort minor, ushort build) => this == From(major, minor, build);
public bool Equals(ushort major, ushort minor, ushort build, UnityVersionType type) => this == From(major, minor, build, type);
public bool Equals(ushort major, ushort minor, ushort build, UnityVersionType type, byte typeNumber) => this == new UnityVersion(major, minor, build, type, typeNumber);
public bool Equals(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 LessThan(ushort major) => this < From(major);
public bool LessThan(ushort major, ushort minor) => this < From(major, minor);
public bool LessThan(ushort major, ushort minor, ushort build) => this < From(major, minor, build);
public bool LessThan(ushort major, ushort minor, ushort build, UnityVersionType type) => this < From(major, minor, build, type);
public bool LessThan(ushort major, ushort minor, ushort build, UnityVersionType type, byte typeNumber) => this < new UnityVersion(major, minor, build, type, typeNumber);
public bool LessThan(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 LessThanOrEquals(ushort major) => this <= From(major);
public bool LessThanOrEquals(ushort major, ushort minor) => this <= From(major, minor);
public bool LessThanOrEquals(ushort major, ushort minor, ushort build) => this <= From(major, minor, build);
public bool LessThanOrEquals(ushort major, ushort minor, ushort build, UnityVersionType type) => this <= From(major, minor, build, type);
public bool LessThanOrEquals(ushort major, ushort minor, ushort build, UnityVersionType type, byte typeNumber) => this <= new UnityVersion(major, minor, build, type, typeNumber);
public bool LessThanOrEquals(string version) => this <= Parse(version);
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);
public bool GreaterThan(ushort major) => this > From(major);
public bool GreaterThan(ushort major, ushort minor) => this > From(major, minor);
public bool GreaterThan(ushort major, ushort minor, ushort build) => this > From(major, minor, build);
public bool GreaterThan(ushort major, ushort minor, ushort build, UnityVersionType type) => this > From(major, minor, build, type);
public bool GreaterThan(ushort major, ushort minor, ushort build, UnityVersionType type, byte typeNumber) => this > new UnityVersion(major, minor, build, type, typeNumber);
public bool GreaterThan(string version) => this > Parse(version);
public bool GreaterThanOrEquals(ushort major) => this >= From(major);
public bool GreaterThanOrEquals(ushort major, ushort minor) => this >= From(major, minor);
public bool GreaterThanOrEquals(ushort major, ushort minor, ushort build) => this >= From(major, minor, build);
public bool GreaterThanOrEquals(ushort major, ushort minor, ushort build, UnityVersionType type) => this >= From(major, minor, build, type);
public bool GreaterThanOrEquals(ushort major, ushort minor, ushort build, UnityVersionType type, byte typeNumber) => this >= new UnityVersion(major, minor, build, type, typeNumber);
public bool GreaterThanOrEquals(string version) => this >= Parse(version);
private UnityVersion From(ushort major)
{
@@ -64,5 +64,4 @@ public readonly partial struct UnityVersion
((ulong)(ushort)type << typeOffset) | subTypeMask & m_data;
return new UnityVersion(data);
}
#pragma warning restore CS1591 // Missing XML comment for publicly visible type or member
}
@@ -27,12 +27,7 @@ public readonly partial struct UnityVersion : IEquatable<UnityVersion>, ICompara
/// </returns>
public int CompareTo(UnityVersion other)
{
if (this > other)
return 1;
else if (this < other)
return -1;
else
return 0;
return m_data.CompareTo(other.m_data);
}
/// <summary>
@@ -55,6 +50,6 @@ public readonly partial struct UnityVersion : IEquatable<UnityVersion>, ICompara
/// <inheritdoc/>
public override int GetHashCode()
{
return unchecked(827 + 911 * m_data.GetHashCode());
return m_data.GetHashCode();
}
}
+68 -37
View File
@@ -2,14 +2,8 @@
using System.Text.RegularExpressions;
namespace AssetRipper.Primitives;
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>
@@ -34,17 +28,22 @@ public readonly partial struct UnityVersion
/// 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>
/// <param name="customEngineString">The custom engine string to be appended</param>
/// <returns>A new string containing the formatted version.</returns>
public string ToString(UnityVersionFormatFlags flags, int? customEngineNumber)
public string ToString(UnityVersionFormatFlags flags,
#if !NET6_0_OR_GREATER
string customEngineString = "")
#else
ReadOnlySpan<char> customEngineString = default)
#endif
{
return customEngineNumber is null
return customEngineString.Length == 0
? 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}";
? $"{Major}.{Minor}.{Build}{Type.ToCharacter()}{TypeNumber}{customEngineString}"
: $"{Major}.{Minor}.{Build}f1c{TypeNumber}{customEngineString}";
}
/// <summary>
@@ -59,66 +58,98 @@ public readonly partial struct UnityVersion
/// <summary>
/// Parse a normal Unity version string
/// </summary>
/// <param name="version">A string to parse</param>
/// <param name="s">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 _);
public static UnityVersion Parse(string s) => Parse(s, 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>
/// <param name="s">A string to parse</param>
/// <param name="customEngine">Not null 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)
public static UnityVersion Parse(string s, out string? customEngine)
{
if (string.IsNullOrEmpty(version))
{
throw new ArgumentNullException(nameof(version));
}
return TryParse(s, out UnityVersion version, out customEngine)
? version
: throw new ArgumentException($"Invalid version format: {s}", nameof(s));
}
if (normalRegex.TryMatch(version, out Match? match))
/// <summary>
/// Try to parse a normal Unity version string
/// </summary>
/// <param name="s">A string to parse</param>
/// <param name="version">The parsed Unity version</param>
/// <param name="customEngine">Not null if this version was generated by a custom Unity Engine.</param>
/// <returns>True if parsing was successful</returns>
public static bool TryParse(string s, out UnityVersion version, out string? customEngine)
{
if (string.IsNullOrEmpty(s))
{
customEngine = null;
version = default;
return false;
}
else if (UnityVersionRegexes.GetChinaRegex().TryMatch(s, out Match? 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 = GetNullableString(match.Groups[5]);
version = new UnityVersion((ushort)major, (ushort)minor, (ushort)build, UnityVersionType.China, (byte)typeNumber);
return true;
}
else if(UnityVersionRegexes.GetNormalRegex().TryMatch(s, 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);
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);
customEngine = GetNullableString(match.Groups[6]);
version = new UnityVersion((ushort)major, (ushort)minor, (ushort)build, type.ToUnityVersionType(), (byte)typeNumber);
return true;
}
else if (majorMinorBuildRegex.TryMatch(version, out match))
else if (UnityVersionRegexes.GetMajorMinorBuildRegex().TryMatch(s, 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);
version = major is not 0 || minor is not 0 || build is not 0
? new UnityVersion((ushort)major, (ushort)minor, (ushort)build, UnityVersionType.Final, 1)
: default;
return true;
}
else if (majorMinorRegex.TryMatch(version, out match))
else if (UnityVersionRegexes.GetMajorMinorRegex().TryMatch(s, 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);
version = major is not 0 || minor is not 0
? new UnityVersion((ushort)major, (ushort)minor, 0, UnityVersionType.Final, 1)
: default;
return true;
}
else if (chinaRegex.TryMatch(version, out match))
else if (UnityVersionRegexes.GetMajorRegex().TryMatch(s, 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);
customEngine = null;
version = major is not 0
? new UnityVersion((ushort)major, 0, 0, UnityVersionType.Final, 1)
: default;
return true;
}
else
{
throw new ArgumentException($"Invalid version format: {version}", nameof(version));
customEngine = null;
version = default;
return false;
}
static int? ParseNullableInteger(Capture capture) => capture.Length == 0 ? null : int.Parse(capture.Value);
static string? GetNullableString(Capture capture) => capture.Length == 0 ? null : capture.Value;
}
}
@@ -0,0 +1,68 @@
using System.Diagnostics.CodeAnalysis;
using System.Text.RegularExpressions;
namespace AssetRipper.Primitives;
internal static partial class UnityVersionRegexes
{
#if NET35
private const RegexOptions Options = RegexOptions.None;
#else
private const RegexOptions Options = RegexOptions.Compiled;
#endif
[StringSyntax("regex")]
private const string Major = @"^([0-9]+)$";
[StringSyntax("regex")]
private const string MajorMinor = @"^([0-9]+)\.([0-9]+)$";
[StringSyntax("regex")]
private const string MajorMinorBuild = @"^([0-9]+)\.([0-9]+)\.([0-9]+)$";
[StringSyntax("regex")]
private const string Normal = @"^([0-9]+)\.([0-9]+)\.([0-9]+)\.?([abcfpx])([0-9]+)((?:.|[\r\n])+)?$";
[StringSyntax("regex")]
private const string China = @"^([0-9]+)\.([0-9]+)\.([0-9]+)\.?f1c([0-9]+)((?:.|[\r\n])+)?$";
#if NET7_0_OR_GREATER
[GeneratedRegex(Major, Options)]
public static partial Regex GetMajorRegex();
#else
private static readonly Regex majorRegex = new Regex(Major, Options);
public static Regex GetMajorRegex() => majorRegex;
#endif
#if NET7_0_OR_GREATER
[GeneratedRegex(MajorMinor, Options)]
public static partial Regex GetMajorMinorRegex();
#else
private static readonly Regex majorMinorRegex = new Regex(MajorMinor, Options);
public static Regex GetMajorMinorRegex() => majorMinorRegex;
#endif
#if NET7_0_OR_GREATER
[GeneratedRegex(MajorMinorBuild, Options)]
public static partial Regex GetMajorMinorBuildRegex();
#else
private static readonly Regex majorMinorBuildRegex = new Regex(MajorMinorBuild, Options);
public static Regex GetMajorMinorBuildRegex() => majorMinorBuildRegex;
#endif
#if NET7_0_OR_GREATER
[GeneratedRegex(Normal, Options)]
public static partial Regex GetNormalRegex();
#else
private static readonly Regex normalRegex = new Regex(Normal, Options);
public static Regex GetNormalRegex() => normalRegex;
#endif
#if NET7_0_OR_GREATER
[GeneratedRegex(China, Options)]
public static partial Regex GetChinaRegex();
#else
private static readonly Regex chinaRegex = new Regex(China, Options);
public static Regex GetChinaRegex() => chinaRegex;
#endif
}
+221 -6
View File
@@ -1,4 +1,4 @@
#if NET7_0_OR_GREATER
#if NET5_0_OR_GREATER || NETSTANDARD2_0_OR_GREATER || NET461_OR_GREATER
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Text;
@@ -11,7 +11,12 @@ namespace AssetRipper.Primitives;
/// <remarks>
/// Conversions to and from <see cref="string"/> are handled by <see cref="Encoding.UTF8"/>.
/// </remarks>
public sealed class Utf8String : IEquatable<Utf8String>
public sealed class Utf8String :
#if NET7_0_OR_GREATER
System.Numerics.IEqualityOperators<Utf8String?, Utf8String?, bool>,
System.Numerics.IEqualityOperators<Utf8String?, string?, bool>,
#endif
IEquatable<Utf8String>
{
private readonly byte[] data;
private string? cachedString;
@@ -27,9 +32,13 @@ public sealed class Utf8String : IEquatable<Utf8String>
cachedString = "";
}
public Utf8String(ReadOnlySpan<byte> data)
public Utf8String(ReadOnlySpan<byte> data) : this(data.ToArray())
{
this.data = data.ToArray();
}
private Utf8String(byte[] data)
{
this.data = data;
}
public Utf8String(string @string)
@@ -56,7 +65,14 @@ public sealed class Utf8String : IEquatable<Utf8String>
public override int GetHashCode()
{
HashCode hash = new();
#if NET6_0_OR_GREATER
hash.AddBytes(data);
#else
foreach (byte b in data)
{
hash.Add(b);
}
#endif
return hash.ToHashCode();
}
@@ -79,7 +95,11 @@ public sealed class Utf8String : IEquatable<Utf8String>
[return: NotNullIfNotNull(nameof(@string))]
public static implicit operator Utf8String?(string? @string)
{
return @string is null ? null : new Utf8String(@string);
return @string is null
? null
: @string.Length == 0
? Empty
: new Utf8String(@string);
}
[return: NotNullIfNotNull(nameof(utf8String))]
@@ -90,12 +110,207 @@ public sealed class Utf8String : IEquatable<Utf8String>
public static implicit operator Utf8String(ReadOnlySpan<byte> data)
{
return new Utf8String(data);
return data.Length == 0 ? Empty : new Utf8String(data);
}
public static implicit operator ReadOnlySpan<byte>(Utf8String? utf8String)
{
return utf8String is null ? default : utf8String.Data;
}
public static Utf8String operator +(Utf8String? string1, Utf8String? string2)
{
return Concat(string1, string2);
}
public static Utf8String operator +(Utf8String? string1, ReadOnlySpan<byte> string2)
{
return string1 is null
? string2.Length == 0 ? Empty : new Utf8String(string2)
: Concat(string1.Data, string2);
}
public static Utf8String operator +(ReadOnlySpan<byte> string1, Utf8String? string2)
{
return string2 is null
? string1.Length == 0 ? Empty : new Utf8String(string1)
: Concat(string1, string2.Data);
}
public static bool IsNullOrEmpty([NotNullWhen(false)] Utf8String? utf8String)
{
return utf8String is null || utf8String.IsEmpty;
}
public static Utf8String Concat(Utf8String? string1, Utf8String? string2)
{
if (IsNullOrEmpty(string1))
{
return string2 ?? Empty;
}
if (IsNullOrEmpty(string2))
{
return string1;
}
byte[] data = new byte[string1.data.Length + string2.data.Length];
string1.data.CopyTo(data.AsSpan());
string2.data.CopyTo(data.AsSpan(string1.data.Length));
return new Utf8String(data);
}
public static Utf8String Concat(Utf8String? string1, Utf8String? string2, Utf8String? string3)
{
if (IsNullOrEmpty(string1))
{
return Concat(string2, string3);
}
if (IsNullOrEmpty(string2))
{
return Concat(string1, string3);
}
if (IsNullOrEmpty(string3))
{
return Concat(string1, string2);
}
byte[] data = new byte[string1.data.Length + string2.data.Length + string3.data.Length];
string1.data.CopyTo(data.AsSpan());
string2.data.CopyTo(data.AsSpan(string1.data.Length));
string3.data.CopyTo(data.AsSpan(string1.data.Length + string2.data.Length));
return new Utf8String(data);
}
public static Utf8String Concat(Utf8String? string1, Utf8String? string2, Utf8String? string3, Utf8String? string4)
{
if (IsNullOrEmpty(string1))
{
return Concat(string2, string3, string4);
}
if (IsNullOrEmpty(string2))
{
return Concat(string1, string3, string4);
}
if (IsNullOrEmpty(string3))
{
return Concat(string1, string2, string4);
}
if (IsNullOrEmpty(string4))
{
return Concat(string1, string2, string3);
}
byte[] data = new byte[string1.data.Length + string2.data.Length + string3.data.Length + string4.data.Length];
string1.data.CopyTo(data.AsSpan());
string2.data.CopyTo(data.AsSpan(string1.data.Length));
string3.data.CopyTo(data.AsSpan(string1.data.Length + string2.data.Length));
string4.data.CopyTo(data.AsSpan(string1.data.Length + string2.data.Length + string3.data.Length));
return new Utf8String(data);
}
public static Utf8String Concat(params Utf8String?[] values)
{
if (values is null)
{
throw new ArgumentNullException(nameof(values));
}
int totalLength = 0;
foreach (Utf8String? value in values)
{
if (value is null)
{
continue;
}
totalLength += value.data.Length;
}
if (totalLength == 0)
{
return Empty;
}
byte[] data = new byte[totalLength];
int offset = 0;
foreach (Utf8String? value in values)
{
if (value is null)
{
continue;
}
value.data.CopyTo(data.AsSpan(offset));
offset += value.data.Length;
}
return new Utf8String(data);
}
public static Utf8String Concat(ReadOnlySpan<byte> string1, ReadOnlySpan<byte> string2)
{
if (string1.Length == 0)
{
return string2.Length == 0 ? Empty : new Utf8String(string2);
}
if (string2.Length == 0)
{
return new Utf8String(string1);
}
byte[] data = new byte[string1.Length + string2.Length];
string1.CopyTo(data);
string2.CopyTo(data.AsSpan(string1.Length));
return new Utf8String(data);
}
public static Utf8String Concat(ReadOnlySpan<byte> string1, ReadOnlySpan<byte> string2, ReadOnlySpan<byte> string3)
{
if (string1.Length == 0)
{
return Concat(string2, string3);
}
if (string2.Length == 0)
{
return Concat(string1, string3);
}
if (string3.Length == 0)
{
return Concat(string1, string2);
}
byte[] data = new byte[string1.Length + string2.Length + string3.Length];
string1.CopyTo(data);
string2.CopyTo(data.AsSpan(string1.Length));
string3.CopyTo(data.AsSpan(string1.Length + string2.Length));
return new Utf8String(data);
}
public static Utf8String Concat(ReadOnlySpan<byte> string1, ReadOnlySpan<byte> string2, ReadOnlySpan<byte> string3, ReadOnlySpan<byte> string4)
{
if (string1.Length == 0)
{
return Concat(string2, string3, string4);
}
if (string2.Length == 0)
{
return Concat(string1, string3, string4);
}
if (string3.Length == 0)
{
return Concat(string1, string2, string4);
}
if (string4.Length == 0)
{
return Concat(string1, string2, string3);
}
byte[] data = new byte[string1.Length + string2.Length + string3.Length + string4.Length];
string1.CopyTo(data);
string2.CopyTo(data.AsSpan(string1.Length));
string3.CopyTo(data.AsSpan(string1.Length + string2.Length));
string4.CopyTo(data.AsSpan(string1.Length + string2.Length + string3.Length));
return new Utf8String(data);
}
}
#endif