Add ref asms and unit tests for Rune.Encode APIs (dotnet/corefx#36035)
authorLevi Broderick <GrabYourPitchforks@users.noreply.github.com>
Wed, 27 Mar 2019 06:23:21 +0000 (23:23 -0700)
committerGitHub <noreply@github.com>
Wed, 27 Mar 2019 06:23:21 +0000 (23:23 -0700)
Commit migrated from https://github.com/dotnet/corefx/commit/9da775f39d7cd3a20ae4732b96d7174ca634339a

src/libraries/System.Runtime/ref/System.Runtime.cs
src/libraries/System.Runtime/src/ApiCompatBaseline.uapaot.txt
src/libraries/System.Runtime/tests/System/Text/RuneTests.netcoreapp.cs
src/libraries/System.Text.Json/src/System/Text/Json/Reader/JsonReaderHelper.Unescaping.cs

index 95a80df..654b711 100644 (file)
@@ -7689,10 +7689,12 @@ namespace System.Text
         public int Utf8SequenceLength { get { throw null; } }
         public int Value { get { throw null; } }
         public int CompareTo(System.Text.Rune other) { throw null; }
-        public static System.Buffers.OperationStatus DecodeUtf16(System.ReadOnlySpan<char> utf16Source, out System.Text.Rune result, out int charsConsumed) { throw null; }
-        public static System.Buffers.OperationStatus DecodeUtf16FromEnd(System.ReadOnlySpan<char> utf16Source, out System.Text.Rune result, out int charsConsumed) { throw null; }
-        public static System.Buffers.OperationStatus DecodeUtf8(System.ReadOnlySpan<byte> utf8Source, out System.Text.Rune result, out int bytesConsumed) { throw null; }
-        public static System.Buffers.OperationStatus DecodeUtf8FromEnd(System.ReadOnlySpan<byte> utf8Source, out System.Text.Rune result, out int bytesConsumed) { throw null; }
+        public static System.Buffers.OperationStatus DecodeFromUtf16(System.ReadOnlySpan<char> source, out System.Text.Rune result, out int charsConsumed) { throw null; }
+        public static System.Buffers.OperationStatus DecodeFromUtf8(System.ReadOnlySpan<byte> source, out System.Text.Rune result, out int bytesConsumed) { throw null; }
+        public static System.Buffers.OperationStatus DecodeLastFromUtf16(System.ReadOnlySpan<char> source, out System.Text.Rune result, out int charsConsumed) { throw null; }
+        public static System.Buffers.OperationStatus DecodeLastFromUtf8(System.ReadOnlySpan<byte> source, out System.Text.Rune value, out int bytesConsumed) { throw null; }
+        public int EncodeToUtf16(System.Span<char> destination) { throw null; }
+        public int EncodeToUtf8(System.Span<byte> destination) { throw null; }
         public override bool Equals(object obj) { throw null; }
         public bool Equals(System.Text.Rune other) { throw null; }
         public override int GetHashCode() { throw null; }
@@ -7733,8 +7735,8 @@ namespace System.Text
         public static bool TryCreate(int value, out System.Text.Rune result) { throw null; }
         [System.CLSCompliantAttribute(false)]
         public static bool TryCreate(uint value, out System.Text.Rune result) { throw null; }
-        public bool TryEncode(System.Span<char> destination, out int charsWritten) { throw null; }
-        public bool TryEncodeToUtf8Bytes(System.Span<byte> destination, out int bytesWritten) { throw null; }
+        public bool TryEncodeToUtf16(System.Span<char> destination, out int charsWritten) { throw null; }
+        public bool TryEncodeToUtf8(System.Span<byte> destination, out int bytesWritten) { throw null; }
         public static bool TryGetRuneAt(string input, int index, out System.Text.Rune value) { throw null; }
     }
     public sealed partial class StringBuilder : System.Runtime.Serialization.ISerializable
