Span factoring (dotnet/corefx#26667)
authorTarek Mahmoud Sayed <tarekms@microsoft.com>
Fri, 2 Feb 2018 19:40:39 +0000 (11:40 -0800)
committerJan Kotas <jkotas@microsoft.com>
Fri, 2 Feb 2018 19:40:39 +0000 (11:40 -0800)
Commit migrated from https://github.com/dotnet/corefx/commit/a68803c848df70ae900f53e602424ba71a4760b1

src/libraries/System.Memory/src/Resources/Strings.resx
src/libraries/System.Memory/src/System.Memory.csproj
src/libraries/System.Memory/src/System/ReadOnlySpan.Portable.cs [moved from src/libraries/System.Memory/src/System/ReadOnlySpan.cs with 73% similarity]
src/libraries/System.Memory/src/System/Span.Portable.cs [moved from src/libraries/System.Memory/src/System/Span.cs with 81% similarity]

index 219d3c9..802f755 100644 (file)
   <resheader name="writer">
     <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
   </resheader>
-  <data name="CannotCallEqualsOnSpan" xml:space="preserve">
+  <data name="NotSupported_CannotCallEqualsOnSpan" xml:space="preserve">
     <value>Equals() on Span and ReadOnlySpan is not supported. Use operator== instead.</value>
   </data>
-  <data name="CannotCallGetHashCodeOnSpan" xml:space="preserve">
+  <data name="NotSupported_CannotCallGetHashCodeOnSpan" xml:space="preserve">
     <value>GetHashCode() on Span and ReadOnlySpan is not supported.</value>
   </data>
   <data name="Argument_InvalidTypeWithPointersNotSupported" xml:space="preserve">
index 7150e7f..26dd461 100644 (file)
     <Compile Include="$(CommonPath)\CoreLib\System\Memory.cs" />
     <Compile Include="$(CommonPath)\CoreLib\System\MemoryDebugView.cs" />
     <Compile Include="$(CommonPath)\CoreLib\System\ReadOnlyMemory.cs" />
+    <Compile Include="$(CommonPath)\CoreLib\System\ReadOnlySpan.cs" />
+    <Compile Include="$(CommonPath)\CoreLib\System\Span.cs" />
     <Compile Include="$(CommonPath)\CoreLib\System\SpanDebugView.cs" />
     <Compile Include="$(CommonPath)\CoreLib\System\Buffers\IRetainable.cs" />
     <Compile Include="$(CommonPath)\CoreLib\System\Buffers\MemoryHandle.cs" />
     <Compile Include="$(CommonPath)\CoreLib\System\Buffers\OwnedMemory.cs" />
     <Compile Include="$(CommonPath)\CoreLib\System\Runtime\InteropServices\MemoryMarshal.cs" />
-    <Compile Include="System\ReadOnlySpan.cs" />
-    <Compile Include="System\Span.cs" />
+    <Compile Include="System\ReadOnlySpan.Portable.cs" />
+    <Compile Include="System\Span.Portable.cs" />
     <Compile Include="System\MemoryExtensions.Portable.cs" />
     <Compile Include="System\SpanHelpers.cs" />
     <Compile Include="System\Pinnable.cs" />
@@ -17,7 +17,7 @@ namespace System
     /// </summary>
     [DebuggerTypeProxy(typeof(SpanDebugView<>))]
     [DebuggerDisplay("{DebuggerDisplay,nq}")]
-    public readonly ref struct ReadOnlySpan<T>
+    public readonly ref partial struct ReadOnlySpan<T>
     {
         /// <summary>
         /// Creates a new read-only span over the entirety of the target array.
@@ -106,16 +106,6 @@ namespace System
         private string DebuggerDisplay => string.Format("System.ReadOnlySpan<{0}>[{1}]", typeof(T).Name, Length);
 
         /// <summary>
-        /// The number of items in the read-only span.
-        /// </summary>
-        public int Length => _length;
-
-        /// <summary>
-        /// Returns true if Length is 0.
-        /// </summary>
-        public bool IsEmpty => _length == 0;
-
-        /// <summary>
         /// Returns the specified element of the read-only span.
         /// </summary>
         /// <param name="index"></param>
@@ -190,55 +180,12 @@ namespace System
         }
 
         /// <summary>
-        /// Returns false if left and right point at the same memory and have the same length.  Note that
-        /// this does *not* check to see if the *contents* are equal.
-        /// </summary>
-        public static bool operator !=(ReadOnlySpan<T> left, ReadOnlySpan<T> right) => !(left == right);
-
-        /// <summary>
-        /// This method is not supported as spans cannot be boxed. To compare two spans, use operator==.
-        /// <exception cref="System.NotSupportedException">
-        /// Always thrown by this method.
-        /// </exception>
-        /// </summary>
-        [Obsolete("Equals() on ReadOnlySpan will always throw an exception. Use == instead.")]
-        [EditorBrowsable(EditorBrowsableState.Never)]
-        public override bool Equals(object obj)
-        {
-            throw new NotSupportedException(SR.CannotCallEqualsOnSpan);
-        }
-
-        /// <summary>
-        /// This method is not supported as spans cannot be boxed.
-        /// <exception cref="System.NotSupportedException">
-        /// Always thrown by this method.
-        /// </exception>
-        /// </summary>
-        [Obsolete("GetHashCode() on ReadOnlySpan will always throw an exception.")]
-        [EditorBrowsable(EditorBrowsableState.Never)]
-        public override int GetHashCode()
-        {
-            throw new NotSupportedException(SR.CannotCallGetHashCodeOnSpan);
-        }
-
-        /// <summary>
         /// Returns a <see cref="String"/> with the name of the type and the number of elements
         /// </summary>
         /// <returns>A <see cref="String"/> with the name of the type and the number of elements</returns>
         public override string ToString() => string.Format("System.ReadOnlySpan<{0}>[{1}]", typeof(T).Name, _length);
 
         /// <summary>
-        /// Defines an implicit conversion of an array to a <see cref="ReadOnlySpan{T}"/>
-        /// </summary>
-        public static implicit operator ReadOnlySpan<T>(T[] array) => array != null ? new ReadOnlySpan<T>(array) : default;
-
-        /// <summary>
-        /// Defines an implicit conversion of a <see cref="ArraySegment{T}"/> to a <see cref="ReadOnlySpan{T}"/>
-        /// </summary>
-        public static implicit operator ReadOnlySpan<T>(ArraySegment<T> arraySegment)
-            => arraySegment.Array != null ? new ReadOnlySpan<T>(arraySegment.Array, arraySegment.Offset, arraySegment.Count) : default;
-
-        /// <summary>
         /// Forms a slice out of the given read-only span, beginning at 'start'.
         /// </summary>
         /// <param name="start">The index at which to begin this slice.</param>
@@ -290,11 +237,6 @@ namespace System
         }
 
         /// <summary>
