Skip to content

Commit e2c2580

Browse files
committed
Fixed [ReadOnly]Span2D<T>.TryGetSpan when no runtime support
Closes #3947
1 parent 0c9a3c5 commit e2c2580

File tree

4 files changed

+25
-4
lines changed

4 files changed

+25
-4
lines changed

Microsoft.Toolkit.HighPerformance/Memory/ReadOnlySpan2D{T}.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -906,7 +906,10 @@ public bool TryGetSpan(out ReadOnlySpan<T> span)
906906
// Without Span<T> runtime support, we can only get a Span<T> from a T[] instance
907907
if (this.instance.GetType() == typeof(T[]))
908908
{
909-
span = Unsafe.As<T[]>(this.instance).AsSpan((int)this.offset, (int)Length);
909+
T[] array = Unsafe.As<T[]>(this.instance)!;
910+
int index = array.AsSpan().IndexOf(ref ObjectMarshal.DangerousGetObjectDataReferenceAt<T>(array, this.offset));
911+
912+
span = array.AsSpan(index, (int)Length);
910913

911914
return true;
912915
}

Microsoft.Toolkit.HighPerformance/Memory/Span2D{T}.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1062,7 +1062,10 @@ public bool TryGetSpan(out Span<T> span)
10621062
// Without Span<T> runtime support, we can only get a Span<T> from a T[] instance
10631063
if (this.Instance.GetType() == typeof(T[]))
10641064
{
1065-
span = Unsafe.As<T[]>(this.Instance).AsSpan((int)this.Offset, (int)Length);
1065+
T[] array = Unsafe.As<T[]>(this.Instance)!;
1066+
int index = array.AsSpan().IndexOf(ref ObjectMarshal.DangerousGetObjectDataReferenceAt<T>(array, this.Offset));
1067+
1068+
span = array.AsSpan(index, (int)Length);
10661069

10671070
return true;
10681071
}

UnitTests/UnitTests.HighPerformance.Shared/Memory/Test_ReadOnlySpan2D{T}.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -605,7 +605,7 @@ public void Test_ReadOnlySpan2DT_TryGetSpan_From1DArray_2()
605605
{
606606
int[] array = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
607607

608-
ReadOnlySpan2D<int> span2d = new ReadOnlySpan2D<int>(array, 3, 3).Slice(1, 0, 2, 3);
608+
ReadOnlySpan2D<int> span2d = new ReadOnlySpan2D<int>(array, 3, 3).Slice(1, 0, 3, 2);
609609

610610
bool success = span2d.TryGetSpan(out ReadOnlySpan<int> span);
611611

@@ -620,7 +620,7 @@ public void Test_ReadOnlySpan2DT_TryGetSpan_From1DArray_3()
620620
{
621621
int[] array = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
622622

623-
ReadOnlySpan2D<int> span2d = new ReadOnlySpan2D<int>(array, 3, 3).Slice(0, 1, 3, 2);
623+
ReadOnlySpan2D<int> span2d = new ReadOnlySpan2D<int>(array, 3, 3).Slice(0, 1, 2, 3);
624624

625625
bool success = span2d.TryGetSpan(out ReadOnlySpan<int> span);
626626

UnitTests/UnitTests.HighPerformance.Shared/Memory/Test_Span2D{T}.cs

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -803,6 +803,21 @@ public void Test_Span2DT_TryGetSpan_From1DArray_3()
803803
Assert.AreEqual(span.Length, 0);
804804
}
805805

806+
// See https://github.com/windows-toolkit/WindowsCommunityToolkit/issues/3947
807+
[TestCategory("Span2DT")]
808+
[TestMethod]
809+
public void Test_Span2DT_TryGetSpan_From1DArray_4()
810+
{
811+
int[] array = new int[128];
812+
Span2D<int> span2d = new Span2D<int>(array, 8, 16);
813+
814+
bool success = span2d.TryGetSpan(out Span<int> span);
815+
816+
Assert.IsTrue(success);
817+
Assert.AreEqual(span.Length, span2d.Length);
818+
Assert.IsTrue(Unsafe.AreSame(ref array[0], ref span[0]));
819+
}
820+
806821
[TestCategory("Span2DT")]
807822
[TestMethod]
808823
public void Test_Span2DT_TryGetSpan_From2DArray_1()

0 commit comments

Comments
 (0)