index af47d04..aed70eb 100644 (file)
@@ -3,3 +3,11 @@ TypesMustExist : Type 'System.ArgIterator' does not exist in the implementation
 MembersMustExist : Member 'System.String System.Runtime.CompilerServices.RuntimeFeature.DefaultImplementationsOfInterfaces' does not exist in the implementation but it does exist in the contract.
 MembersMustExist : Member 'System.Runtime.CompilerServices.RuntimeHelpers.PrepareMethod(System.RuntimeMethodHandle)' does not exist in the implementation but it does exist in the contract.
 MembersMustExist : Member 'System.Runtime.CompilerServices.RuntimeHelpers.PrepareMethod(System.RuntimeMethodHandle, System.RuntimeTypeHandle[])' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Text.Rune.DecodeFromUtf16(System.ReadOnlySpan<System.Char>, System.Text.Rune, System.Int32)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Text.Rune.DecodeLastFromUtf16(System.ReadOnlySpan<System.Char>, System.Text.Rune, System.Int32)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Text.Rune.DecodeFromUtf8(System.ReadOnlySpan<System.Byte>, System.Text.Rune, System.Int32)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Text.Rune.DecodeLastFromUtf8(System.ReadOnlySpan<System.Byte>, System.Text.Rune, System.Int32)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Text.Rune.EncodeToUtf16(System.Span<System.Char>)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Text.Rune.TryEncodeToUtf16(System.Span<System.Char>, System.Int32)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Text.Rune.EncodeToUtf8(System.Span<System.Byte>)' does not exist in the implementation but it does exist in the contract.
+MembersMustExist : Member 'System.Text.Rune.TryEncodeToUtf8(System.Span<System.Byte>, System.Int32)' does not exist in the implementation but it does exist in the contract.
index c281585..d90f688 100644 (file)
@@ -4,7 +4,6 @@
 
 using System.Buffers;
 using System.Globalization;
-using System.Reflection;
 using Xunit;
 
 namespace System.Text.Tests
@@ -174,9 +173,9 @@ namespace System.Text.Tests
         [InlineData(new char[] { '\ud800' }, OperationStatus.NeedMoreData, 0xFFFD, 1)] // high surrogate at end of buffer
         [InlineData(new char[] { '\ud800', '\ud800' }, OperationStatus.InvalidData, 0xFFFD, 1)] // standalone high surrogate
         [InlineData(new char[] { '\ud800', '\u1234' }, OperationStatus.InvalidData, 0xFFFD, 1)] // standalone high surrogate
-        public static void DecodeUtf16(char[] data, OperationStatus expectedOperationStatus, int expectedRuneValue, int expectedCharsConsumed)
+        public static void DecodeFromUtf16(char[] data, OperationStatus expectedOperationStatus, int expectedRuneValue, int expectedCharsConsumed)
         {
-            Assert.Equal(expectedOperationStatus, Rune.DecodeUtf16(data, out Rune actualRune, out int actualCharsConsumed));
+            Assert.Equal(expectedOperationStatus, Rune.DecodeFromUtf16(data, out Rune actualRune, out int actualCharsConsumed));
             Assert.Equal(expectedRuneValue, actualRune.Value);
             Assert.Equal(expectedCharsConsumed, actualCharsConsumed);
         }
@@ -188,9 +187,9 @@ namespace System.Text.Tests
         [InlineData(new char[] { '\ud83d', '\ude32' }, OperationStatus.Done, 0x1F632, 2)] // supplementary value (U+1F632 ASTONISHED FACE)
         [InlineData(new char[] { '\u1234', '\udc00' }, OperationStatus.InvalidData, 0xFFFD, 1)] // standalone low surrogate
         [InlineData(new char[] { '\udc00' }, OperationStatus.InvalidData, 0xFFFD, 1)] // standalone low surrogate
-        public static void DecodeUtf16FromEnd(char[] data, OperationStatus expectedOperationStatus, int expectedRuneValue, int expectedCharsConsumed)
+        public static void DecodeLastFromUtf16(char[] data, OperationStatus expectedOperationStatus, int expectedRuneValue, int expectedCharsConsumed)
         {
-            Assert.Equal(expectedOperationStatus, Rune.DecodeUtf16FromEnd(data, out Rune actualRune, out int actualCharsConsumed));
+            Assert.Equal(expectedOperationStatus, Rune.DecodeLastFromUtf16(data, out Rune actualRune, out int actualCharsConsumed));
             Assert.Equal(expectedRuneValue, actualRune.Value);
             Assert.Equal(expectedCharsConsumed, actualCharsConsumed);
         }
@@ -222,9 +221,9 @@ namespace System.Text.Tests
         [InlineData(new byte[] { 0xF0, 0x9F, 0x98 }, OperationStatus.NeedMoreData, 0xFFFD, 3)] // [ F0 9F 98 ] is valid 3-byte start of 4-byte sequence
         [InlineData(new byte[] { 0xF0, 0x9F, 0x98, 0x20 }, OperationStatus.InvalidData, 0xFFFD, 3)] // [ F0 9F 98 ] followed by non-continuation byte, maximal invalid subsequence length 3
         [InlineData(new byte[] { 0xF0, 0x9F, 0x98, 0xB2 }, OperationStatus.Done, 0x1F632, 4)] // [ F0 9F 98 B2 ] is U+1F632 ASTONISHED FACE