-        /// Returns a 0-length read-only span whose base is the null pointer.
-        /// </summary>
-        public static ReadOnlySpan<T> Empty => default(ReadOnlySpan<T>);
-
-        /// <summary>
         /// This method is obsolete, use System.Runtime.InteropServices.MemoryMarshal.GetReference instead.
         /// Returns a reference to the 0th element of the Span. If the Span is empty, returns a reference to the location where the 0th element
         /// would have been stored. Such a reference can be used for pinning but must never be dereferenced.
@@ -309,61 +251,6 @@ namespace System
                 return ref Unsafe.AddByteOffset<T>(ref _pinnable.Data, _byteOffset);
         }
 
-        /// <summary>Gets an enumerator for this span.</summary>
-        public Enumerator GetEnumerator() => new Enumerator(this);
-
-        /// <summary>Enumerates the elements of a <see cref="ReadOnlySpan{T}"/>.</summary>
-        public ref struct Enumerator
-        {
-            /// <summary>The span being enumerated.</summary>
-            private readonly ReadOnlySpan<T> _span;
-            /// <summary>The next index to yield.</summary>
-            private int _index;
-
-            /// <summary>Initialize the enumerator.</summary>
-            /// <param name="span">The span to enumerate.</param>
-            [MethodImpl(MethodImplOptions.AggressiveInlining)]
-            internal Enumerator(ReadOnlySpan<T> span)
-            {
-                _span = span;
-                _index = -1;
-            }
-
-            /// <summary>Advances the enumerator to the next element of the span.</summary>
-            [MethodImpl(MethodImplOptions.AggressiveInlining)]
-            public bool MoveNext()
-            {
-                int index = _index + 1;
-                if (index < _span.Length)
-                {
-                    _index = index;
-                    return true;
-                }
-
-                return false;
-            }
-
-            /// <summary>Gets the element at the current position of the enumerator.</summary>
-            public ref readonly T Current
-            {
-                [MethodImpl(MethodImplOptions.AggressiveInlining)]
-                get
-                {
-                    // TODO https://github.com/dotnet/corefx/issues/24105:
-                    // Change this to simply be:
-                    //     get => ref _span[_index];
-                    // once ReadOnlySpan<T>'s indexer returns ref readonly.
-
-                    if ((uint)_index >= (uint)_span.Length)
-                    {
-                        ThrowHelper.ThrowIndexOutOfRangeException();
-                    }
-
-                    return ref Unsafe.Add(ref _span.DangerousGetPinnableReference(), _index);
-                }
-            }
-        }
-
         // These expose the internal representation for Span-related apis use only.
         internal Pinnable<T> Pinnable => _pinnable;
         internal IntPtr ByteOffset => _byteOffset;
