Compare commits

..
97 Commits
Author SHA1 Message Date
ds5678 c3ff29e8d7 Bump version to 3.1.6 in project file
Updated the version number from 3.1.5 to 3.1.6 in the AssetRipper.Primitives.csproj file.
2025-02-22 21:43:28 -08:00
ds5678 61f47faf04 Utf8StringJsonConverter 2025-02-22 21:42:49 -08:00
ds5678 57912c52f1 Update version to 3.1.5 and adjust project properties
- Bump version number from 3.1.4 to 3.1.5.
- Update copyright year to 2025.
- Add property group for trimmability with net6.0.
- Modify AOT compatibility check for net8.0.
2025-02-13 16:03:05 -08:00
ds5678 5ab5d744d6 UnityVersion : IParsable<UnityVersion> 2025-02-13 15:57:20 -08:00
ds5678 cd7f841845 Json serialization support for UnityVersion 2025-02-13 15:56:24 -08:00
ds5678 9a5f8bb707 .NET 9 support 2025-02-13 15:47:09 -08:00
dependabot[bot] 089c71d944 Bump actions/setup-dotnet from 4.1.0 to 4.3.0
Bumps [actions/setup-dotnet](https://github.com/actions/setup-dotnet) from 4.1.0 to 4.3.0.
- [Release notes](https://github.com/actions/setup-dotnet/releases)
- [Commits](https://github.com/actions/setup-dotnet/compare/v4.1.0...v4.3.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]>
2025-02-13 18:44:41 -05:00
ds5678 919fa0d5ab Don't bother testing .NET 5 2025-02-13 15:40:27 -08:00
ds5678 df8c5e2879 All frameworks 2025-02-13 15:34:49 -08:00
ds5678 13ece60907 Remove dotnet restore 2025-02-13 15:26:28 -08:00
ds5678 3a46414f08 .net 8 only 2025-02-13 15:24:08 -08:00
ds5678 bc556b7c72 .net 8 2025-02-13 15:23:01 -08:00
ds5678 7147a5d5b1 Strings instead of floats 2025-02-13 15:21:08 -08:00
ds5678 776ab543fa Use a build matrix 2025-02-13 15:18:48 -08:00
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
Jeremy Pritts 57c444ba0e Json support for UnityGuid 2023-07-10 16:57:53 -04:00
Jeremy Pritts ff95cc0dc4 Rename to AssetRipper.Primitives 2023-07-10 16:50:50 -04:00
Jeremy Pritts 25385ab739 Remove compact versions 2023-07-10 16:06:59 -04:00
dependabot[bot] a292fe87a4 Bump Microsoft.NET.Test.Sdk from 17.6.1 to 17.6.3
Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 17.6.1 to 17.6.3.
- [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.1...v17.6.3)

---
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-06-27 15:24:21 -04:00
Jeremy Pritts 3320be1312 Bump version 2023-06-05 09:45:02 -04:00
Jeremy Pritts 659c382ff7 Support formatting short chinese versions 2023-06-05 09:40:48 -04:00
Jeremy Pritts 4aed9eb024 Support parsing alternate chinese versions 2023-06-05 08:43:50 -04:00
dependabot[bot] 4e6f668e10 Bump NUnit.Analyzers from 3.6.0 to 3.6.1
Bumps [NUnit.Analyzers](https://github.com/nunit/nunit.analyzers) from 3.6.0 to 3.6.1.
- [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.0...3.6.1)

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

Signed-off-by: dependabot[bot] <[email protected]>
2023-06-05 08:10:53 -04:00
dependabot[bot] dc4e81eb28 Bump PolySharp from 1.13.1 to 1.13.2
Bumps [PolySharp](https://github.com/Sergio0694/PolySharp) from 1.13.1 to 1.13.2.
- [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-patch
...

Signed-off-by: dependabot[bot] <[email protected]>
2023-06-05 08:07:13 -04:00
dependabot[bot] 0e2a37e920 Bump coverlet.collector from 3.2.0 to 6.0.0
Bumps [coverlet.collector](https://github.com/coverlet-coverage/coverlet) from 3.2.0 to 6.0.0.
- [Release notes](https://github.com/coverlet-coverage/coverlet/releases)
- [Commits](https://github.com/coverlet-coverage/coverlet/compare/v3.2.0...v6.0.0)

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

Signed-off-by: dependabot[bot] <[email protected]>
2023-06-05 08:07:06 -04:00
dependabot[bot] b29d4a7a69 Bump Microsoft.NET.Test.Sdk from 17.6.0 to 17.6.1
Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 17.6.0 to 17.6.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.6.0...v17.6.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-06-01 15:09:18 -04:00
dependabot[bot] 93ee2b0675 Bump Microsoft.NET.Test.Sdk from 17.5.0 to 17.6.0
Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 17.5.0 to 17.6.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.5.0...v17.6.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-05-31 06:04:58 -04:00
dependabot[bot] ebe6802570 Bump NUnit3TestAdapter from 4.4.2 to 4.5.0
Bumps [NUnit3TestAdapter](https://github.com/nunit/nunit3-vs-adapter) from 4.4.2 to 4.5.0.
- [Release notes](https://github.com/nunit/nunit3-vs-adapter/releases)
- [Commits](https://github.com/nunit/nunit3-vs-adapter/compare/V4.4.2...V4.5.0)

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

Signed-off-by: dependabot[bot] <[email protected]>
2023-05-30 18:37:57 -04:00
dependabot[bot] 97da17c016 Bump actions/setup-dotnet from 3.1.0 to 3.2.0
Bumps [actions/setup-dotnet](https://github.com/actions/setup-dotnet) from 3.1.0 to 3.2.0.
- [Release notes](https://github.com/actions/setup-dotnet/releases)
- [Commits](https://github.com/actions/setup-dotnet/compare/v3.1.0...v3.2.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]>
2023-05-29 15:13:51 -04:00
dependabot[bot] 475c27c28c Bump actions/setup-dotnet from 3.0.3 to 3.1.0
Bumps [actions/setup-dotnet](https://github.com/actions/setup-dotnet) from 3.0.3 to 3.1.0.
- [Release notes](https://github.com/actions/setup-dotnet/releases)
- [Commits](https://github.com/actions/setup-dotnet/compare/v3.0.3...v3.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]>
2023-05-25 16:37:20 -04:00
dependabot[bot] fb0fb3f1c6 Bump PolySharp from 1.12.1 to 1.13.1
Bumps [PolySharp](https://github.com/Sergio0694/PolySharp) from 1.12.1 to 1.13.1.
- [Release notes](https://github.com/Sergio0694/PolySharp/releases)
- [Commits](https://github.com/Sergio0694/PolySharp/compare/1.12.1...1.13.1)

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

Signed-off-by: dependabot[bot] <[email protected]>
2023-04-06 22:22:53 -04:00
Jeremy Pritts 182fca60ca Add test case for custom china version 2023-03-16 00:04:38 -04:00
Jeremy Pritts d4609533b2 Bump version to 1.4.0 2023-03-15 23:58:57 -04:00
Jeremy Pritts 46e53d834f NUnit constraint model 2023-03-15 23:56:25 -04:00
Jeremy Pritts 99157d5433 Support parsing custom versions 2023-03-15 23:52:00 -04:00
Jeremy Pritts 5ec33f0518 Simplify ToString 2023-03-15 23:32:35 -04:00
Jeremy Pritts c4a5ab77d4 Refactor parsing tests 2023-03-15 23:10:59 -04:00
Jeremy Pritts ab4df10c87 Remove ParseFromDllName 2023-03-15 23:02:59 -04:00
dependabot[bot] 2d00a1259a Bump NUnit3TestAdapter from 4.4.0 to 4.4.2
Bumps [NUnit3TestAdapter](https://github.com/nunit/nunit3-vs-adapter) from 4.4.0 to 4.4.2.
- [Release notes](https://github.com/nunit/nunit3-vs-adapter/releases)
- [Commits](https://github.com/nunit/nunit3-vs-adapter/compare/V4.4.0...V4.4.2)

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

Signed-off-by: dependabot[bot] <[email protected]>
2023-03-01 14:05:44 -05:00
dependabot[bot] b65056d08f Bump NUnit3TestAdapter from 4.3.1 to 4.4.0
Bumps [NUnit3TestAdapter](https://github.com/nunit/nunit3-vs-adapter) from 4.3.1 to 4.4.0.
- [Release notes](https://github.com/nunit/nunit3-vs-adapter/releases)
- [Commits](https://github.com/nunit/nunit3-vs-adapter/compare/V4.3.1...V4.4.0)

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

Signed-off-by: dependabot[bot] <[email protected]>
2023-02-27 14:18:13 -05:00
dependabot[bot] 42c5957429 Bump Microsoft.NET.Test.Sdk from 17.4.1 to 17.5.0
Bumps [Microsoft.NET.Test.Sdk](https://github.com/microsoft/vstest) from 17.4.1 to 17.5.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.4.1...v17.5.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-02-22 13:56:50 -05:00
dependabot[bot] 606e439721 Bump PolySharp from 1.11.0 to 1.12.1
Bumps [PolySharp](https://github.com/Sergio0694/PolySharp) from 1.11.0 to 1.12.1.
- [Release notes](https://github.com/Sergio0694/PolySharp/releases)
- [Commits](https://github.com/Sergio0694/PolySharp/compare/1.11.0...1.12.1)

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

Signed-off-by: dependabot[bot] <[email protected]>
2023-01-23 17:29:41 -05:00
dependabot[bot] b9a57bd765 Bump PolySharp from 1.10.0 to 1.11.0
Bumps [PolySharp](https://github.com/Sergio0694/PolySharp) from 1.10.0 to 1.11.0.
- [Release notes](https://github.com/Sergio0694/PolySharp/releases)
- [Commits](https://github.com/Sergio0694/PolySharp/compare/1.10.0...1.11.0)

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

Signed-off-by: dependabot[bot] <[email protected]>
2023-01-19 13:10:01 -05:00
48 changed files with 1485 additions and 1258 deletions

No files matched your search

+13 -43
View File
@@ -7,55 +7,25 @@ on:
branches: [ master ]
jobs:
net7:
build-and-test:
runs-on: ubuntu-latest
strategy:
matrix:
dotnet-version: ["9.0", "8.0", "7.0", "6.0"]
steps:
- uses: actions/checkout@v3
- uses: actions/checkout@v4
- name: Setup .NET
uses: actions/[email protected].3
uses: actions/setup-dotnet@v4.3.0
with:
dotnet-version: 7.0.x
dotnet-version: |
6.0.x
7.0.x
8.0.x
9.0.x
- name: Restore dependencies
run: dotnet restore
- name: Build
run: dotnet build --framework net7.0 --no-restore
run: dotnet build --framework net${{ matrix.dotnet-version }} --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
run: dotnet test --framework net${{ matrix.dotnet-version }} --no-build --verbosity normal
@@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net35;net40;net48;net5.0;net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
<LangVersion>Latest</LangVersion>
<Nullable>enable</Nullable>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<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="4.1.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="coverlet.collector" Version="6.0.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\AssetRipper.Primitives\AssetRipper.Primitives.csproj" />
</ItemGroup>
</Project>
@@ -0,0 +1,75 @@
namespace AssetRipper.Primitives.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).GreaterThanOrEquals(2019, 1, 0));
Assert.That(new UnityVersion(2019, 1, 0, UnityVersionType.Final, 1).LessThanOrEquals(2019, 1, 0));
});
}
}
@@ -1,4 +1,4 @@
namespace AssetRipper.VersionUtilities.Tests;
namespace AssetRipper.Primitives.Tests;
public class DistanceTests
{
@@ -16,14 +16,14 @@ public class DistanceTests
{
ulong distance1 = UnityVersion.Distance(version4, version5);
ulong distance2 = UnityVersion.Distance(version5, version4);
Assert.IsTrue(distance1 == distance2);
Assert.That(distance1, Is.EqualTo(distance2));
}
[Test]
public void DistanceIsZeroForEquivalentVersions()
{
ulong distance = UnityVersion.Distance(version4, version4);
Assert.IsTrue(distance == 0);
Assert.That(distance, Is.EqualTo(0));
}
[Test]
@@ -31,7 +31,7 @@ public class DistanceTests
{
UnityVersion version = new UnityVersion(6, 1);
UnityVersion closest = version.GetClosestVersion(versionArray);
Assert.IsTrue(closest == version6);
Assert.That(closest, Is.EqualTo(version6));
}
[Test]
@@ -39,6 +39,6 @@ public class DistanceTests
{
UnityVersion version = new UnityVersion(5, 4, 9);
UnityVersion closest = version.GetClosestVersion(versionArray);
Assert.IsTrue(closest == version5);
Assert.That(closest, Is.EqualTo(version5));
}
}
@@ -0,0 +1,100 @@
using NUnit.Framework.Internal;
using System.Collections.Generic;
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, "\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, "\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")]
[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 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 0 and 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 string? 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));
});
}
[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;
for (int i = 0; i < count; i++)
{
yield return new UnityVersion(random.NextUShort(), random.NextUShort(), random.NextUShort(), random.NextEnum<UnityVersionType>(), random.NextByte());
}
}
}
@@ -0,0 +1,90 @@
#if NET5_0_OR_GREATER
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
namespace AssetRipper.Primitives.Tests;
public class UnityGuidTests
{
private const string randomGuidString = "352a5b3897136ed2702a283243520538";
private const string sequentialGuidString = "0123456789abcdef0fedcba987654321";
[Test]
public void MissingReferenceSerializedCorrectly()
{
Assert.That(UnityGuid.MissingReference.ToString(), Is.EqualTo("0000000deadbeef15deadf00d0000000"));
}
[Test]
public void ToByteArrayIsConsistentWithConstructorFromByteArray()
{
UnityGuid guid = UnityGuid.NewGuid();
byte[] bytes = guid.ToByteArray();
UnityGuid fromBytes = new UnityGuid(bytes);
Assert.That(fromBytes, Is.EqualTo(guid));
Assert.That(fromBytes.ToString(), Is.EqualTo(guid.ToString()));
}
[Test]
public void ConversionFromSystemGuidToUnityGuidProducesSameString()
{
Guid systemGuid = Guid.NewGuid();
UnityGuid unityGUID = new UnityGuid(systemGuid);
Assert.That(unityGUID.ToString(), Is.EqualTo(systemGuid.ToString().Replace("-", "")));
}
[Test]
public void IsZeroReturnsTrueForTheZeroGuid()
{
UnityGuid unityGUID = new UnityGuid(0, 0, 0, 0);
Assert.That(unityGUID.IsZero, Is.True);
}
[Test]
public void IsZeroReturnsFalseForRandomGuid()
{
UnityGuid unityGUID = UnityGuid.NewGuid();
Assert.That(unityGUID.IsZero, Is.False);
}
[Test]
public void ParsedGuidOutputsSameString()
{
UnityGuid parsedGUID = UnityGuid.Parse(randomGuidString);
string outputedString = parsedGUID.ToString();
Assert.That(outputedString, Is.EqualTo(randomGuidString));
}
[Test]
public void ConversionsAreInverses()
{
UnityGuid unityGuid = UnityGuid.NewGuid();
Guid systemGuid = (Guid)unityGuid;
Assert.That((UnityGuid)systemGuid, Is.EqualTo(unityGuid));
}
[Test]
public void ByteConversionIsItsOwnInverse()
{
UnityGuid originalGuid = UnityGuid.NewGuid();
UnityGuid inverseGuid = new UnityGuid(originalGuid.ToByteArray());
UnityGuid equivalentGuid = new UnityGuid(inverseGuid.ToByteArray());
Assert.That(equivalentGuid, Is.EqualTo(originalGuid));
}
[Test]
public void UnityGuidIsTheSameSizeAsSystemGuid()
{
Assert.That(Unsafe.SizeOf<UnityGuid>(), Is.EqualTo(Unsafe.SizeOf<Guid>()));
}
[Test]
public void ToBytesMethod()
{
Guid originalGuid = Guid.NewGuid();
UnityGuid tobyteArrayGuid = new UnityGuid(originalGuid.ToByteArray());
UnityGuid memoryMarshallGuid = Unsafe.As<Guid, UnityGuid>(ref originalGuid);
Assert.That(memoryMarshallGuid, Is.EqualTo(tobyteArrayGuid));
}
}
#endif
+2
View File
@@ -0,0 +1,2 @@
global using NUnit.Framework;
global using System;
@@ -0,0 +1,87 @@
#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()
{
Assert.Multiple(() =>
{
Assert.That(Utf8String.Empty.Data.Length, Is.EqualTo(0));
Assert.That(Utf8String.Empty.String, Is.Empty);
#pragma warning disable NUnit2010 // Use EqualConstraint for better assertion messages in case of failure
Assert.That(Utf8String.Empty == "");
Assert.That("" == Utf8String.Empty);
#pragma warning restore NUnit2010 // Use EqualConstraint for better assertion messages in case of failure
Assert.That(new Utf8String(""), Is.EqualTo(Utf8String.Empty));
});
}
/// <summary>
/// <see href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/proposals/csharp-11.0/utf8-string-literals"/>
/// </summary>
[Test]
public void Utf8StringMadeFromUtf8LiteralIsTheSameAsMadeFromConstantString()
{
Utf8String dataString = "AssetRipperTestString"u8;
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
@@ -3,10 +3,6 @@ Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio Version 17
VisualStudioVersion = 17.0.32112.339
MinimumVisualStudioVersion = 10.0.40219.1
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VersionUtilities", "VersionUtilities\VersionUtilities.csproj", "{5628CFCF-F89B-4191-808C-5EE5FB327B63}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "VersionUtilities.Tests", "VersionUtilities.Tests\VersionUtilities.Tests.csproj", "{451F668C-6079-40FD-A79B-96A2CA0C5AAC}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{36D291AB-E468-4CE7-8DB3-2C46639FE5AE}"
ProjectSection(SolutionItems) = preProject
.gitignore = .gitignore
@@ -24,20 +20,24 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Workflows", "Workflows", "{
.github\workflows\dotnet.yml = .github\workflows\dotnet.yml
EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AssetRipper.Primitives", "AssetRipper.Primitives\AssetRipper.Primitives.csproj", "{0B77D2BD-812E-4717-8D11-2F6C09167C41}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AssetRipper.Primitives.Tests", "AssetRipper.Primitives.Tests\AssetRipper.Primitives.Tests.csproj", "{545E670D-141B-4F05-9AFD-2F184A59EADC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Release|Any CPU = Release|Any CPU
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{5628CFCF-F89B-4191-808C-5EE5FB327B63}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{5628CFCF-F89B-4191-808C-5EE5FB327B63}.Debug|Any CPU.Build.0 = Debug|Any CPU
{5628CFCF-F89B-4191-808C-5EE5FB327B63}.Release|Any CPU.ActiveCfg = Release|Any CPU
{5628CFCF-F89B-4191-808C-5EE5FB327B63}.Release|Any CPU.Build.0 = Release|Any CPU
{451F668C-6079-40FD-A79B-96A2CA0C5AAC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{451F668C-6079-40FD-A79B-96A2CA0C5AAC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{451F668C-6079-40FD-A79B-96A2CA0C5AAC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{451F668C-6079-40FD-A79B-96A2CA0C5AAC}.Release|Any CPU.Build.0 = Release|Any CPU
{0B77D2BD-812E-4717-8D11-2F6C09167C41}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{0B77D2BD-812E-4717-8D11-2F6C09167C41}.Debug|Any CPU.Build.0 = Debug|Any CPU
{0B77D2BD-812E-4717-8D11-2F6C09167C41}.Release|Any CPU.ActiveCfg = Release|Any CPU
{0B77D2BD-812E-4717-8D11-2F6C09167C41}.Release|Any CPU.Build.0 = Release|Any CPU
{545E670D-141B-4F05-9AFD-2F184A59EADC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{545E670D-141B-4F05-9AFD-2F184A59EADC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{545E670D-141B-4F05-9AFD-2F184A59EADC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{545E670D-141B-4F05-9AFD-2F184A59EADC}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -0,0 +1,58 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>net35;net40;net461;netstandard2.0;net5.0;net6.0;net7.0;net8.0;net9.0</TargetFrameworks>
<LangVersion>Latest</LangVersion>
<Nullable>enable</Nullable>
<Authors>ds5678</Authors>
<Company>AssetRipper</Company>
<Version>3.1.6</Version>
<AssemblyVersion>$(Version)</AssemblyVersion>
<PackageId>AssetRipper.Primitives</PackageId>
<PackageTags>C# assetripper unity unity3d</PackageTags>
<RepositoryUrl>https://github.com/AssetRipper/AssetRipper.Primitives</RepositoryUrl>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<RepositoryType>git</RepositoryType>
<PackageProjectUrl>https://github.com/AssetRipper/AssetRipper.Primitives</PackageProjectUrl>
<Copyright>Copyright (c) 2022-2025 ds5678</Copyright>
<Description>Managed library for primitive types used in AssetRipper.</Description>
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<NoWarn>1591</NoWarn>
</PropertyGroup>
<PropertyGroup Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net6.0'))">
<IsTrimmable>true</IsTrimmable>
</PropertyGroup>
<PropertyGroup Condition="$([MSBuild]::IsTargetFrameworkCompatible('$(TargetFramework)', 'net8.0'))">
<IsAotCompatible>true</IsAotCompatible>
</PropertyGroup>
<ItemGroup>
<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.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>
@@ -1,4 +1,4 @@
namespace AssetRipper.VersionUtilities.Extensions;
namespace AssetRipper.Primitives.Extensions;
/// <summary>
/// Extensions for <see cref="char"/>
@@ -1,7 +1,7 @@
using System.Diagnostics.CodeAnalysis;
using System.Text.RegularExpressions;
namespace AssetRipper.VersionUtilities.Extensions;
namespace AssetRipper.Primitives.Extensions;
internal static class RegexExtensions
{
+278
View File
@@ -0,0 +1,278 @@
#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;
namespace AssetRipper.Primitives;
#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);
Data2 = ReadUInt32LittleEndian(guidData, 2);
Data3 = ReadUInt32LittleEndian(guidData, 3);
}
public UnityGuid(ReadOnlySpan<byte> guidData)
{
Data0 = ReadUInt32LittleEndian(guidData, 0);
Data1 = ReadUInt32LittleEndian(guidData, 1);
Data2 = ReadUInt32LittleEndian(guidData, 2);
Data3 = ReadUInt32LittleEndian(guidData, 3);
}
public UnityGuid(uint data0, uint data1, uint data2, uint data3)
{
Data0 = data0;
Data1 = data1;
Data2 = data2;
Data3 = data3;
}
public static UnityGuid NewGuid()
{
//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.
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);
public static explicit operator Guid(UnityGuid 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)
{
BinaryPrimitives.WriteUInt32LittleEndian(span.Slice(0 * sizeof(uint), sizeof(uint)), Data0);
BinaryPrimitives.WriteUInt32LittleEndian(span.Slice(1 * sizeof(uint), sizeof(uint)), Data1);
BinaryPrimitives.WriteUInt32LittleEndian(span.Slice(2 * sizeof(uint), sizeof(uint)), Data2);
BinaryPrimitives.WriteUInt32LittleEndian(span.Slice(3 * sizeof(uint), sizeof(uint)), Data3);
}
public byte[] ToByteArray()
{
byte[] result = new byte[16];
Write(result);
return result;
}
public override string ToString()
{
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),
GetHexChar(Data0, 8),
GetHexChar(Data0, 12),
GetHexChar(Data0, 16),
GetHexChar(Data0, 20),
GetHexChar(Data0, 24),
GetHexChar(Data0, 28),
GetHexChar(Data1, 0),
GetHexChar(Data1, 4),
GetHexChar(Data1, 8),
GetHexChar(Data1, 12),
GetHexChar(Data1, 16),
GetHexChar(Data1, 20),
GetHexChar(Data1, 24),
GetHexChar(Data1, 28),
GetHexChar(Data2, 0),
GetHexChar(Data2, 4),
GetHexChar(Data2, 8),
GetHexChar(Data2, 12),
GetHexChar(Data2, 16),
GetHexChar(Data2, 20),
GetHexChar(Data2, 24),
GetHexChar(Data2, 28),
GetHexChar(Data3, 0),
GetHexChar(Data3, 4),
GetHexChar(Data3, 8),
GetHexChar(Data3, 12),
GetHexChar(Data3, 16),
GetHexChar(Data3, 20),
GetHexChar(Data3, 24),
GetHexChar(Data3, 28),
};
span.CopyTo(buffer);
static char GetHexChar(uint value, int offset)
{
int index = unchecked((int)((value >> offset) & 0xF));
return "0123456789abcdef"[index];
}
}
/// <summary>
/// Read little-endian <see cref="uint"/> from <see cref="ReadOnlySpan{T}"/>
/// </summary>
/// <param name="byteSpan">A span of bytes.</param>
/// <param name="index">The ith <see cref="uint"/> in <paramref name="byteSpan"/>.</param>
/// <returns></returns>
private static uint ReadUInt32LittleEndian(ReadOnlySpan<byte> byteSpan, int index)
{
return BinaryPrimitives.ReadUInt32LittleEndian(byteSpan.Slice(index * sizeof(uint), sizeof(uint)));
}
/// <summary>
/// Converts system bytes to unity bytes, or the reverse
/// </summary>
/// <param name="input">A 16 byte input span</param>
/// <param name="output">A 16 byte output span</param>
/// <returns>The same span: <paramref name="input"/></returns>
/// <exception cref="ArgumentException">Span doesn't have 16 elements</exception>
private static void ConvertSystemOrUnityBytes(scoped ReadOnlySpan<byte> input, scoped Span<byte> output)
{
if (input.Length != 16)
{
throw new ArgumentException($"Invalid length: {input.Length}", nameof(input));
}
if (output.Length != 16)
{
throw new ArgumentException($"Invalid length: {output.Length}", nameof(output));
}
//Unity Guid's are in big endian, so the bytes have to be flipped for multibyte fields
(output[0], output[1], output[2], output[3]) = (input[3], input[2], input[1], input[0]);
(output[4], output[5]) = (input[5], input[4]);
(output[6], output[7]) = (input[7], input[6]);
input.Slice(8).CopyTo(output.Slice(8));
for (int i = 0; i < 16; i++)
{
//AB becomes BA
uint value = output[i];
output[i] = (byte)(unchecked(value << 4 & 0xF0) | unchecked(value >> 4 & 0xF));
}
}
public static UnityGuid Parse(string guidString) => new UnityGuid(Guid.Parse(guidString));
/// <summary>
/// Make a guid by MD5 hashing a string
/// </summary>
/// <remarks>
/// The returned guid is most likely not "valid" by official standards. However, Unity doesn't seem to care.
/// </remarks>
/// <param name="str">Input string. Can be any length</param>
/// <returns>A stable guid corresponding to the input string</returns>
public static UnityGuid Md5Hash(string str) => Md5Hash(Encoding.UTF8.GetBytes(str));
/// <summary>
/// Make a guid by MD5 hashing some input data
/// </summary>
/// <remarks>
/// The returned guid is most likely not "valid" by official standards. However, Unity doesn't seem to care.
/// </remarks>
/// <param name="input">Input data. Can be any length</param>
/// <returns>A stable guid corresponding to the <paramref name="input"/>.</returns>
public static UnityGuid Md5Hash(scoped ReadOnlySpan<byte> input)
{
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]
#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));
return Md5Hash(input);
}
public bool IsZero => Data0 == 0 && Data1 == 0 && Data2 == 0 && Data3 == 0;
public uint Data0 { get; }
public uint Data1 { get; }
public uint Data2 { get; }
public uint Data3 { get; }
/// <summary>
/// 0x0000000DEADBEEF15DEADF00D0000000
/// </summary>
public static UnityGuid MissingReference { get; } = new UnityGuid(0xD0000000, 0x1FEEBDAE, 0x00FDAED5, 0x0000000D);
public static UnityGuid Zero => default;
}
#endif
@@ -0,0 +1,19 @@
#if NET5_0_OR_GREATER
using System.Text.Json;
using System.Text.Json.Serialization;
namespace AssetRipper.Primitives;
public sealed class UnityGuidJsonConverter : JsonConverter<UnityGuid>
{
public override UnityGuid Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return UnityGuid.Parse(reader.GetString() ?? throw new JsonException("String was read as null"));
}
public override void Write(Utf8JsonWriter writer, UnityGuid value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString());
}
}
#endif
@@ -0,0 +1,67 @@
namespace AssetRipper.Primitives;
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;
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 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 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 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)
{
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);
}
}
@@ -0,0 +1,25 @@
#if NET7_0_OR_GREATER
using System.Numerics;
namespace AssetRipper.Primitives;
partial struct UnityVersion :
IComparisonOperators<UnityVersion, UnityVersion, bool>,
IEqualityOperators<UnityVersion, UnityVersion, bool>,
IMinMaxValue<UnityVersion>,
IParsable<UnityVersion>
{
static UnityVersion IMinMaxValue<UnityVersion>.MaxValue => MaxVersion;
static UnityVersion IMinMaxValue<UnityVersion>.MinValue => MinVersion;
static UnityVersion IParsable<UnityVersion>.Parse(string s, IFormatProvider? provider)
{
return Parse(s);
}
static bool IParsable<UnityVersion>.TryParse(string? s, IFormatProvider? provider, out UnityVersion result)
{
return TryParse(s, out result, out _);
}
}
#endif
@@ -1,4 +1,4 @@
namespace AssetRipper.VersionUtilities;
namespace AssetRipper.Primitives;
public readonly partial struct UnityVersion : IEquatable<UnityVersion>, IComparable, IComparable<UnityVersion>
{
@@ -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();
}
}
@@ -0,0 +1,10 @@
#if NET5_0_OR_GREATER
using System.Text.Json.Serialization;
namespace AssetRipper.Primitives;
[JsonConverter(typeof(UnityVersionJsonConverter))]
partial struct UnityVersion
{
}
#endif
@@ -1,4 +1,4 @@
namespace AssetRipper.VersionUtilities;
namespace AssetRipper.Primitives;
public readonly partial struct UnityVersion
{
@@ -1,4 +1,4 @@
namespace AssetRipper.VersionUtilities;
namespace AssetRipper.Primitives;
partial struct UnityVersion
{
/// <summary>
@@ -1,4 +1,4 @@
namespace AssetRipper.VersionUtilities;
namespace AssetRipper.Primitives;
public readonly partial struct UnityVersion
{
@@ -0,0 +1,155 @@
using AssetRipper.Primitives.Extensions;
using System.Text.RegularExpressions;
namespace AssetRipper.Primitives;
public readonly partial struct UnityVersion
{
/// <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)
{
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="customEngineString">The custom engine string to be appended</param>
/// <returns>A new string containing the formatted version.</returns>
public string ToString(UnityVersionFormatFlags flags,
#if !NET6_0_OR_GREATER
string customEngineString = "")
#else
ReadOnlySpan<char> customEngineString = default)
#endif
{
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}{customEngineString}"
: $"{Major}.{Minor}.{Build}f1c{TypeNumber}{customEngineString}";
}
/// <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="s">A string to parse</param>
/// <returns>The parsed Unity version</returns>
/// <exception cref="ArgumentException">If the string is in an invalid format</exception>
public static UnityVersion Parse(string s) => Parse(s, out _);
/// <summary>
/// Parse a normal Unity version string
/// </summary>
/// <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="ArgumentException">If the string is in an invalid format</exception>
public static UnityVersion Parse(string s, out string? customEngine)
{
return TryParse(s, out UnityVersion version, out customEngine)
? version
: throw new ArgumentException($"Invalid version format: {s}", nameof(s));
}
/// <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 (s is null || s.Length is 0)
{
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 = GetNullableString(match.Groups[6]);
version = new UnityVersion((ushort)major, (ushort)minor, (ushort)build, type.ToUnityVersionType(), (byte)typeNumber);
return true;
}
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;
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 (UnityVersionRegexes.GetMajorMinorRegex().TryMatch(s, out match))
{
int major = int.Parse(match.Groups[1].Value);
int minor = int.Parse(match.Groups[2].Value);
customEngine = null;
version = major is not 0 || minor is not 0
? new UnityVersion((ushort)major, (ushort)minor, 0, UnityVersionType.Final, 1)
: default;
return true;
}
else if (UnityVersionRegexes.GetMajorRegex().TryMatch(s, out match))
{
int major = int.Parse(match.Groups[1].Value);
customEngine = null;
version = major is not 0
? new UnityVersion((ushort)major, 0, 0, UnityVersionType.Final, 1)
: default;
return true;
}
else
{
customEngine = null;
version = default;
return false;
}
static string? GetNullableString(Capture capture) => capture.Length == 0 ? null : capture.Value;
}
}
@@ -1,4 +1,4 @@
namespace AssetRipper.VersionUtilities;
namespace AssetRipper.Primitives;
/// <summary>
/// A value type for holding Unity versions
@@ -0,0 +1,25 @@
namespace AssetRipper.Primitives;
/// <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,
}
@@ -0,0 +1,19 @@
#if NET5_0_OR_GREATER
using System.Text.Json;
using System.Text.Json.Serialization;
namespace AssetRipper.Primitives;
public sealed class UnityVersionJsonConverter : JsonConverter<UnityVersion>
{
public override UnityVersion Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return UnityVersion.Parse(reader.GetString() ?? throw new JsonException("String was read as null"));
}
public override void Write(Utf8JsonWriter writer, UnityVersion value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString());
}
}
#endif
@@ -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
}
@@ -1,4 +1,4 @@
namespace AssetRipper.VersionUtilities;
namespace AssetRipper.Primitives;
/// <summary>
/// An enumeration representing the letter in a Unity Version string
@@ -1,2 +1 @@
global using System;
global using System.IO;
+319
View File
@@ -0,0 +1,319 @@
#if NET5_0_OR_GREATER || NETSTANDARD2_0_OR_GREATER || NET461_OR_GREATER
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Text;
namespace AssetRipper.Primitives;
/// <summary>
/// An immutable, thread-safe, representation of UTF8 text data.
/// </summary>
/// <remarks>
/// Conversions to and from <see cref="string"/> are handled by <see cref="Encoding.UTF8"/>.
/// </remarks>
#if NET5_0_OR_GREATER
[System.Text.Json.Serialization.JsonConverter(typeof(Utf8StringJsonConverter))]
#endif
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;
public static Utf8String Empty { get; } = new();
/// <summary>
/// The empty string. A shared instance is available in <see cref="Empty"/>.
/// </summary>
public Utf8String()
{
data = [];
cachedString = "";
}
public Utf8String(ReadOnlySpan<byte> data) : this(data.ToArray())
{
}
private Utf8String(byte[] data)
{
this.data = data;
}
public Utf8String(string @string)
{
cachedString = @string;
data = Encoding.UTF8.GetBytes(@string);
}
public ReadOnlySpan<byte> Data => data;
public string String
{
get
{
cachedString ??= Encoding.UTF8.GetString(data);
return cachedString;
}
}
public bool IsEmpty => data.Length == 0;
public override string ToString() => String;
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();
}
public override bool Equals(object? obj) => Equals(obj as Utf8String);
public bool Equals(Utf8String? other) => other is not null && Data.SequenceEqual(other.Data);
public static bool operator ==(Utf8String? string1, Utf8String? string2)
{
return EqualityComparer<Utf8String>.Default.Equals(string1, string2);
}
public static bool operator !=(Utf8String? string1, Utf8String? string2) => !(string1 == string2);
public static bool operator ==(Utf8String? utf8String, string? @string) => utf8String?.String == @string;
public static bool operator !=(Utf8String? utf8String, string? @string) => utf8String?.String != @string;
public static bool operator ==(string? @string, Utf8String? utf8String) => utf8String?.String == @string;
public static bool operator !=(string? @string, Utf8String? utf8String) => utf8String?.String != @string;
[return: NotNullIfNotNull(nameof(@string))]
public static implicit operator Utf8String?(string? @string)
{
return @string is null
? null
: @string.Length == 0
? Empty
: new Utf8String(@string);
}
[return: NotNullIfNotNull(nameof(utf8String))]
public static implicit operator string?(Utf8String? utf8String)
{
return utf8String?.String;
}
public static implicit operator Utf8String(ReadOnlySpan<byte> 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
@@ -0,0 +1,19 @@
#if NET5_0_OR_GREATER
using System.Text.Json;
using System.Text.Json.Serialization;
namespace AssetRipper.Primitives;
public sealed class Utf8StringJsonConverter : JsonConverter<Utf8String>
{
public override Utf8String Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return reader.GetString() ?? throw new JsonException("String was read as null");
}
public override void Write(Utf8JsonWriter writer, Utf8String value, JsonSerializerOptions options)
{
writer.WriteStringValue(value.ToString());
}
}
#endif
+3 -3
View File
@@ -1,8 +1,8 @@
# AssetRipper.VersionUtilities
# AssetRipper.Primitives
[![](https://img.shields.io/nuget/v/AssetRipper.VersionUtilities)](https://www.nuget.org/packages/AssetRipper.VersionUtilities)
[![](https://img.shields.io/nuget/v/AssetRipper.Primitives)](https://www.nuget.org/packages/AssetRipper.Primitives)
Managed library for handling Unity versions
Managed library for primitive types used in AssetRipper projects.
# Legal Disclaimers
-63
View File
@@ -1,63 +0,0 @@
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.IsTrue(lowValue < mediumValue);
Assert.IsTrue(mediumValue < highValue);
Assert.IsTrue(lowValue < highValue);
}
[Test]
public void GreaterThanIsTransitive()
{
Assert.IsTrue(mediumValue > lowValue);
Assert.IsTrue(highValue > mediumValue);
Assert.IsTrue(highValue > lowValue);
}
[Test]
public void WeakInequalityHolds()
{
UnityVersion low = lowValue;
Assert.IsTrue(lowValue <= low);
}
[Test]
public void MinimumValueDefinition()
{
Assert.IsTrue(UnityVersion.MinVersion == new UnityVersion(ushort.MinValue, ushort.MinValue, ushort.MinValue, UnityVersionType.Alpha, byte.MinValue));
}
[Test]
public void MaximumValueDefinition()
{
Assert.IsTrue(UnityVersion.MaxVersion == new UnityVersion(ushort.MaxValue, ushort.MaxValue, ushort.MaxValue, (UnityVersionType)byte.MaxValue, byte.MaxValue));
}
[Test]
public void AnIncreaseOfTypeNumberMakesInequal()
{
Assert.IsTrue(UnityVersion.MinVersion < new UnityVersion(ushort.MinValue, ushort.MinValue, ushort.MinValue, UnityVersionType.Alpha, 1));
Assert.IsTrue(lowValue < new UnityVersion(lowValue.Major, lowValue.Minor, lowValue.Build, lowValue.Type, (byte)(lowValue.TypeNumber + 1)));
}
[Test]
public void AlphaZeroIsTheDefault()
{
Assert.IsTrue(new UnityVersion(2019, 1, 0) < new UnityVersion(2019, 1, 0, UnityVersionType.Final, 1));
}
[Test]
public void ComparisonMethodsIgnoreUnspecifiedValues()
{
Assert.IsTrue(new UnityVersion(2019, 1, 0, UnityVersionType.Final, 1).IsGreaterEqual(2019, 1, 0));
Assert.IsTrue(new UnityVersion(2019, 1, 0, UnityVersionType.Final, 1).IsLessEqual(2019, 1, 0));
}
}
-66
View File
@@ -1,66 +0,0 @@
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));
}
[Test]
public void MajorMinorOnly()
{
string version = "2019.4";
UnityVersion expected = new UnityVersion(2019, 4, 0, UnityVersionType.Final, 1);
Assert.AreEqual(expected, UnityVersion.Parse(version));
}
[Test]
public void MajorMinorBuildOnly()
{
string version = "2019.4.3";
UnityVersion expected = new UnityVersion(2019, 4, 3, UnityVersionType.Final, 1);
Assert.AreEqual(expected, UnityVersion.Parse(version));
}
[Test]
public void ChinaVersionString()
{
string version = "2021.3.11f1c2";//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
UnityVersion expected = new UnityVersion(2021, 3, 11, UnityVersionType.China, 2);
Assert.Multiple(() =>
{
Assert.AreEqual(expected, UnityVersion.Parse(version));
Assert.AreEqual(version, expected.ToString());
});
}
}
-1
View File
@@ -1 +0,0 @@
global using NUnit.Framework;
@@ -1,23 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netframework3.5;netframework4.0;netframework4.8;net5.0;net6.0;net7.0</TargetFrameworks>
<LangVersion>Latest</LangVersion>
<Nullable>enable</Nullable>
<RootNamespace>AssetRipper.VersionUtilities.Tests</RootNamespace>
<IsPackable>false</IsPackable>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.4.1" />
<PackageReference Include="NUnit" Version="3.13.3" />
<PackageReference Include="NUnit3TestAdapter" Version="4.3.1" />
<PackageReference Include="coverlet.collector" Version="3.2.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\VersionUtilities\VersionUtilities.csproj" />
</ItemGroup>
</Project>
@@ -1,60 +0,0 @@
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;
}
}
@@ -1,110 +0,0 @@
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);
}
}
-202
View File
@@ -1,202 +0,0 @@
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();
}
}
@@ -1,60 +0,0 @@
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();
}
}
@@ -1,88 +0,0 @@
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;
}
}
-163
View File
@@ -1,163 +0,0 @@
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();
}
}
@@ -1,39 +0,0 @@
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);
}
}
@@ -1,39 +0,0 @@
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);
}
}
@@ -1,68 +0,0 @@
namespace AssetRipper.VersionUtilities;
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(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 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(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(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
}
-11
View File
@@ -1,11 +0,0 @@
#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
-145
View File
@@ -1,145 +0,0 @@
using AssetRipper.VersionUtilities.Extensions;
using System.Text;
using System.Text.RegularExpressions;
namespace AssetRipper.VersionUtilities;
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]+)\.?([abfpx])([0-9]+)$", RegexOptions.Compiled);
private static readonly Regex chinaRegex = new Regex(@"^([0-9]+)\.([0-9]+)\.([0-9]+)\.?f1c([0-9]+)$", RegexOptions.Compiled);
/// <summary>
/// Serialize the version as a string
/// </summary>
/// <returns>A new string like 2019.4.3f1</returns>
public override string ToString()
{
return ToString(false, false, false, false);
}
/// <summary>
/// Serialize the version as a string
/// </summary>
/// <param name="hasUnderscorePrefix">Include the _ prefix</param>
/// <param name="useUnderscoresAsSeparators">Use underscores as separators instead of periods</param>
/// <param name="hasDllExtension">Include the .dll extension</param>
/// <param name="hasSeparatorAfterBuild">Include a separator between <see cref="Build"/> and <see cref="Type"/></param>
/// <returns>A new string generated with those parameters</returns>
public string ToString(bool hasUnderscorePrefix, bool useUnderscoresAsSeparators, bool hasDllExtension, bool hasSeparatorAfterBuild)
{
StringBuilder sb = new();
char separator = useUnderscoresAsSeparators ? '_' : '.';
if(hasUnderscorePrefix)
sb.Append('_');
sb.Append(Major);
sb.Append(separator);
sb.Append(Minor);
sb.Append(separator);
sb.Append(Build);
if (hasSeparatorAfterBuild)
{
sb.Append(separator);
}
if (Type == UnityVersionType.China)
{
sb.Append("f1");
sb.Append('c');
sb.Append(TypeNumber);
}
else
{
sb.Append(Type.ToCharacter());
sb.Append(TypeNumber);
}
if(hasDllExtension)
sb.Append(".dll");
return sb.ToString();
}
/// <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));
}
if (normalRegex.TryMatch(version, 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);
char type = match.Groups[4].Value[0];
int typeNumber = int.Parse(match.Groups[5].Value);
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);
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);
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);
return new UnityVersion((ushort)major, (ushort)minor, (ushort)build, UnityVersionType.China, (byte)typeNumber);
}
else
{
throw new ArgumentException($"Invalid version format: {version}", nameof(version));
}
}
}
-41
View File
@@ -1,41 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFrameworks>netframework3.5;netframework4.0;netstandard2.0;net5.0;net6.0;net7.0</TargetFrameworks>
<LangVersion>Latest</LangVersion>
<Nullable>enable</Nullable>
<RootNamespace>AssetRipper.VersionUtilities</RootNamespace>
<AssemblyName>AssetRipper.VersionUtilities</AssemblyName>
<Authors>ds5678</Authors>
<Company>AssetRipper</Company>
<Version>1.3.1.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-$([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.10.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>