-        public static void DecodeUtf8(byte[] data, OperationStatus expectedOperationStatus, int expectedRuneValue, int expectedBytesConsumed)
+        public static void DecodeFromUtf8(byte[] data, OperationStatus expectedOperationStatus, int expectedRuneValue, int expectedBytesConsumed)
         {
-            Assert.Equal(expectedOperationStatus, Rune.DecodeUtf8(data, out Rune actualRune, out int actualBytesConsumed));
+            Assert.Equal(expectedOperationStatus, Rune.DecodeFromUtf8(data, out Rune actualRune, out int actualBytesConsumed));
             Assert.Equal(expectedRuneValue, actualRune.Value);
             Assert.Equal(expectedBytesConsumed, actualBytesConsumed);
         }
@@ -243,9 +242,9 @@ namespace System.Text.Tests
         [InlineData(new byte[] { 0xE2, 0x88, 0xB4, 0xB2 }, OperationStatus.InvalidData, 0xFFFD, 1)] // [ B2 ] is standalone continuation byte
         [InlineData(new byte[] { 0x80, 0x62, 0x80, 0x80 }, OperationStatus.InvalidData, 0xFFFD, 1)] // [ 80 ] is standalone continuation byte
         [InlineData(new byte[] { 0xF0, 0x9F, 0x98, }, OperationStatus.NeedMoreData, 0xFFFD, 3)] // [ F0 9F 98 ] is valid 3-byte start of 4-byte sequence
-        public static void DecodeUtf8FromEnd(byte[] data, OperationStatus expectedOperationStatus, int expectedRuneValue, int expectedBytesConsumed)
+        public static void DecodeLastFromUtf8(byte[] data, OperationStatus expectedOperationStatus, int expectedRuneValue, int expectedBytesConsumed)
         {
-            Assert.Equal(expectedOperationStatus, Rune.DecodeUtf8FromEnd(data, out Rune actualRune, out int actualBytesConsumed));
+            Assert.Equal(expectedOperationStatus, Rune.DecodeLastFromUtf8(data, out Rune actualRune, out int actualBytesConsumed));
             Assert.Equal(expectedRuneValue, actualRune.Value);
             Assert.Equal(expectedBytesConsumed, actualBytesConsumed);
         }
@@ -530,7 +529,7 @@ namespace System.Text.Tests
         [Theory]
         [MemberData(nameof(GeneralTestData_BmpCodePoints_NoSurrogates))]
         [MemberData(nameof(GeneralTestData_SupplementaryCodePoints_ValidOnly))]
-        public static void TryEncode_AsUtf16(GeneralTestData testData)
+        public static void TryEncodeToUtf16(GeneralTestData testData)
         {
             Rune rune = new Rune(testData.ScalarValue);
             Assert.Equal(testData.Utf16Sequence.Length, rune.Utf16SequenceLength);
@@ -538,33 +537,41 @@ namespace System.Text.Tests
             // First, try with a buffer that's too short
 
             Span<char> utf16Buffer = stackalloc char[rune.Utf16SequenceLength - 1];
-            bool success = rune.TryEncode(utf16Buffer, out int charsWritten);
+            bool success = rune.TryEncodeToUtf16(utf16Buffer, out int charsWritten);
             Assert.False(success);
             Assert.Equal(0, charsWritten);
 
+            Assert.Throws<ArgumentException>("destination", () => rune.EncodeToUtf16(new char[rune.Utf16SequenceLength - 1]));
+
             // Then, try with a buffer that's appropriately sized
 
             utf16Buffer = stackalloc char[rune.Utf16SequenceLength];
-            success = rune.TryEncode(utf16Buffer, out charsWritten);
+            success = rune.TryEncodeToUtf16(utf16Buffer, out charsWritten);
             Assert.True(success);
             Assert.Equal(testData.Utf16Sequence.Length, charsWritten);
             Assert.True(utf16Buffer.SequenceEqual(testData.Utf16Sequence));
 
+            utf16Buffer.Clear();
+            Assert.Equal(testData.Utf16Sequence.Length, rune.EncodeToUtf16(utf16Buffer));
+            Assert.True(utf16Buffer.SequenceEqual(testData.Utf16Sequence));
+
             // Finally, try with a buffer that's too long (should succeed)
 
             utf16Buffer = stackalloc char[rune.Utf16SequenceLength + 1];
-            success = rune.TryEncode(utf16Buffer, out charsWritten);
+            success = rune.TryEncodeToUtf16(utf16Buffer, out charsWritten);
             Assert.True(success);
             Assert.Equal(testData.Utf16Sequence.Length, charsWritten);
             Assert.True(utf16Buffer.Slice(0, testData.Utf16Sequence.Length).SequenceEqual(testData.Utf16Sequence));
+
+            utf16Buffer.Clear();
+            Assert.Equal(testData.Utf16Sequence.Length, rune.EncodeToUtf16(utf16Buffer));
+            Assert.True(utf16Buffer.Slice(0, testData.Utf16Sequence.Length).SequenceEqual(testData.Utf16Sequence));
         }
 