@@ -17,7 +17,7 @@ namespace System
     /// </summary>
     [DebuggerTypeProxy(typeof(SpanDebugView<>))]
     [DebuggerDisplay("{DebuggerDisplay,nq}")]
-    public readonly ref struct Span<T>
+    public readonly ref partial struct Span<T>
     {
         /// <summary>
         /// Creates a new span over the entirety of the target array.
@@ -110,16 +110,6 @@ namespace System
         private string DebuggerDisplay => string.Format("System.Span<{0}>[{1}]", typeof(T).Name, _length);
 
         /// <summary>
-        /// The number of items in the span.
-        /// </summary>
-        public int Length => _length;
-
-        /// <summary>
-        /// Returns true if Length is 0.
-        /// </summary>
-        public bool IsEmpty => _length == 0;
-
-        /// <summary>
         /// Returns a reference to specified element of the Span.
         /// </summary>
         /// <param name="index"></param>
@@ -297,36 +287,9 @@ namespace System
         }
 
         /// <summary>
-        /// Returns false if left and right point at the same memory and have the same length.  Note that
-        /// this does *not* check to see if the *contents* are equal.
-        /// </summary>
-        public static bool operator !=(Span<T> left, Span<T> right) => !(left == right);
-
-        /// <summary>
-        /// This method is not supported as spans cannot be boxed. To compare two spans, use operator==.
-        /// <exception cref="System.NotSupportedException">
-        /// Always thrown by this method.
-        /// </exception>
-        /// </summary>
-        [Obsolete("Equals() on Span will always throw an exception. Use == instead.")]
-        [EditorBrowsable(EditorBrowsableState.Never)]
-        public override bool Equals(object obj)
-        {
-            throw new NotSupportedException(SR.CannotCallEqualsOnSpan);
-        }
-
-        /// <summary>
-        /// This method is not supported as spans cannot be boxed.
-        /// <exception cref="System.NotSupportedException">
-        /// Always thrown by this method.
-        /// </exception>
+        /// Defines an implicit conversion of a <see cref="Span{T}"/> to a <see cref="ReadOnlySpan{T}"/>
         /// </summary>
