diff --git a/src/libraries/Common/tests/System/Runtime/CompilerServices/RuntimeHelpers.cs b/src/libraries/Common/tests/System/Runtime/CompilerServices/RuntimeHelpers.cs
new file mode 100644
index 0000000000000..1b7fe928a7fee
--- /dev/null
+++ b/src/libraries/Common/tests/System/Runtime/CompilerServices/RuntimeHelpers.cs
@@ -0,0 +1,43 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace System.Runtime.CompilerServices
+{
+ internal static class RuntimeHelpers
+ {
+ ///
+ /// Slices the specified array using the specified range.
+ ///
+ internal static T[] GetSubArray(T[] array, Range range)
+ {
+ if (array == null)
+ {
+ throw new ArgumentNullException(nameof(array));
+ }
+
+ (int offset, int length) = range.GetOffsetAndLength(array.Length);
+
+ if (default(T) != null || typeof(T[]) == array.GetType())
+ {
+ // We know the type of the array to be exactly T[].
+
+ if (length == 0)
+ {
+ return Array.Empty();
+ }
+
+ var dest = new T[length];
+ Array.Copy(array, offset, dest, 0, length);
+ return dest;
+ }
+ else
+ {
+ // The array is actually a U[] where U:T.
+ var dest = (T[])Array.CreateInstance(array.GetType().GetElementType(), length);
+ Array.Copy(array, offset, dest, 0, length);
+ return dest;
+ }
+ }
+ }
+}
+
diff --git a/src/libraries/Microsoft.Bcl.Memory/ref/Microsoft.Bcl.Memory.Forwards.netstandard21.cs b/src/libraries/Microsoft.Bcl.Memory/ref/Microsoft.Bcl.Memory.Forwards.netstandard21.cs
new file mode 100644
index 0000000000000..4bfc68544aa76
--- /dev/null
+++ b/src/libraries/Microsoft.Bcl.Memory/ref/Microsoft.Bcl.Memory.Forwards.netstandard21.cs
@@ -0,0 +1,5 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Index))]
+[assembly: System.Runtime.CompilerServices.TypeForwardedTo(typeof(System.Range))]
diff --git a/src/libraries/Microsoft.Bcl.Memory/ref/Microsoft.Bcl.Memory.csproj b/src/libraries/Microsoft.Bcl.Memory/ref/Microsoft.Bcl.Memory.csproj
index a122f2cfeebb5..ae94b2d611097 100644
--- a/src/libraries/Microsoft.Bcl.Memory/ref/Microsoft.Bcl.Memory.csproj
+++ b/src/libraries/Microsoft.Bcl.Memory/ref/Microsoft.Bcl.Memory.csproj
@@ -1,7 +1,7 @@
- netstandard2.0;$(NetFrameworkMinimum);$(NetCoreAppCurrent)
+ netstandard2.0;netstandard2.1;$(NetFrameworkMinimum);$(NetCoreAppCurrent)
@@ -12,6 +12,20 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/src/libraries/Microsoft.Bcl.Memory/ref/Microsoft.Bcl.Memory.netstandard20.cs b/src/libraries/Microsoft.Bcl.Memory/ref/Microsoft.Bcl.Memory.netstandard20.cs
new file mode 100644
index 0000000000000..3044055cc4834
--- /dev/null
+++ b/src/libraries/Microsoft.Bcl.Memory/ref/Microsoft.Bcl.Memory.netstandard20.cs
@@ -0,0 +1,41 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// ------------------------------------------------------------------------------
+// Changes to this file must follow the https://aka.ms/api-review process.
+// ------------------------------------------------------------------------------
+
+namespace System
+{
+ public readonly partial struct Index : System.IEquatable
+ {
+ private readonly int _dummyPrimitive;
+ public Index(int value, bool fromEnd = false) { throw null; }
+ public static System.Index End { get { throw null; } }
+ public bool IsFromEnd { get { throw null; } }
+ public static System.Index Start { get { throw null; } }
+ public int Value { get { throw null; } }
+ public bool Equals(System.Index other) { throw null; }
+ public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; }
+ public static System.Index FromEnd(int value) { throw null; }
+ public static System.Index FromStart(int value) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public int GetOffset(int length) { throw null; }
+ public static implicit operator System.Index (int value) { throw null; }
+ public override string ToString() { throw null; }
+ }
+ public readonly partial struct Range : System.IEquatable
+ {
+ private readonly int _dummyPrimitive;
+ public Range(System.Index start, System.Index end) { throw null; }
+ public static System.Range All { get { throw null; } }
+ public System.Index End { get { throw null; } }
+ public System.Index Start { get { throw null; } }
+ public static System.Range EndAt(System.Index end) { throw null; }
+ public override bool Equals([System.Diagnostics.CodeAnalysis.NotNullWhenAttribute(true)] object? value) { throw null; }
+ public bool Equals(System.Range other) { throw null; }
+ public override int GetHashCode() { throw null; }
+ public (int Offset, int Length) GetOffsetAndLength(int length) { throw null; }
+ public static System.Range StartAt(System.Index start) { throw null; }
+ public override string ToString() { throw null; }
+ }
+}
\ No newline at end of file
diff --git a/src/libraries/Microsoft.Bcl.Memory/src/Microsoft.Bcl.Memory.csproj b/src/libraries/Microsoft.Bcl.Memory/src/Microsoft.Bcl.Memory.csproj
index 8c8600b3c459d..0b191a869540f 100644
--- a/src/libraries/Microsoft.Bcl.Memory/src/Microsoft.Bcl.Memory.csproj
+++ b/src/libraries/Microsoft.Bcl.Memory/src/Microsoft.Bcl.Memory.csproj
@@ -1,18 +1,22 @@
- netstandard2.0;$(NetFrameworkMinimum);$(NetCoreAppCurrent)
+ netstandard2.0;netstandard2.1;$(NetFrameworkMinimum);$(NetCoreAppCurrent)
true
true
+ MICROSOFT_BCL_MEMORY;$(DefineConstants)
true
Provides Base64Url encoding, decoding and validation APIs support for .NET Framework and .NET Standard.
+ Provides Index and Range types support for .NET Framework and .NET Standard 2.0.
Commonly Used Types:
System.Buffers.Text.Base64Url
+ System.Index
+ System.Range
@@ -25,6 +29,11 @@
+
+
+
+
+
System\Buffers\Text\Base64Helper\Base64Helper.cs
@@ -49,8 +58,18 @@
+
+
+
+
+
+
+
-
+
+
+
+
diff --git a/src/libraries/Microsoft.Bcl.Memory/tests/Microsoft.Bcl.Memory.Tests.csproj b/src/libraries/Microsoft.Bcl.Memory/tests/Microsoft.Bcl.Memory.Tests.csproj
index f3f7262755c19..e805a830958db 100644
--- a/src/libraries/Microsoft.Bcl.Memory/tests/Microsoft.Bcl.Memory.Tests.csproj
+++ b/src/libraries/Microsoft.Bcl.Memory/tests/Microsoft.Bcl.Memory.Tests.csproj
@@ -24,10 +24,23 @@
System\Memory\Base64Url\Base64UrlValidationUnitTests.cs
+
+ System\RangeTests.cs
+
+
+ System\IndexTests.cs
+
-
+
+
+
+
+ System\Runtime\CompilerServices\RuntimeHelpers.cs
+
+
+
-
+
diff --git a/src/libraries/System.Private.CoreLib/src/System/Index.cs b/src/libraries/System.Private.CoreLib/src/System/Index.cs
index 23c3765e8bcc6..8858102be1e79 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Index.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Index.cs
@@ -15,7 +15,7 @@ namespace System
/// int lastElement = someArray[^1]; // lastElement = 5
///
///
-#if SYSTEM_PRIVATE_CORELIB
+#if SYSTEM_PRIVATE_CORELIB || MICROSOFT_BCL_MEMORY
public
#else
internal
diff --git a/src/libraries/System.Private.CoreLib/src/System/Range.cs b/src/libraries/System.Private.CoreLib/src/System/Range.cs
index 76308162f110c..f29f366ef486f 100644
--- a/src/libraries/System.Private.CoreLib/src/System/Range.cs
+++ b/src/libraries/System.Private.CoreLib/src/System/Range.cs
@@ -20,7 +20,7 @@ namespace System
/// int[] subArray2 = someArray[1..^0]; // { 2, 3, 4, 5 }
///
///
-#if SYSTEM_PRIVATE_CORELIB
+#if SYSTEM_PRIVATE_CORELIB || MICROSOFT_BCL_MEMORY
public
#else
internal