Add GetReference and TryGetArray to MemoryMarshal (#15417)
authorAhson Khan <ahkha@microsoft.com>
Fri, 8 Dec 2017 11:04:57 +0000 (03:04 -0800)
committerJan Kotas <jkotas@microsoft.com>
Fri, 8 Dec 2017 11:04:57 +0000 (06:04 -0500)
* Add GetReference and TryGetArray to MemoryMarshal

* Marking GetReference with AggressiveInlining

* Do not use ByReference as a return type.

* Addressing PR feedback.

src/mscorlib/shared/System/ReadOnlyMemory.cs
src/mscorlib/shared/System/ReadOnlySpan.cs
src/mscorlib/shared/System/Runtime/InteropServices/MemoryMarshal.cs
src/mscorlib/shared/System/Span.cs

index d68f622..bdf92ff 100644 (file)
@@ -29,7 +29,7 @@ namespace System
         private readonly int _index;
         private readonly int _length;
 
-        private const int RemoveOwnedFlagBitMask = 0x7FFFFFFF;
+        internal const int RemoveOwnedFlagBitMask = 0x7FFFFFFF;
 
         /// <summary>
         /// Creates a new memory over the entirety of the target array.
index 7a8243d..a7f6f6e 100644 (file)
@@ -21,7 +21,7 @@ namespace System
     public readonly ref struct ReadOnlySpan<T>
     {
         /// <summary>A byref or a native ptr.</summary>
-        private readonly ByReference<T> _pointer;
+        internal readonly ByReference<T> _pointer;
         /// <summary>The number of elements this ReadOnlySpan contains.</summary>
 #if PROJECTN
         [Bound]
index 5301f87..5ee643f 100644 (file)
@@ -2,6 +2,7 @@
 // The .NET Foundation licenses this file to you under the MIT license.
 // See the LICENSE file in the project root for more information.
 
+using System.Buffers;
 using System.Runtime.CompilerServices;
 
 namespace System.Runtime.InteropServices
@@ -23,5 +24,30 @@ namespace System.Runtime.InteropServices
         /// </remarks>
         public static Memory<T> AsMemory<T>(ReadOnlyMemory<T> readOnlyMemory) =>
             Unsafe.As<ReadOnlyMemory<T>, Memory<T>>(ref readOnlyMemory);
+
+        public static ref T GetReference<T>(Span<T> span) => ref span._pointer.Value;
+
+        public static ref readonly T GetReference<T>(ReadOnlySpan<T> span) => ref span._pointer.Value;
+
+        public static bool TryGetArray<T>(ReadOnlyMemory<T> readOnlyMemory, out ArraySegment<T> arraySegment)
+        {
+            object obj = readOnlyMemory.GetObjectStartLength(out int index, out int length);
+            if (index < 0)
+            {
+                if (((OwnedMemory<T>)obj).TryGetArray(out var segment))
+                {
+                    arraySegment = new ArraySegment<T>(segment.Array, segment.Offset + (index & ReadOnlyMemory<T>.RemoveOwnedFlagBitMask), length);
+                    return true;
+                }
+            }
+            else if (obj is T[] arr)
+            {
+                arraySegment = new ArraySegment<T>(arr, index, length);
+                return true;
+            }
+
+            arraySegment = default;
+            return false;
+        }
     }
 }
index ca146ae..45d630d 100644 (file)
@@ -27,7 +27,7 @@ namespace System
     public readonly ref struct Span<T>
     {
         /// <summary>A byref or a native ptr.</summary>
-        private readonly ByReference<T> _pointer;
+        internal readonly ByReference<T> _pointer;
         /// <summary>The number of elements this Span contains.</summary>
 #if PROJECTN
         [Bound]