diff --git a/src/CommunityToolkit.HighPerformance/Memory/Internals/OverflowHelper.cs b/src/CommunityToolkit.HighPerformance/Memory/Internals/OverflowHelper.cs index f03c18e96..41db25635 100644 --- a/src/CommunityToolkit.HighPerformance/Memory/Internals/OverflowHelper.cs +++ b/src/CommunityToolkit.HighPerformance/Memory/Internals/OverflowHelper.cs @@ -64,6 +64,6 @@ public static void EnsureIsInNativeIntRange(int height, int width, int pitch) [MethodImpl(MethodImplOptions.AggressiveInlining)] public static int ComputeInt32Area(int height, int width, int pitch) { - return checked(((width + pitch) * Max(unchecked(height - 1), 0)) + width); + return Max(checked(((width + pitch) * (height - 1)) + width), 0); } } diff --git a/src/CommunityToolkit.HighPerformance/Memory/Memory2D{T}.cs b/src/CommunityToolkit.HighPerformance/Memory/Memory2D{T}.cs index 848499cf8..385e53f2c 100644 --- a/src/CommunityToolkit.HighPerformance/Memory/Memory2D{T}.cs +++ b/src/CommunityToolkit.HighPerformance/Memory/Memory2D{T}.cs @@ -362,13 +362,6 @@ public unsafe Memory2D(MemoryManager memoryManager, int offset, int height, i ThrowHelper.ThrowArgumentOutOfRangeExceptionForPitch(); } - if (width == 0 || height == 0) - { - this = default; - - return; - } - int area = OverflowHelper.ComputeInt32Area(height, width, pitch); int remaining = length - offset; @@ -435,16 +428,8 @@ internal unsafe Memory2D(Memory memory, int offset, int height, int width, in ThrowHelper.ThrowArgumentOutOfRangeExceptionForPitch(); } - if (width == 0 || height == 0) - { - this = default; - - return; - } - - int - area = OverflowHelper.ComputeInt32Area(height, width, pitch), - remaining = memory.Length - offset; + int area = OverflowHelper.ComputeInt32Area(height, width, pitch); + int remaining = memory.Length - offset; if (area > remaining) { diff --git a/src/CommunityToolkit.HighPerformance/Memory/ReadOnlyMemory2D{T}.cs b/src/CommunityToolkit.HighPerformance/Memory/ReadOnlyMemory2D{T}.cs index 2786c8799..855f351a7 100644 --- a/src/CommunityToolkit.HighPerformance/Memory/ReadOnlyMemory2D{T}.cs +++ b/src/CommunityToolkit.HighPerformance/Memory/ReadOnlyMemory2D{T}.cs @@ -382,13 +382,6 @@ public unsafe ReadOnlyMemory2D(MemoryManager memoryManager, int offset, int h ThrowHelper.ThrowArgumentOutOfRangeExceptionForPitch(); } - if (width == 0 || height == 0) - { - this = default; - - return; - } - int area = OverflowHelper.ComputeInt32Area(height, width, pitch); int remaining = length - offset; @@ -455,13 +448,6 @@ internal unsafe ReadOnlyMemory2D(ReadOnlyMemory memory, int offset, int heigh ThrowHelper.ThrowArgumentOutOfRangeExceptionForPitch(); } - if (width == 0 || height == 0) - { - this = default; - - return; - } - int area = OverflowHelper.ComputeInt32Area(height, width, pitch); int remaining = memory.Length - offset; diff --git a/src/CommunityToolkit.HighPerformance/Memory/ReadOnlySpan2D{T}.cs b/src/CommunityToolkit.HighPerformance/Memory/ReadOnlySpan2D{T}.cs index a56475ed4..0816e0234 100644 --- a/src/CommunityToolkit.HighPerformance/Memory/ReadOnlySpan2D{T}.cs +++ b/src/CommunityToolkit.HighPerformance/Memory/ReadOnlySpan2D{T}.cs @@ -209,13 +209,6 @@ public ReadOnlySpan2D(T[] array, int offset, int height, int width, int pitch) ThrowHelper.ThrowArgumentOutOfRangeExceptionForPitch(); } - if (width == 0 || height == 0) - { - this = default; - - return; - } - int area = OverflowHelper.ComputeInt32Area(height, width, pitch); int remaining = array.Length - offset; @@ -459,13 +452,6 @@ internal ReadOnlySpan2D(ReadOnlySpan span, int offset, int height, int width, ThrowHelper.ThrowArgumentOutOfRangeExceptionForPitch(); } - if (width == 0 || height == 0) - { - this = default; - - return; - } - int area = OverflowHelper.ComputeInt32Area(height, width, pitch); int remaining = span.Length - offset; diff --git a/src/CommunityToolkit.HighPerformance/Memory/Span2D{T}.cs b/src/CommunityToolkit.HighPerformance/Memory/Span2D{T}.cs index f48f35d11..beb13ad81 100644 --- a/src/CommunityToolkit.HighPerformance/Memory/Span2D{T}.cs +++ b/src/CommunityToolkit.HighPerformance/Memory/Span2D{T}.cs @@ -531,13 +531,6 @@ internal Span2D(Span span, int offset, int height, int width, int pitch) ThrowHelper.ThrowArgumentOutOfRangeExceptionForPitch(); } - if (width == 0 || height == 0) - { - this = default; - - return; - } - int area = OverflowHelper.ComputeInt32Area(height, width, pitch); int remaining = span.Length - offset; diff --git a/tests/CommunityToolkit.HighPerformance.UnitTests/Extensions/Test_MemoryExtensions.cs b/tests/CommunityToolkit.HighPerformance.UnitTests/Extensions/Test_MemoryExtensions.cs index 3c33ee981..d365c86e8 100644 --- a/tests/CommunityToolkit.HighPerformance.UnitTests/Extensions/Test_MemoryExtensions.cs +++ b/tests/CommunityToolkit.HighPerformance.UnitTests/Extensions/Test_MemoryExtensions.cs @@ -569,6 +569,30 @@ public void Test_MemoryExtensions_MemoryStream() Assert.IsTrue(stream.CanWrite); } +#if NET6_0_OR_GREATER + [TestMethod] + public void Test_MemoryExtensions_AsMemory2d_Empty() + { + Memory2D empty1 = Array.Empty().AsMemory().AsMemory2D(0, 0); + Assert.IsTrue(empty1.IsEmpty); + Assert.AreEqual(empty1.Length, 0); + Assert.AreEqual(empty1.Width, 0); + Assert.AreEqual(empty1.Height, 0); + + Memory2D empty2 = Array.Empty().AsMemory().AsMemory2D(4, 0); + Assert.IsTrue(empty2.IsEmpty); + Assert.AreEqual(empty2.Length, 0); + Assert.AreEqual(empty2.Width, 0); + Assert.AreEqual(empty2.Height, 4); + + Memory2D empty3 = Array.Empty().AsMemory().AsMemory2D(0, 7); + Assert.IsTrue(empty3.IsEmpty); + Assert.AreEqual(empty3.Length, 0); + Assert.AreEqual(empty3.Width, 7); + Assert.AreEqual(empty3.Height, 0); + } +#endif + private sealed class ArrayMemoryManager : MemoryManager where T : unmanaged { diff --git a/tests/CommunityToolkit.HighPerformance.UnitTests/Extensions/Test_ReadOnlyMemoryExtensions.cs b/tests/CommunityToolkit.HighPerformance.UnitTests/Extensions/Test_ReadOnlyMemoryExtensions.cs index 119d8a83f..89f2faf17 100644 --- a/tests/CommunityToolkit.HighPerformance.UnitTests/Extensions/Test_ReadOnlyMemoryExtensions.cs +++ b/tests/CommunityToolkit.HighPerformance.UnitTests/Extensions/Test_ReadOnlyMemoryExtensions.cs @@ -3,6 +3,7 @@ // See the LICENSE file in the project root for more information. using System; +using System.Collections.Generic; using System.IO; using Microsoft.VisualStudio.TestTools.UnitTesting; @@ -34,4 +35,28 @@ public void Test_ReadOnlyMemoryExtensions_MemoryStream() Assert.AreEqual(stream.Length, memory.Length); Assert.IsFalse(stream.CanWrite); } + +#if NET6_0_OR_GREATER + [TestMethod] + public void Test_ReadOnlyMemoryExtensions_AsMemory2d_Empty() + { + ReadOnlyMemory2D empty1 = ((ReadOnlyMemory)Array.Empty().AsMemory()).AsMemory2D(0, 0); + Assert.IsTrue(empty1.IsEmpty); + Assert.AreEqual(empty1.Length, 0); + Assert.AreEqual(empty1.Width, 0); + Assert.AreEqual(empty1.Height, 0); + + ReadOnlyMemory2D empty2 = ((ReadOnlyMemory)Array.Empty().AsMemory()).AsMemory2D(4, 0); + Assert.IsTrue(empty2.IsEmpty); + Assert.AreEqual(empty2.Length, 0); + Assert.AreEqual(empty2.Width, 0); + Assert.AreEqual(empty2.Height, 4); + + ReadOnlyMemory2D empty3 = ((ReadOnlyMemory)Array.Empty().AsMemory()).AsMemory2D(0, 7); + Assert.IsTrue(empty3.IsEmpty); + Assert.AreEqual(empty3.Length, 0); + Assert.AreEqual(empty3.Width, 7); + Assert.AreEqual(empty3.Height, 0); + } +#endif } diff --git a/tests/CommunityToolkit.HighPerformance.UnitTests/Extensions/Test_ReadOnlySpanExtensions.cs b/tests/CommunityToolkit.HighPerformance.UnitTests/Extensions/Test_ReadOnlySpanExtensions.cs index c7db7c108..00ed8a8bc 100644 --- a/tests/CommunityToolkit.HighPerformance.UnitTests/Extensions/Test_ReadOnlySpanExtensions.cs +++ b/tests/CommunityToolkit.HighPerformance.UnitTests/Extensions/Test_ReadOnlySpanExtensions.cs @@ -294,4 +294,28 @@ public void Test_ReadOnlySpanExtensions_CopyTo_RefEnumerable() CollectionAssert.AreEqual(array, result); } + +#if NET6_0_OR_GREATER + [TestMethod] + public void Test_ReadOnlySpanExtensions_AsSpan2d_Empty() + { + ReadOnlySpan2D empty1 = ReadOnlySpan.Empty.AsSpan2D(0, 0); + Assert.IsTrue(empty1.IsEmpty); + Assert.AreEqual(empty1.Length, 0); + Assert.AreEqual(empty1.Width, 0); + Assert.AreEqual(empty1.Height, 0); + + ReadOnlySpan2D empty2 = ReadOnlySpan.Empty.AsSpan2D(4, 0); + Assert.IsTrue(empty2.IsEmpty); + Assert.AreEqual(empty2.Length, 0); + Assert.AreEqual(empty2.Width, 0); + Assert.AreEqual(empty2.Height, 4); + + ReadOnlySpan2D empty3 = ReadOnlySpan.Empty.AsSpan2D(0, 7); + Assert.IsTrue(empty3.IsEmpty); + Assert.AreEqual(empty3.Length, 0); + Assert.AreEqual(empty3.Width, 7); + Assert.AreEqual(empty3.Height, 0); + } +#endif } diff --git a/tests/CommunityToolkit.HighPerformance.UnitTests/Extensions/Test_SpanExtensions.cs b/tests/CommunityToolkit.HighPerformance.UnitTests/Extensions/Test_SpanExtensions.cs index f3dd41f05..08e0ff1d7 100644 --- a/tests/CommunityToolkit.HighPerformance.UnitTests/Extensions/Test_SpanExtensions.cs +++ b/tests/CommunityToolkit.HighPerformance.UnitTests/Extensions/Test_SpanExtensions.cs @@ -199,4 +199,28 @@ public void Test_SpanExtensions_CopyTo_RefEnumerable() CollectionAssert.AreEqual(array, result); } + +#if NET6_0_OR_GREATER + [TestMethod] + public void Test_SpanExtensions_AsSpan2d_Empty() + { + Span2D empty1 = Span.Empty.AsSpan2D(0, 0); + Assert.IsTrue(empty1.IsEmpty); + Assert.AreEqual(empty1.Length, 0); + Assert.AreEqual(empty1.Width, 0); + Assert.AreEqual(empty1.Height, 0); + + Span2D empty2 = Span.Empty.AsSpan2D(4, 0); + Assert.IsTrue(empty2.IsEmpty); + Assert.AreEqual(empty2.Length, 0); + Assert.AreEqual(empty2.Width, 0); + Assert.AreEqual(empty2.Height, 4); + + Span2D empty3 = Span.Empty.AsSpan2D(0, 7); + Assert.IsTrue(empty3.IsEmpty); + Assert.AreEqual(empty3.Length, 0); + Assert.AreEqual(empty3.Width, 7); + Assert.AreEqual(empty3.Height, 0); + } +#endif } diff --git a/tests/CommunityToolkit.HighPerformance.UnitTests/Memory/Test_Memory2D{T}.cs b/tests/CommunityToolkit.HighPerformance.UnitTests/Memory/Test_Memory2D{T}.cs index 337663c71..50730558d 100644 --- a/tests/CommunityToolkit.HighPerformance.UnitTests/Memory/Test_Memory2D{T}.cs +++ b/tests/CommunityToolkit.HighPerformance.UnitTests/Memory/Test_Memory2D{T}.cs @@ -3,7 +3,9 @@ // See the LICENSE file in the project root for more information. using System; +using System.Buffers; using System.Runtime.CompilerServices; +using CommunityToolkit.HighPerformance.UnitTests.Buffers.Internals; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace CommunityToolkit.HighPerformance.UnitTests; @@ -43,6 +45,27 @@ public void Test_Memory2DT_Empty() Assert.AreEqual(empty4.Length, 0); Assert.AreEqual(empty4.Width, 7); Assert.AreEqual(empty4.Height, 0); + +#if NET6_0_OR_GREATER + MemoryManager memoryManager = new UnmanagedSpanOwner(1); + Memory2D empty5 = new (memoryManager, 0, 0); + Assert.IsTrue(empty5.IsEmpty); + Assert.AreEqual(empty5.Length, 0); + Assert.AreEqual(empty5.Width, 0); + Assert.AreEqual(empty5.Height, 0); + + Memory2D empty6 = new (memoryManager, 4, 0); + Assert.IsTrue(empty6.IsEmpty); + Assert.AreEqual(empty6.Length, 0); + Assert.AreEqual(empty6.Width, 0); + Assert.AreEqual(empty6.Height, 4); + + Memory2D empty7 = new (memoryManager, 0, 7); + Assert.IsTrue(empty7.IsEmpty); + Assert.AreEqual(empty7.Length, 0); + Assert.AreEqual(empty7.Width, 7); + Assert.AreEqual(empty7.Height, 0); +#endif } [TestMethod] diff --git a/tests/CommunityToolkit.HighPerformance.UnitTests/Memory/Test_ReadOnlyMemory2D{T}.cs b/tests/CommunityToolkit.HighPerformance.UnitTests/Memory/Test_ReadOnlyMemory2D{T}.cs index dc8673771..3f830ceed 100644 --- a/tests/CommunityToolkit.HighPerformance.UnitTests/Memory/Test_ReadOnlyMemory2D{T}.cs +++ b/tests/CommunityToolkit.HighPerformance.UnitTests/Memory/Test_ReadOnlyMemory2D{T}.cs @@ -3,7 +3,9 @@ // See the LICENSE file in the project root for more information. using System; +using System.Buffers; using System.Runtime.CompilerServices; +using CommunityToolkit.HighPerformance.UnitTests.Buffers.Internals; using Microsoft.VisualStudio.TestTools.UnitTesting; namespace CommunityToolkit.HighPerformance.UnitTests; @@ -34,6 +36,27 @@ public void Test_ReadOnlyMemory2DT_Empty() Assert.AreEqual(empty2.Length, 0); Assert.AreEqual(empty2.Width, 0); Assert.AreEqual(empty2.Height, 0); + +#if NET6_0_OR_GREATER + MemoryManager memoryManager = new UnmanagedSpanOwner(1); + ReadOnlyMemory2D empty5 = new (memoryManager, 0, 0); + Assert.IsTrue(empty5.IsEmpty); + Assert.AreEqual(empty5.Length, 0); + Assert.AreEqual(empty5.Width, 0); + Assert.AreEqual(empty5.Height, 0); + + ReadOnlyMemory2D empty6 = new (memoryManager, 4, 0); + Assert.IsTrue(empty6.IsEmpty); + Assert.AreEqual(empty6.Length, 0); + Assert.AreEqual(empty6.Width, 0); + Assert.AreEqual(empty6.Height, 4); + + ReadOnlyMemory2D empty7 = new (memoryManager, 0, 7); + Assert.IsTrue(empty7.IsEmpty); + Assert.AreEqual(empty7.Length, 0); + Assert.AreEqual(empty7.Width, 7); + Assert.AreEqual(empty7.Height, 0); +#endif } [TestMethod] diff --git a/tests/CommunityToolkit.HighPerformance.UnitTests/Memory/Test_ReadOnlySpan2D{T}.cs b/tests/CommunityToolkit.HighPerformance.UnitTests/Memory/Test_ReadOnlySpan2D{T}.cs index b65c83075..9e4a9e2f4 100644 --- a/tests/CommunityToolkit.HighPerformance.UnitTests/Memory/Test_ReadOnlySpan2D{T}.cs +++ b/tests/CommunityToolkit.HighPerformance.UnitTests/Memory/Test_ReadOnlySpan2D{T}.cs @@ -36,6 +36,27 @@ public void Test_ReadOnlySpan2DT_Empty() Assert.AreEqual(empty2.Length, 0); Assert.AreEqual(empty2.Width, 0); Assert.AreEqual(empty2.Height, 0); + + ReadOnlySpan2D empty3 = new([], 0, 0); + + Assert.IsTrue(empty3.IsEmpty); + Assert.AreEqual(empty3.Length, 0); + Assert.AreEqual(empty3.Width, 0); + Assert.AreEqual(empty3.Height, 0); + + ReadOnlySpan2D empty4 = new([], 4, 0); + + Assert.IsTrue(empty4.IsEmpty); + Assert.AreEqual(empty4.Length, 0); + Assert.AreEqual(empty4.Width, 0); + Assert.AreEqual(empty4.Height, 4); + + ReadOnlySpan2D empty5 = new([], 0, 7); + + Assert.IsTrue(empty5.IsEmpty); + Assert.AreEqual(empty5.Length, 0); + Assert.AreEqual(empty5.Width, 7); + Assert.AreEqual(empty5.Height, 0); } #if NET6_0_OR_GREATER