diff --git a/src/NGuid/GuidHelpers.cs b/src/NGuid/GuidHelpers.cs index 78c0f44..b2d3438 100644 --- a/src/NGuid/GuidHelpers.cs +++ b/src/NGuid/GuidHelpers.cs @@ -106,9 +106,14 @@ public static Guid CreateFromName(Guid namespaceId, ReadOnlySpan name, int // convert the namespace UUID to network order (step 3) Span buffer = name.Length < 500 ? stackalloc byte[16 + name.Length + 20] : new byte[16 + name.Length + 20]; +#if NET8_0_OR_GREATER + if (!namespaceId.TryWriteBytes(buffer, bigEndian: true, out _)) + throw new InvalidOperationException("Failed to write namespace ID bytes to buffer"); +#else if (!namespaceId.TryWriteBytes(buffer)) throw new InvalidOperationException("Failed to write Guid bytes to buffer"); SwapByteOrder(buffer); +#endif // compute the hash of the namespace ID concatenated with the name (step 4) #pragma warning disable CA5350 // Do Not Use Weak Cryptographic Algorithms @@ -131,9 +136,13 @@ public static Guid CreateFromName(Guid namespaceId, ReadOnlySpan name, int // set the two most significant bits (bits 6 and 7) of the clock_seq_hi_and_reserved to zero and one, respectively (step 10) newGuid[8] = (byte) ((newGuid[8] & 0x3F) | 0x80); +#if NET8_0_OR_GREATER + return new Guid(newGuid, bigEndian: true); +#else // convert the resulting UUID to local byte order (step 13) SwapByteOrder(newGuid); return new Guid(newGuid); +#endif } #endif @@ -354,14 +363,17 @@ public static Guid CreateVersion8(ReadOnlySpan bytes) Span guidBytes = stackalloc byte[16]; bytes[..16].CopyTo(guidBytes); - // convert the bytes to network order (so that bytes[0] is the first byte in the serialized GUID output) - SwapByteOrder(guidBytes); - // set the version and variant fields - guidBytes[7] = (byte) (0x80 | (guidBytes[7] & 0xF)); + guidBytes[6] = (byte) (0x80 | (guidBytes[6] & 0xF)); guidBytes[8] = (byte) (0x80 | (guidBytes[8] & 0x3F)); +#if NET8_0_OR_GREATER + return new Guid(guidBytes, bigEndian: true); +#else + // convert the bytes to network order (so that bytes[0] is the first byte in the serialized GUID output) + SwapByteOrder(guidBytes); return new Guid(guidBytes); +#endif } #endif @@ -422,10 +434,15 @@ public static Guid CreateVersion8FromName(HashAlgorithmName hashAlgorithmName, G #endif Span buffer = name.Length < 500 ? stackalloc byte[16 + name.Length] : new byte[16 + name.Length]; +#if NET8_0_OR_GREATER + if (!namespaceId.TryWriteBytes(buffer, bigEndian: true, out _)) + throw new InvalidOperationException("Failed to write namespace ID bytes to buffer"); +#else // convert the hash space and namespace UUIDs to network order if (!namespaceId.TryWriteBytes(buffer)) throw new InvalidOperationException("Failed to write namespace ID bytes to buffer"); SwapByteOrder(buffer); +#endif // compute the hash of [ namespace ID, name ] name.CopyTo(buffer[16..]); @@ -447,9 +464,13 @@ public static Guid CreateVersion8FromName(HashAlgorithmName hashAlgorithmName, G newGuid[6] = (byte) ((newGuid[6] & 0x0F) | 0x80); newGuid[8] = (byte) ((newGuid[8] & 0x3F) | 0x80); +#if NET8_0_OR_GREATER + return new Guid(newGuid, bigEndian: true); +#else // convert the resulting UUID to local byte order SwapByteOrder(newGuid); return new Guid(newGuid); +#endif } #endif @@ -479,6 +500,7 @@ private static HashAlgorithm GetHashAlgorithm(HashAlgorithmName hashAlgorithmNam /// public static readonly Guid IsoOidNamespace = new("6ba7b812-9dad-11d1-80b4-00c04fd430c8"); +#if !NET8_0_OR_GREATER // Converts a GUID (expressed as a byte array) to/from network order (MSB-first). internal static void SwapByteOrder(Span guid) { @@ -487,6 +509,7 @@ internal static void SwapByteOrder(Span guid) SwapBytes(guid, 4, 5); SwapBytes(guid, 6, 7); } +#endif private static void SwapBytes(Span guid, int left, int right) { diff --git a/tests/NGuid.Tests/GuidHelpersTests.cs b/tests/NGuid.Tests/GuidHelpersTests.cs index fde32c5..b1340ac 100644 --- a/tests/NGuid.Tests/GuidHelpersTests.cs +++ b/tests/NGuid.Tests/GuidHelpersTests.cs @@ -1,5 +1,4 @@ using System.Buffers.Binary; -using System.Globalization; using System.Text; namespace NGuid.Tests; @@ -13,8 +12,10 @@ public void SwapByteOrder() var bytes = guid.ToByteArray(); Assert.Equal([4, 3, 2, 1, 6, 5, 8, 7, 9, 10, 11, 12, 13, 14, 15, 16], bytes); +#if !NET8_0_OR_GREATER GuidHelpers.SwapByteOrder(bytes); Assert.Equal([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16], bytes); +#endif } [Theory] @@ -83,7 +84,7 @@ public void CreateV6() [InlineData("2022-02-22T14:22:22-05:00", "1ec9414c-232a-6b00")] // https://datatracker.ietf.org/doc/html/draft-ietf-uuidrev-rfc4122bis-14#name-example-of-a-uuidv6-value public void CreateV6FromTimeProvider(string timestamp, string expectedPrefix) { - var timeProvider = new FixedTimeProvider(DateTimeOffset.Parse(timestamp, CultureInfo.InvariantCulture)); + var timeProvider = new FixedTimeProvider(DateTimeOffset.Parse(timestamp, System.Globalization.CultureInfo.InvariantCulture)); var guid = GuidHelpers.CreateVersion6(timeProvider); Assert.StartsWith(expectedPrefix, guid.ToString("d"), StringComparison.Ordinal); } @@ -108,7 +109,7 @@ public void CreateV7() [InlineData("2022-02-22T14:22:22-05:00", "017f22e2-79b0-7")] // https://datatracker.ietf.org/doc/html/draft-ietf-uuidrev-rfc4122bis-14#name-example-of-a-uuidv7-value public void CreateV7FromTimeProvider(string timestamp, string expectedPrefix) { - var timeProvider = new FixedTimeProvider(DateTimeOffset.Parse(timestamp, CultureInfo.InvariantCulture)); + var timeProvider = new FixedTimeProvider(DateTimeOffset.Parse(timestamp, System.Globalization.CultureInfo.InvariantCulture)); var guid = GuidHelpers.CreateVersion7(timeProvider); Assert.StartsWith(expectedPrefix, guid.ToString("d"), StringComparison.Ordinal); } @@ -129,12 +130,12 @@ public void ConvertV4ToV6() => [InlineData("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", "ffffffff-ffff-8fff-bfff-ffffffffffff")] public void CreateV8(string input, string expected) { -#if NET8_0_OR_GREATER +#if NET5_0_OR_GREATER var bytes = Convert.FromHexString(input); #else var bytes = new byte[input.Length / 2]; for (var i = 0; i < bytes.Length; i++) - bytes[i] = byte.Parse(input.Substring(i * 2, 2), NumberStyles.HexNumber, CultureInfo.InvariantCulture); + bytes[i] = byte.Parse(input.Substring(i * 2, 2), System.Globalization.NumberStyles.HexNumber, System.Globalization.CultureInfo.InvariantCulture); #endif var guid = GuidHelpers.CreateVersion8(bytes); Assert.Equal(new Guid(expected), guid); diff --git a/tests/NGuid.Tests/NGuid.Tests.csproj b/tests/NGuid.Tests/NGuid.Tests.csproj index 080b871..26cb6b6 100644 --- a/tests/NGuid.Tests/NGuid.Tests.csproj +++ b/tests/NGuid.Tests/NGuid.Tests.csproj @@ -1,7 +1,7 @@ - net481;net8.0;net9.0 + net481;net6.0;net8.0;net9.0 false true $(NoWarn);CA1515;CS1591