-        [Obsolete("GetHashCode() on Span will always throw an exception.")]
-        [EditorBrowsable(EditorBrowsableState.Never)]
-        public override int GetHashCode()
-        {
-            throw new NotSupportedException(SR.CannotCallGetHashCodeOnSpan);
-        }
+        public static implicit operator ReadOnlySpan<T>(Span<T> span) => new ReadOnlySpan<T>(span._pinnable, span._byteOffset, span._length);
 
         /// <summary>
         /// Returns a <see cref="String"/> with the name of the type and the number of elements
@@ -335,22 +298,6 @@ namespace System
         public override string ToString() => string.Format("System.Span<{0}>[{1}]", typeof(T).Name, Length);
 
         /// <summary>
-        /// Defines an implicit conversion of an array to a <see cref="Span{T}"/>
-        /// </summary>
-        public static implicit operator Span<T>(T[] array) => array != null ? new Span<T>(array) : default;
-
-        /// <summary>
-        /// Defines an implicit conversion of a <see cref="ArraySegment{T}"/> to a <see cref="Span{T}"/>
-        /// </summary>
-        public static implicit operator Span<T>(ArraySegment<T> arraySegment)
-            => arraySegment.Array != null ? new Span<T>(arraySegment.Array, arraySegment.Offset, arraySegment.Count) : default;
-
-        /// <summary>
-        /// Defines an implicit conversion of a <see cref="Span{T}"/> to a <see cref="ReadOnlySpan{T}"/>
-        /// </summary>
-        public static implicit operator ReadOnlySpan<T>(Span<T> span) => new ReadOnlySpan<T>(span._pinnable, span._byteOffset, span._length);
-
-        /// <summary>
         /// Forms a slice out of the given span, beginning at 'start'.
         /// </summary>
         /// <param name="start">The index at which to begin this slice.</param>
@@ -402,11 +349,6 @@ namespace System
         }
 
         /// <summary>
-        /// Returns a 0-length span whose base is the null pointer.
-        /// </summary>
-        public static Span<T> Empty => default(Span<T>);
-
-        /// <summary>
         /// This method is obsolete, use System.Runtime.InteropServices.MemoryMarshal.GetReference instead.
         /// Returns a reference to the 0th element of the Span. If the Span is empty, returns a reference to the location where the 0th element
         /// would have been stored. Such a reference can be used for pinning but must never be dereferenced.
@@ -421,48 +363,6 @@ namespace System
                 return ref Unsafe.AddByteOffset<T>(ref _pinnable.Data, _byteOffset);
         }
 
-        /// <summary>Gets an enumerator for this span.</summary>
-        public Enumerator GetEnumerator() => new Enumerator(this);
-
-        /// <summary>Enumerates the elements of a <see cref="Span{T}"/>.</summary>
-        public ref struct Enumerator
-        {
-            /// <summary>The span being enumerated.</summary>
-            private readonly Span<T> _span;
-            /// <summary>The next index to yield.</summary>
-            private int _index;
-
-            /// <summary>Initialize the enumerator.</summary>
-            /// <param name="span">The span to enumerate.</param>
-            [MethodImpl(MethodImplOptions.AggressiveInlining)]
-            internal Enumerator(Span<T> span)
-            {
-                _span = span;
-                _index = -1;
-            }
-
-            /// <summary>Advances the enumerator to the next element of the span.</summary>
-            [MethodImpl(MethodImplOptions.AggressiveInlining)]
-            public bool MoveNext()
-            {
-                int index = _index + 1;
-                if (index < _span.Length)
-                {
-                    _index = index;
-                    return true;
-                }
-
-                return false;
-            }
-
-            /// <summary>Gets the element at the current position of the enumerator.</summary>
-            public ref T Current
-            {
-                [MethodImpl(MethodImplOptions.AggressiveInlining)]
-                get => ref _span[_index];
-            }
-        }
-
         // These expose the internal representation for Span-related apis use only.
         internal Pinnable<T> Pinnable => _pinnable;
         internal IntPtr ByteOffset => _byteOffset;