-        // This test needs use private reflection into Rune at the moment because the
-        // TryEncode method which writes as UTF-8 isn't yet public.
         [Theory]
         [MemberData(nameof(GeneralTestData_BmpCodePoints_NoSurrogates))]
         [MemberData(nameof(GeneralTestData_SupplementaryCodePoints_ValidOnly))]
-        public static void TryEncode_AsUtf8(GeneralTestData testData)
+        public static void TryEncodeToUtf8(GeneralTestData testData)
         {
             Rune rune = new Rune(testData.ScalarValue);
             Assert.Equal(testData.Utf8Sequence.Length, actual: rune.Utf8SequenceLength);
@@ -572,25 +579,35 @@ namespace System.Text.Tests
             // First, try with a buffer that's too short
 
             Span<byte> utf8Buffer = stackalloc byte[rune.Utf8SequenceLength - 1];
-            bool success = rune.TryEncodeToUtf8Bytes(utf8Buffer, out int bytesWritten);
+            bool success = rune.TryEncodeToUtf8(utf8Buffer, out int bytesWritten);
             Assert.False(success);
             Assert.Equal(0, bytesWritten);
 
+            Assert.Throws<ArgumentException>("destination", () => rune.EncodeToUtf8(new byte[rune.Utf8SequenceLength - 1]));
+
             // Then, try with a buffer that's appropriately sized
 
             utf8Buffer = stackalloc byte[rune.Utf8SequenceLength];
-            success = rune.TryEncodeToUtf8Bytes(utf8Buffer, out bytesWritten);
+            success = rune.TryEncodeToUtf8(utf8Buffer, out bytesWritten);
             Assert.True(success);
             Assert.Equal(testData.Utf8Sequence.Length, bytesWritten);
             Assert.True(utf8Buffer.SequenceEqual(testData.Utf8Sequence));
 
+            utf8Buffer.Clear();
+            Assert.Equal(testData.Utf8Sequence.Length, rune.EncodeToUtf8(utf8Buffer));
+            Assert.True(utf8Buffer.SequenceEqual(testData.Utf8Sequence));
+
             // Finally, try with a buffer that's too long (should succeed)
 
             utf8Buffer = stackalloc byte[rune.Utf8SequenceLength + 1];
-            success = rune.TryEncodeToUtf8Bytes(utf8Buffer, out bytesWritten);
+            success = rune.TryEncodeToUtf8(utf8Buffer, out bytesWritten);
             Assert.True(success);
             Assert.Equal(testData.Utf8Sequence.Length, bytesWritten);
             Assert.True(utf8Buffer.Slice(0, testData.Utf8Sequence.Length).SequenceEqual(testData.Utf8Sequence));
+
+            utf8Buffer.Clear();
+            Assert.Equal(testData.Utf8Sequence.Length, rune.EncodeToUtf8(utf8Buffer));
+            Assert.True(utf8Buffer.Slice(0, testData.Utf8Sequence.Length).SequenceEqual(testData.Utf8Sequence));
         }
     }
 }
index 8063db2..8ac8f38 100644 (file)
@@ -279,8 +279,7 @@ namespace System.Text.Json
 
 #if BUILDING_INBOX_LIBRARY
                         var rune = new Rune(scalar);
-                        result = rune.TryEncodeToUtf8Bytes(destination.Slice(written), out int bytesWritten);
-                        Debug.Assert(result);
+                        int bytesWritten = rune.EncodeToUtf8(destination.Slice(written));
 #else
                         EncodeToUtf8Bytes((uint)scalar, destination.Slice(written), out int bytesWritten);
 #endif