Add MemoryMarshal.AsRef implementation (#19021)
authorJan Kotas <jkotas@microsoft.com>
Thu, 19 Jul 2018 15:29:36 +0000 (08:29 -0700)
committerGitHub <noreply@github.com>
Thu, 19 Jul 2018 15:29:36 +0000 (08:29 -0700)
Contributes to https://github.com/dotnet/corefx/issues/30613

src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MemoryMarshal.Fast.cs
src/System.Private.CoreLib/shared/System/Runtime/InteropServices/MemoryMarshal.cs

index a954529..e3cf0a8 100644 (file)
@@ -102,7 +102,7 @@ namespace System.Runtime.InteropServices
         /// These types may not contain pointers or references. This is checked at runtime in order to preserve type safety.
         /// </summary>
         /// <remarks>
-        /// Supported only for platforms that support misaligned memory access.
+        /// Supported only for platforms that support misaligned memory access or when the memory block is aligned by other means.
         /// </remarks>
         /// <param name="span">The source slice, of type <typeparamref name="TFrom"/>.</param>
         /// <exception cref="System.ArgumentException">
@@ -157,7 +157,7 @@ namespace System.Runtime.InteropServices
         /// These types may not contain pointers or references. This is checked at runtime in order to preserve type safety.
         /// </summary>
         /// <remarks>
-        /// Supported only for platforms that support misaligned memory access.
+        /// Supported only for platforms that support misaligned memory access or when the memory block is aligned by other means.
         /// </remarks>
         /// <param name="span">The source slice, of type <typeparamref name="TFrom"/>.</param>
         /// <exception cref="System.ArgumentException">
index 5e33ced..fcc9c4f 100644 (file)
@@ -212,6 +212,50 @@ namespace System.Runtime.InteropServices
         }
 
         /// <summary>
+        /// Re-interprets a span of bytes as a reference to structure of type T.
+        /// The type may not contain pointers or references. This is checked at runtime in order to preserve type safety.
+        /// </summary>
+        /// <remarks>
+        /// Supported only for platforms that support misaligned memory access or when the memory block is aligned by other means.
+        /// </remarks>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static ref T AsRef<T>(Span<byte> span)
+            where T : struct
+        {
+            if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
+            {
+                ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(T));
+            }
+            if (Unsafe.SizeOf<T>() > (uint)span.Length)
+            {
+                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length);
+            }
+            return ref Unsafe.As<byte, T>(ref GetReference(span));
+        }
+
+        /// <summary>
+        /// Re-interprets a span of bytes as a reference to structure of type T.
+        /// The type may not contain pointers or references. This is checked at runtime in order to preserve type safety.
+        /// </summary>
+        /// <remarks>
+        /// Supported only for platforms that support misaligned memory access or when the memory block is aligned by other means.
+        /// </remarks>
+        [MethodImpl(MethodImplOptions.AggressiveInlining)]
+        public static ref readonly T AsRef<T>(ReadOnlySpan<byte> span)
+            where T : struct
+        {
+            if (RuntimeHelpers.IsReferenceOrContainsReferences<T>())
+            {
+                ThrowHelper.ThrowInvalidTypeWithPointersNotSupported(typeof(T));
+            }
+            if (Unsafe.SizeOf<T>() > (uint)span.Length)
+            {
+                ThrowHelper.ThrowArgumentOutOfRangeException(ExceptionArgument.length);
+            }
+            return ref Unsafe.As<byte, T>(ref GetReference(span));
+        }
+
+        /// <summary>
         /// Creates a new memory over the portion of the pre-pinned target array beginning
         /// at 'start' index and ending at 'end' index (exclusive).
         /// </summary>