From c93ea1862ccfdf85f11a99b1e0859c9a4573f1be Mon Sep 17 00:00:00 2001 From: Bradley Grainger Date: Mon, 19 Feb 2024 03:26:50 -0800 Subject: [PATCH] Use one-shot HashData method in .NET 9.0. --- global.json | 3 ++- src/NGuid/GuidHelpers.cs | 15 ++++++++++++++- src/NGuid/NGuid.csproj | 2 +- tests/NGuid.Tests/NGuid.Tests.csproj | 2 +- 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/global.json b/global.json index 391ba3c..cd89fb1 100644 --- a/global.json +++ b/global.json @@ -1,6 +1,7 @@ { "sdk": { - "version": "8.0.100", + "version": "9.0.100-preview", + "allowPrerelease": true, "rollForward": "latestFeature" } } diff --git a/src/NGuid/GuidHelpers.cs b/src/NGuid/GuidHelpers.cs index 04443cc..2c0f7d8 100644 --- a/src/NGuid/GuidHelpers.cs +++ b/src/NGuid/GuidHelpers.cs @@ -424,9 +424,13 @@ public static Guid CreateVersion8FromName(HashAlgorithmName hashAlgorithmName, G [SkipLocalsInit] public static Guid CreateVersion8FromName(HashAlgorithmName hashAlgorithmName, Guid namespaceId, ReadOnlySpan name) { +#if NET9_0_OR_GREATER + Span hashOutput = stackalloc byte[64]; +#else using var algorithm = GetHashAlgorithm(hashAlgorithmName); - Span buffer = name.Length < 500 ? stackalloc byte[16 + name.Length] : new byte[16 + name.Length]; Span hashOutput = stackalloc byte[algorithm.HashSize / 8]; +#endif + Span buffer = name.Length < 500 ? stackalloc byte[16 + name.Length] : new byte[16 + name.Length]; // convert the hash space and namespace UUIDs to network order if (!namespaceId.TryWriteBytes(buffer)) @@ -435,9 +439,16 @@ public static Guid CreateVersion8FromName(HashAlgorithmName hashAlgorithmName, G // compute the hash of [ namespace ID, name ] name.CopyTo(buffer[16..]); +#if NET9_0_OR_GREATER + var hashLength = CryptographicOperations.HashData(hashAlgorithmName, buffer, hashOutput); + if (hashLength == 0) + throw new InvalidOperationException("Failed to hash data"); + hashOutput = hashOutput[..hashLength]; +#else var success = algorithm.TryComputeHash(buffer, hashOutput, out var bytesWritten); if (!success || bytesWritten != hashOutput.Length) throw new InvalidOperationException("Failed to hash data"); +#endif // the initial bytes from the hash are copied straight to the bytes of the new GUID var newGuid = hashOutput[..16]; @@ -452,6 +463,7 @@ public static Guid CreateVersion8FromName(HashAlgorithmName hashAlgorithmName, G } #endif +#if !NET9_0_OR_GREATER private static HashAlgorithm GetHashAlgorithm(HashAlgorithmName hashAlgorithmName) => hashAlgorithmName.Name switch { @@ -460,6 +472,7 @@ private static HashAlgorithm GetHashAlgorithm(HashAlgorithmName hashAlgorithmNam "SHA512" => SHA512.Create(), _ => throw new ArgumentException($"Unsupported hash algorithm name: {hashAlgorithmName.Name}", nameof(hashAlgorithmName)), }; +#endif /// /// The namespace for fully-qualified domain names (from RFC 4122, Appendix C). diff --git a/src/NGuid/NGuid.csproj b/src/NGuid/NGuid.csproj index b73f70d..cabb564 100644 --- a/src/NGuid/NGuid.csproj +++ b/src/NGuid/NGuid.csproj @@ -1,7 +1,7 @@ - netstandard2.0;net6.0;net8.0 + netstandard2.0;net6.0;net8.0;net9.0 Creates GUIDs according to RFC 4122 and the UUID Revision Working Draft. README.md guid;uuid;rfc4122;uuidv6;uuidv7;uuidv8 diff --git a/tests/NGuid.Tests/NGuid.Tests.csproj b/tests/NGuid.Tests/NGuid.Tests.csproj index 595a780..418bc09 100644 --- a/tests/NGuid.Tests/NGuid.Tests.csproj +++ b/tests/NGuid.Tests/NGuid.Tests.csproj @@ -1,7 +1,7 @@ - net48;net8.0 + net481;net8.0;net9.0 false true $(NoWarn);CS1591