diff --git a/src/libraries/Common/src/System/Security/Cryptography/PasswordBasedEncryption.cs b/src/libraries/Common/src/System/Security/Cryptography/PasswordBasedEncryption.cs index f5f62cf3f1db79..cb9db0df3ab661 100644 --- a/src/libraries/Common/src/System/Security/Cryptography/PasswordBasedEncryption.cs +++ b/src/libraries/Common/src/System/Security/Cryptography/PasswordBasedEncryption.cs @@ -7,6 +7,7 @@ using System.Runtime.InteropServices; using System.Security.Cryptography.Asn1; using System.Security.Cryptography.Pkcs; +using System.Text; using Internal.Cryptography; namespace System.Security.Cryptography diff --git a/src/libraries/Common/src/System/Text/EncodingPolyfills.cs b/src/libraries/Common/src/System/Text/EncodingPolyfills.cs new file mode 100644 index 00000000000000..9e2981db8f922d --- /dev/null +++ b/src/libraries/Common/src/System/Text/EncodingPolyfills.cs @@ -0,0 +1,82 @@ +// Licensed to the .NET Foundation under one or more agreements. +// The .NET Foundation licenses this file to you under the MIT license. + +using System.Diagnostics; +using System.Runtime.CompilerServices; +using System.Runtime.InteropServices; + +namespace System.Text +{ + /// Provides downlevel polyfills for span-based Encoding APIs. + internal static class EncodingPolyfills + { + public static unsafe int GetByteCount(this Encoding encoding, ReadOnlySpan chars) + { + fixed (char* charsPtr = &GetNonNullPinnableReference(chars)) + { + return encoding.GetByteCount(charsPtr, chars.Length); + } + } + + public static unsafe int GetCharCount(this Encoding encoding, ReadOnlySpan bytes) + { + fixed (byte* bytesPtr = &GetNonNullPinnableReference(bytes)) + { + return encoding.GetCharCount(bytesPtr, bytes.Length); + } + } + + public static int GetBytes(this Encoding encoding, string str, Span bytes) + { + return GetBytes(encoding, str.AsSpan(), bytes); + } + + public static unsafe int GetBytes(this Encoding encoding, ReadOnlySpan chars, Span bytes) + { + fixed (char* charsPtr = &GetNonNullPinnableReference(chars)) + fixed (byte* bytesPtr = &GetNonNullPinnableReference(bytes)) + { + return encoding.GetBytes(charsPtr, chars.Length, bytesPtr, bytes.Length); + } + } + + public static unsafe int GetChars(this Encoding encoding, ReadOnlySpan bytes, Span chars) + { + fixed (byte* bytesPtr = &GetNonNullPinnableReference(bytes)) + fixed (char* charsPtr = &GetNonNullPinnableReference(chars)) + { + return encoding.GetChars(bytesPtr, bytes.Length, charsPtr, chars.Length); + } + } + + public static unsafe string GetString(this Encoding encoding, ReadOnlySpan bytes) + { + fixed (byte* bytesPtr = &GetNonNullPinnableReference(bytes)) + { + return encoding.GetString(bytesPtr, bytes.Length); + } + } + + public static bool TryGetChars(this Encoding encoding, ReadOnlySpan bytes, Span chars, out int charsWritten) + { + int charCount = encoding.GetCharCount(bytes); + + if (charCount > chars.Length) + { + charsWritten = 0; + return false; + } + + charsWritten = encoding.GetChars(bytes, chars); + Debug.Assert(charCount == charsWritten); + return true; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + private static unsafe ref readonly T GetNonNullPinnableReference(ReadOnlySpan buffer) + { + // Based on the internal implementation from MemoryMarshal. + return ref buffer.Length != 0 ? ref MemoryMarshal.GetReference(buffer) : ref Unsafe.AsRef((void*)1); + } + } +} diff --git a/src/libraries/Directory.Build.targets b/src/libraries/Directory.Build.targets index 28202e01ed7aa7..1163572cec2902 100644 --- a/src/libraries/Directory.Build.targets +++ b/src/libraries/Directory.Build.targets @@ -194,6 +194,7 @@ + diff --git a/src/libraries/Microsoft.Bcl.Cryptography/src/System/Security/Cryptography/NetStandardShims.cs b/src/libraries/Microsoft.Bcl.Cryptography/src/System/Security/Cryptography/NetStandardShims.cs index b0ea8a95506c8d..344ff4878ca9eb 100644 --- a/src/libraries/Microsoft.Bcl.Cryptography/src/System/Security/Cryptography/NetStandardShims.cs +++ b/src/libraries/Microsoft.Bcl.Cryptography/src/System/Security/Cryptography/NetStandardShims.cs @@ -1,51 +1,18 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Diagnostics; +using System.IO; using System.Runtime.CompilerServices; -using System.Text; namespace System.Security.Cryptography { internal static class NetStandardShims { - internal static unsafe int GetByteCount(this Encoding encoding, ReadOnlySpan str) - { - if (str.IsEmpty) - { - return 0; - } - - fixed (char* pStr = str) - { - return encoding.GetByteCount(pStr, str.Length); - } - } - - internal static unsafe int GetBytes(this Encoding encoding, string str, Span destination) - { - return GetBytes(encoding, str.AsSpan(), destination); - } - - internal static unsafe int GetBytes(this Encoding encoding, ReadOnlySpan str, Span destination) - { - if (str.IsEmpty) - { - return 0; - } - - fixed (char* pStr = str) - fixed (byte* pDestination = destination) - { - return encoding.GetBytes(pStr, str.Length, pDestination, destination.Length); - } - } - - internal static void ReadExactly(this System.IO.Stream stream, Span buffer) => + internal static void ReadExactly(this Stream stream, Span buffer) => ReadAtLeast(stream, buffer, buffer.Length, throwOnEndOfStream: true); internal static int ReadAtLeast( - this System.IO.Stream stream, + this Stream stream, Span buffer, int minimumBytes, bool throwOnEndOfStream = true) diff --git a/src/libraries/Microsoft.Bcl.Cryptography/tests/Microsoft.Bcl.Cryptography.Tests.csproj b/src/libraries/Microsoft.Bcl.Cryptography/tests/Microsoft.Bcl.Cryptography.Tests.csproj index 5abb2246869ee1..5c4ce5f6439beb 100644 --- a/src/libraries/Microsoft.Bcl.Cryptography/tests/Microsoft.Bcl.Cryptography.Tests.csproj +++ b/src/libraries/Microsoft.Bcl.Cryptography/tests/Microsoft.Bcl.Cryptography.Tests.csproj @@ -7,6 +7,7 @@ $(NoWarn);SYSLIB5006 ../src/Resources/Strings.resx true + true diff --git a/src/libraries/System.Formats.Asn1/src/System.Formats.Asn1.csproj b/src/libraries/System.Formats.Asn1/src/System.Formats.Asn1.csproj index bfe129e148c396..f7a85ae076f779 100644 --- a/src/libraries/System.Formats.Asn1/src/System.Formats.Asn1.csproj +++ b/src/libraries/System.Formats.Asn1/src/System.Formats.Asn1.csproj @@ -6,6 +6,7 @@ $(DefineConstants);CP_NO_ZEROMEMORY true Provides classes that can read and write the ASN.1 BER, CER, and DER data formats. + true diff --git a/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnCharacterStringEncodings.cs b/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnCharacterStringEncodings.cs index f33e261f1fa1e4..5bbc3fef701b81 100644 --- a/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnCharacterStringEncodings.cs +++ b/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnCharacterStringEncodings.cs @@ -2,9 +2,7 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Buffers.Binary; -using System.Collections.Generic; using System.Diagnostics; -using System.Runtime.InteropServices; using System.Text; namespace System.Formats.Asn1 @@ -31,47 +29,6 @@ internal static Encoding GetEncoding(UniversalTagNumber encodingType) => UniversalTagNumber.T61String => s_t61Encoding, _ => throw new ArgumentOutOfRangeException(nameof(encodingType), encodingType, null), }; - - internal static int GetByteCount(this Encoding encoding, ReadOnlySpan str) - { - if (str.IsEmpty) - { - // Ensure a non-null pointer is obtained, even though the expected answer is 0. - str = string.Empty.AsSpan(); - } - - unsafe - { - fixed (char* strPtr = &MemoryMarshal.GetReference(str)) - { - return encoding.GetByteCount(strPtr, str.Length); - } - } - } - - internal static int GetBytes(this Encoding encoding, ReadOnlySpan chars, Span bytes) - { - if (chars.IsEmpty) - { - // Ensure a non-null pointer is obtained. - chars = string.Empty.AsSpan(); - } - - if (bytes.IsEmpty) - { - // Ensure a non-null pointer is obtained. - bytes = Array.Empty(); - } - - unsafe - { - fixed (char* charsPtr = &MemoryMarshal.GetReference(chars)) - fixed (byte* bytesPtr = &MemoryMarshal.GetReference(bytes)) - { - return encoding.GetBytes(charsPtr, chars.Length, bytesPtr, bytes.Length); - } - } - } } internal abstract class SpanBasedEncoding : Encoding diff --git a/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnDecoder.Text.cs b/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnDecoder.Text.cs index 6aebb2aed8bbc9..3804d62f3e0415 100644 --- a/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnDecoder.Text.cs +++ b/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnDecoder.Text.cs @@ -1,8 +1,6 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Diagnostics; -using System.Runtime.InteropServices; using System.Security.Cryptography; using System.Text; @@ -248,7 +246,7 @@ public static bool TryReadCharacterString( out int charsWritten, Asn1Tag? expectedTag = null) { - Text.Encoding encoding = AsnCharacterStringEncodings.GetEncoding(encodingType); + Encoding encoding = AsnCharacterStringEncodings.GetEncoding(encodingType); return TryReadCharacterStringCore( source, @@ -319,7 +317,7 @@ public static string ReadCharacterString( out int bytesConsumed, Asn1Tag? expectedTag = null) { - Text.Encoding encoding = AsnCharacterStringEncodings.GetEncoding(encodingType); + Encoding encoding = AsnCharacterStringEncodings.GetEncoding(encodingType); return ReadCharacterStringCore( source, @@ -384,53 +382,12 @@ private static bool TryReadCharacterStringBytesCore( return copied; } - private static unsafe bool TryReadCharacterStringCore( - ReadOnlySpan source, - Span destination, - Text.Encoding encoding, - out int charsWritten) - { - try - { -#if NET - return encoding.TryGetChars(source, destination, out charsWritten); -#else - if (source.Length == 0) - { - charsWritten = 0; - return true; - } - - fixed (byte* bytePtr = &MemoryMarshal.GetReference(source)) - fixed (char* charPtr = &MemoryMarshal.GetReference(destination)) - { - int charCount = encoding.GetCharCount(bytePtr, source.Length); - - if (charCount > destination.Length) - { - charsWritten = 0; - return false; - } - - charsWritten = encoding.GetChars(bytePtr, source.Length, charPtr, destination.Length); - Debug.Assert(charCount == charsWritten); - - return true; - } -#endif - } - catch (DecoderFallbackException e) - { - throw new AsnContentException(SR.ContentException_DefaultMessage, e); - } - } - private static string ReadCharacterStringCore( ReadOnlySpan source, AsnEncodingRules ruleSet, Asn1Tag expectedTag, UniversalTagNumber universalTagNumber, - Text.Encoding encoding, + Encoding encoding, out int bytesConsumed) { byte[]? rented = null; @@ -445,27 +402,13 @@ private static string ReadCharacterStringCore( ref rented); string str; - - if (contents.Length == 0) + try { - str = string.Empty; + str = encoding.GetString(contents); } - else + catch (DecoderFallbackException e) { - unsafe - { - fixed (byte* bytePtr = &MemoryMarshal.GetReference(contents)) - { - try - { - str = encoding.GetString(bytePtr, contents.Length); - } - catch (DecoderFallbackException e) - { - throw new AsnContentException(SR.ContentException_DefaultMessage, e); - } - } - } + throw new AsnContentException(SR.ContentException_DefaultMessage, e); } if (rented != null) @@ -482,7 +425,7 @@ private static bool TryReadCharacterStringCore( AsnEncodingRules ruleSet, Asn1Tag expectedTag, UniversalTagNumber universalTagNumber, - Text.Encoding encoding, + Encoding encoding, Span destination, out int bytesConsumed, out int charsWritten) @@ -498,11 +441,15 @@ private static bool TryReadCharacterStringCore( out int bytesRead, ref rented); - bool copied = TryReadCharacterStringCore( - contents, - destination, - encoding, - out charsWritten); + bool copied; + try + { + copied = encoding.TryGetChars(contents, destination, out charsWritten); + } + catch (DecoderFallbackException e) + { + throw new AsnContentException(SR.ContentException_DefaultMessage, e); + } if (rented != null) { diff --git a/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnWriter.Text.cs b/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnWriter.Text.cs index 950318d30c578d..10859074272f49 100644 --- a/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnWriter.Text.cs +++ b/src/libraries/System.Formats.Asn1/src/System/Formats/Asn1/AsnWriter.Text.cs @@ -2,8 +2,8 @@ // The .NET Foundation licenses this file to you under the MIT license. using System.Diagnostics; -using System.Runtime.InteropServices; using System.Security.Cryptography; +using System.Text; namespace System.Formats.Asn1 { @@ -73,12 +73,12 @@ public void WriteCharacterString(UniversalTagNumber encodingType, ReadOnlySpan str) + private void WriteCharacterStringCore(Asn1Tag tag, Encoding encoding, ReadOnlySpan str) { int size = encoding.GetByteCount(str); @@ -110,7 +110,7 @@ private void WriteCharacterStringCore(Asn1Tag tag, Text.Encoding encoding, ReadO _offset += size; } - private void WriteConstructedCerCharacterString(Asn1Tag tag, Text.Encoding encoding, ReadOnlySpan str, int size) + private void WriteConstructedCerCharacterString(Asn1Tag tag, Encoding encoding, ReadOnlySpan str, int size) { Debug.Assert(size > AsnReader.MaxCERSegmentSize); diff --git a/src/libraries/System.Formats.Cbor/src/System.Formats.Cbor.csproj b/src/libraries/System.Formats.Cbor/src/System.Formats.Cbor.csproj index 2613efbb39603e..0a0b502728f9c4 100644 --- a/src/libraries/System.Formats.Cbor/src/System.Formats.Cbor.csproj +++ b/src/libraries/System.Formats.Cbor/src/System.Formats.Cbor.csproj @@ -9,6 +9,7 @@ Commonly Used Types: System.Formats.Cbor.CborReader System.Formats.Cbor.CborWriter + true diff --git a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/CborHelpers.netcoreapp.cs b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/CborHelpers.netcoreapp.cs index 3832e832569c95..95dc9bde882ba4 100644 --- a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/CborHelpers.netcoreapp.cs +++ b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/CborHelpers.netcoreapp.cs @@ -5,7 +5,6 @@ using System.Buffers.Binary; using System.Numerics; using System.Runtime.CompilerServices; -using System.Text; namespace System.Formats.Cbor { @@ -13,21 +12,6 @@ internal static partial class CborHelpers { public static readonly DateTimeOffset UnixEpoch = DateTimeOffset.UnixEpoch; - public static int GetBytes(Encoding encoding, ReadOnlySpan source, Span destination) - => encoding.GetBytes(source, destination); - - public static int GetByteCount(Encoding encoding, ReadOnlySpan chars) - => encoding.GetByteCount(chars); - - public static int GetChars(Encoding encoding, ReadOnlySpan source, Span destination) - => encoding.GetChars(source, destination); - - public static int GetCharCount(Encoding encoding, ReadOnlySpan source) - => encoding.GetCharCount(source); - - public static string GetString(Encoding encoding, ReadOnlySpan bytes) - => encoding.GetString(bytes); - public static BigInteger CreateBigIntegerFromUnsignedBigEndianBytes(byte[] bytes) => new BigInteger(bytes, isUnsigned: true, isBigEndian: true); diff --git a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/CborHelpers.netstandard.cs b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/CborHelpers.netstandard.cs index c2354ab697ac50..adb2eb362c0308 100644 --- a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/CborHelpers.netstandard.cs +++ b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/CborHelpers.netstandard.cs @@ -8,7 +8,6 @@ using System.Numerics; using System.Runtime.CompilerServices; using System.Runtime.InteropServices; -using System.Text; namespace System.Formats.Cbor { @@ -18,73 +17,6 @@ internal static partial class CborHelpers public static readonly DateTimeOffset UnixEpoch = new DateTimeOffset(UnixEpochTicks, TimeSpan.Zero); - public static unsafe int GetBytes(Encoding encoding, ReadOnlySpan source, Span destination) - { - if (source.IsEmpty || destination.IsEmpty) - { - return 0; - } - - fixed (char* charPtr = source) - fixed (byte* bytePtr = destination) - { - return encoding.GetBytes(charPtr, source.Length, bytePtr, destination.Length); - } - } - - public static unsafe int GetByteCount(Encoding encoding, ReadOnlySpan chars) - { - if (chars.IsEmpty) - { - return 0; - } - - fixed (char* charPtr = chars) - { - return encoding.GetByteCount(charPtr, chars.Length); - } - } - - public static unsafe int GetChars(Encoding encoding, ReadOnlySpan source, Span destination) - { - if (source.IsEmpty || destination.IsEmpty) - { - return 0; - } - - fixed (byte* bytePtr = source) - fixed (char* charPtr = destination) - { - return encoding.GetChars(bytePtr, source.Length, charPtr, destination.Length); - } - } - - public static unsafe int GetCharCount(Encoding encoding, ReadOnlySpan source) - { - if (source.IsEmpty) - { - return 0; - } - - fixed (byte* bytePtr = source) - { - return encoding.GetCharCount(bytePtr, source.Length); - } - } - - public static unsafe string GetString(Encoding encoding, ReadOnlySpan bytes) - { - if (bytes.IsEmpty) - { - return string.Empty; - } - - fixed (byte* bytePtr = bytes) - { - return encoding.GetString(bytePtr, bytes.Length); - } - } - public static BigInteger CreateBigIntegerFromUnsignedBigEndianBytes(byte[] bigEndianBytes) { if (bigEndianBytes.Length == 0) diff --git a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Reader/CborReader.String.cs b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Reader/CborReader.String.cs index 284619e83d3d0d..8ddb9986212974 100644 --- a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Reader/CborReader.String.cs +++ b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Reader/CborReader.String.cs @@ -192,7 +192,7 @@ public string ReadTextString() string result; try { - result = CborHelpers.GetString(utf8Encoding, encodedString); + result = utf8Encoding.GetString(encodedString); } catch (DecoderFallbackException e) { @@ -244,7 +244,7 @@ public bool TryReadTextString(Span destination, out int charsWritten) return false; } - CborHelpers.GetChars(utf8Encoding, encodedSlice, destination); + utf8Encoding.GetChars(encodedSlice, destination); AdvanceBuffer(bytesRead + byteLength); AdvanceDataItemCounters(); charsWritten = charLength; @@ -400,7 +400,7 @@ static void BuildString(Span target, (List<(int Offset, int Length)> range foreach ((int o, int l) in input.ranges) { - int charsWritten = CborHelpers.GetChars(input.utf8Encoding, source.Slice(o, l), target); + int charsWritten = input.utf8Encoding.GetChars(source.Slice(o, l), target); target = target.Slice(charsWritten); } @@ -429,7 +429,7 @@ private bool TryReadIndefiniteLengthTextStringConcatenated(Span destinatio foreach ((int o, int l) in ranges) { - CborHelpers.GetChars(utf8Encoding, buffer.Slice(o, l), destination); + utf8Encoding.GetChars(buffer.Slice(o, l), destination); destination = destination.Slice(l); } @@ -507,7 +507,7 @@ private static int ValidateUtf8AndGetCharCount(ReadOnlySpan buffer, Encodi { try { - return CborHelpers.GetCharCount(utf8Encoding, buffer); + return utf8Encoding.GetCharCount(buffer); } catch (DecoderFallbackException e) { diff --git a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.String.cs b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.String.cs index 880b6e1706090b..bed62b0d2dc874 100644 --- a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.String.cs +++ b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.String.cs @@ -125,7 +125,7 @@ public void WriteTextString(ReadOnlySpan value) int length; try { - length = CborHelpers.GetByteCount(utf8Encoding, value); + length = utf8Encoding.GetByteCount(value); } catch (EncoderFallbackException e) { @@ -144,7 +144,7 @@ public void WriteTextString(ReadOnlySpan value) _currentIndefiniteLengthStringRanges.Add((_offset, value.Length)); } - CborHelpers.GetBytes(utf8Encoding, value, _buffer.AsSpan(_offset, length)); + utf8Encoding.GetBytes(value, _buffer.AsSpan(_offset, length)); _offset += length; AdvanceDataItemCounters(); } diff --git a/src/libraries/System.Memory.Data/src/System.Memory.Data.csproj b/src/libraries/System.Memory.Data/src/System.Memory.Data.csproj index e221d3ef351dfc..0934137422a017 100644 --- a/src/libraries/System.Memory.Data/src/System.Memory.Data.csproj +++ b/src/libraries/System.Memory.Data/src/System.Memory.Data.csproj @@ -9,6 +9,7 @@ Commonly Used Types: System.BinaryData + true diff --git a/src/libraries/System.Memory.Data/src/System/BinaryData.cs b/src/libraries/System.Memory.Data/src/System/BinaryData.cs index b1fe9b2b0a8880..02caf7c47a703f 100644 --- a/src/libraries/System.Memory.Data/src/System/BinaryData.cs +++ b/src/libraries/System.Memory.Data/src/System/BinaryData.cs @@ -416,20 +416,7 @@ public BinaryData WithMediaType(string? mediaType) /// A string from the value of this instance, using UTF-8 to decode the bytes. /// /// - public override unsafe string ToString() - { - ReadOnlySpan span = _bytes.Span; - - if (span.IsEmpty) - { - return string.Empty; - } - - fixed (byte* ptr = span) - { - return Encoding.UTF8.GetString(ptr, span.Length); - } - } + public override string ToString() => Encoding.UTF8.GetString(_bytes.Span); /// /// Converts the to a read-only stream. diff --git a/src/libraries/System.Net.ServerSentEvents/src/System.Net.ServerSentEvents.csproj b/src/libraries/System.Net.ServerSentEvents/src/System.Net.ServerSentEvents.csproj index 2db346e77547d3..06853d559595f5 100644 --- a/src/libraries/System.Net.ServerSentEvents/src/System.Net.ServerSentEvents.csproj +++ b/src/libraries/System.Net.ServerSentEvents/src/System.Net.ServerSentEvents.csproj @@ -8,6 +8,7 @@ Commonly Used Types: System.Net.ServerSentEvents.SseParser + true diff --git a/src/libraries/System.Net.ServerSentEvents/src/System/Net/ServerSentEvents/Helpers.cs b/src/libraries/System.Net.ServerSentEvents/src/System/Net/ServerSentEvents/Helpers.cs index fe9fa17489bb6e..12847048f4192b 100644 --- a/src/libraries/System.Net.ServerSentEvents/src/System/Net/ServerSentEvents/Helpers.cs +++ b/src/libraries/System.Net.ServerSentEvents/src/System/Net/ServerSentEvents/Helpers.cs @@ -47,20 +47,9 @@ public static void WriteUtf8String(this IBufferWriter writer, ReadOnlySpan int maxByteCount = Encoding.UTF8.GetMaxByteCount(value.Length); Span buffer = writer.GetSpan(maxByteCount); - Debug.Assert(maxByteCount <= buffer.Length); - int bytesWritten; -#if NET - bytesWritten = Encoding.UTF8.GetBytes(value, buffer); -#else - unsafe - { - fixed (char* chars = value) - fixed (byte* bytes = buffer) - { - bytesWritten = Encoding.UTF8.GetBytes(chars, value.Length, bytes, maxByteCount); - } - } -#endif + Debug.Assert(buffer.Length >= maxByteCount); + + int bytesWritten = Encoding.UTF8.GetBytes(value, buffer); writer.Advance(bytesWritten); } diff --git a/src/libraries/System.Net.ServerSentEvents/src/System/Net/ServerSentEvents/SseParser.cs b/src/libraries/System.Net.ServerSentEvents/src/System/Net/ServerSentEvents/SseParser.cs index 9ca4ecf1cce0e6..1ea0378296c4c9 100644 --- a/src/libraries/System.Net.ServerSentEvents/src/System/Net/ServerSentEvents/SseParser.cs +++ b/src/libraries/System.Net.ServerSentEvents/src/System/Net/ServerSentEvents/SseParser.cs @@ -1,10 +1,8 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. -using System.Collections.Generic; using System.IO; using System.Text; -using System.Threading; namespace System.Net.ServerSentEvents { @@ -26,7 +24,7 @@ public static class SseParser /// that decodes the data of each event using 's GetString method. /// public static SseParser Create(Stream sseStream) => - Create(sseStream, static (_, bytes) => Utf8GetString(bytes)); + Create(sseStream, static (_, bytes) => Encoding.UTF8.GetString(bytes)); /// Creates a parser for parsing a of server-sent events into a sequence of values. /// Specifies the type of data in each event. @@ -48,23 +46,5 @@ public static SseParser Create(Stream sseStream, SseItemParser itemPars return new SseParser(sseStream, itemParser); } - - /// Encoding.UTF8.GetString(bytes) - internal static string Utf8GetString(ReadOnlySpan bytes) - { -#if NET - return Encoding.UTF8.GetString(bytes); -#else - unsafe - { - fixed (byte* ptr = bytes) - { - return ptr is null ? - string.Empty : - Encoding.UTF8.GetString(ptr, bytes.Length); - } - } -#endif - } } } diff --git a/src/libraries/System.Net.ServerSentEvents/src/System/Net/ServerSentEvents/SseParser_1.cs b/src/libraries/System.Net.ServerSentEvents/src/System/Net/ServerSentEvents/SseParser_1.cs index dbf4bd1579c03b..2a3fccc0bf191e 100644 --- a/src/libraries/System.Net.ServerSentEvents/src/System/Net/ServerSentEvents/SseParser_1.cs +++ b/src/libraries/System.Net.ServerSentEvents/src/System/Net/ServerSentEvents/SseParser_1.cs @@ -9,6 +9,7 @@ using System.Globalization; using System.IO; using System.Runtime.CompilerServices; +using System.Text; using System.Threading; using System.Threading.Tasks; @@ -405,7 +406,7 @@ private bool ProcessLine(out SseItem sseItem, out int advance) else if (fieldName.SequenceEqual("event"u8)) { // Spec: "Set the event type buffer to field value." - _eventType = SseParser.Utf8GetString(fieldValue); + _eventType = Encoding.UTF8.GetString(fieldValue); } else if (fieldName.SequenceEqual("id"u8)) { @@ -413,7 +414,7 @@ private bool ProcessLine(out SseItem sseItem, out int advance) if (fieldValue.IndexOf((byte)'\0') < 0) { // Note that fieldValue might be empty, in which case LastEventId will naturally be reset to the empty string. This is per spec. - LastEventId = _eventId = SseParser.Utf8GetString(fieldValue); + LastEventId = _eventId = Encoding.UTF8.GetString(fieldValue); } } else if (fieldName.SequenceEqual("retry"u8)) @@ -424,7 +425,7 @@ private bool ProcessLine(out SseItem sseItem, out int advance) #if NET fieldValue, #else - SseParser.Utf8GetString(fieldValue), + Encoding.UTF8.GetString(fieldValue), #endif NumberStyles.None, CultureInfo.InvariantCulture, out long milliseconds) && 0 <= milliseconds && milliseconds <= TimeSpan_MaxValueMilliseconds) diff --git a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/Helpers.cs b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/Helpers.cs index 0d3f648ad812c2..cfcfd4625667d3 100644 --- a/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/Helpers.cs +++ b/src/libraries/System.Reflection.MetadataLoadContext/src/System/Reflection/TypeLoading/General/Helpers.cs @@ -358,22 +358,7 @@ public static RoAssemblyName ToRoAssemblyName(this AssemblyName assemblyName) public static byte[] ToUtf8(this string s) => Encoding.UTF8.GetBytes(s); -#if NET public static string ToUtf16(this ReadOnlySpan utf8) => Encoding.UTF8.GetString(utf8); -#else - public static unsafe string ToUtf16(this ReadOnlySpan utf8) - { - if (utf8.IsEmpty) - { - return string.Empty; - } - - fixed (byte* ptr = utf8) - { - return Encoding.UTF8.GetString(ptr, utf8.Length); - } - } -#endif // Guards ToString() implementations. Sample usage: // diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.cs b/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.cs index 7b836147cc58cc..378aa773613701 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/JsonHelpers.cs @@ -190,31 +190,6 @@ public static bool TrySkipPartial(this ref Utf8JsonReader reader) return reader.TrySkipPartial(reader.CurrentDepth); } - /// - /// Calls Encoding.UTF8.GetString that supports netstandard. - /// - /// The utf8 bytes to convert. - /// - public static string Utf8GetString(ReadOnlySpan bytes) - { -#if NET - return Encoding.UTF8.GetString(bytes); -#else - if (bytes.Length == 0) - { - return string.Empty; - } - - unsafe - { - fixed (byte* bytesPtr = bytes) - { - return Encoding.UTF8.GetString(bytesPtr, bytes.Length); - } - } -#endif - } - public static bool TryLookupUtf8Key( this Dictionary dictionary, ReadOnlySpan utf8Key, @@ -245,7 +220,7 @@ public static bool TryLookupUtf8Key( return success; #else - string key = Utf8GetString(utf8Key); + string key = Encoding.UTF8.GetString(utf8Key); return dictionary.TryGetValue(key, out result); #endif } diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonNode.To.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonNode.To.cs index 97215bae51c85c..374c41fde42fb0 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonNode.To.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Nodes/JsonNode.To.cs @@ -25,7 +25,7 @@ public string ToJsonString(JsonSerializerOptions? options = null) { WriteTo(writer, options); writer.Flush(); - return JsonHelpers.Utf8GetString(output.WrittenSpan); + return Encoding.UTF8.GetString(output.WrittenSpan); } finally { @@ -58,7 +58,7 @@ public override string ToString() { WriteTo(writer); writer.Flush(); - return JsonHelpers.Utf8GetString(output.WrittenSpan); + return Encoding.UTF8.GetString(output.WrittenSpan); } finally { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Reader/JsonReaderHelper.Unescaping.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Reader/JsonReaderHelper.Unescaping.cs index 7c3221921dcc51..41b3830608d5d3 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Reader/JsonReaderHelper.Unescaping.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Reader/JsonReaderHelper.Unescaping.cs @@ -254,21 +254,7 @@ public static string TranscodeHelper(ReadOnlySpan utf8Unescaped) { try { -#if NET return s_utf8Encoding.GetString(utf8Unescaped); -#else - if (utf8Unescaped.IsEmpty) - { - return string.Empty; - } - unsafe - { - fixed (byte* bytePtr = utf8Unescaped) - { - return s_utf8Encoding.GetString(bytePtr, utf8Unescaped.Length); - } - } -#endif } catch (DecoderFallbackException ex) { @@ -285,22 +271,7 @@ public static int TranscodeHelper(ReadOnlySpan utf8Unescaped, Span d { try { -#if NET return s_utf8Encoding.GetChars(utf8Unescaped, destination); -#else - if (utf8Unescaped.IsEmpty) - { - return 0; - } - unsafe - { - fixed (byte* srcPtr = utf8Unescaped) - fixed (char* destPtr = destination) - { - return s_utf8Encoding.GetChars(srcPtr, utf8Unescaped.Length, destPtr, destination.Length); - } - } -#endif } catch (DecoderFallbackException dfe) { @@ -329,18 +300,7 @@ public static void ValidateUtf8(ReadOnlySpan utf8Buffer) #else try { - if (utf8Buffer.IsEmpty) - { - return; - } - - unsafe - { - fixed (byte* srcPtr = utf8Buffer) - { - s_utf8Encoding.GetCharCount(srcPtr, utf8Buffer.Length); - } - } + _ = s_utf8Encoding.GetCharCount(utf8Buffer); } catch (DecoderFallbackException ex) { @@ -358,21 +318,7 @@ internal static int GetUtf8ByteCount(ReadOnlySpan text) { try { -#if NET return s_utf8Encoding.GetByteCount(text); -#else - if (text.IsEmpty) - { - return 0; - } - unsafe - { - fixed (char* charPtr = text) - { - return s_utf8Encoding.GetByteCount(charPtr, text.Length); - } - } -#endif } catch (EncoderFallbackException ex) { @@ -389,23 +335,7 @@ internal static int GetUtf8FromText(ReadOnlySpan text, Span dest) { try { -#if NET return s_utf8Encoding.GetBytes(text, dest); -#else - if (text.IsEmpty) - { - return 0; - } - - unsafe - { - fixed (char* charPtr = text) - fixed (byte* destPtr = dest) - { - return s_utf8Encoding.GetBytes(charPtr, text.Length, destPtr, dest.Length); - } - } -#endif } catch (EncoderFallbackException ex) { @@ -420,22 +350,7 @@ internal static int GetUtf8FromText(ReadOnlySpan text, Span dest) internal static string GetTextFromUtf8(ReadOnlySpan utf8Text) { -#if NET return s_utf8Encoding.GetString(utf8Text); -#else - if (utf8Text.IsEmpty) - { - return string.Empty; - } - - unsafe - { - fixed (byte* bytePtr = utf8Text) - { - return s_utf8Encoding.GetString(bytePtr, utf8Text.Length); - } - } -#endif } internal static void Unescape(ReadOnlySpan source, Span destination, out int written) diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandlePropertyName.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandlePropertyName.cs index 64a9de11e893a7..9903355472e607 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandlePropertyName.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/JsonSerializer.Read.HandlePropertyName.cs @@ -44,14 +44,14 @@ internal static JsonPropertyInfo LookupProperty( if (jsonTypeInfo.EffectiveUnmappedMemberHandling is JsonUnmappedMemberHandling.Disallow) { Debug.Assert(jsonTypeInfo.ExtensionDataProperty is null, "jsonTypeInfo.Configure() should have caught conflicting configuration."); - string stringPropertyName = JsonHelpers.Utf8GetString(unescapedPropertyName); + string stringPropertyName = Encoding.UTF8.GetString(unescapedPropertyName); ThrowHelper.ThrowJsonException_UnmappedJsonProperty(jsonTypeInfo.Type, stringPropertyName); } // Determine if we should use the extension property. if (jsonTypeInfo.ExtensionDataProperty is JsonPropertyInfo { HasGetter: true, HasSetter: true } dataExtProperty) { - state.Current.JsonPropertyNameAsString = JsonHelpers.Utf8GetString(unescapedPropertyName); + state.Current.JsonPropertyNameAsString = Encoding.UTF8.GetString(unescapedPropertyName); if (createExtensionProperty) { diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadStack.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadStack.cs index 55cab6492d1d6f..8d9678f8df9f99 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadStack.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Serialization/ReadStack.cs @@ -361,7 +361,7 @@ static void AppendPropertyName(StringBuilder sb, string? propertyName) if (utf8PropertyName != null) { - propertyName = JsonHelpers.Utf8GetString(utf8PropertyName); + propertyName = Encoding.UTF8.GetString(utf8PropertyName); } return propertyName; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs b/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs index 3292e7602c94b1..b06afbe6a450ee 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.Serialization.cs @@ -344,7 +344,7 @@ public static void ThrowJsonException_DuplicatePropertyNotAllowed(string name) [DoesNotReturn] public static void ThrowJsonException_DuplicatePropertyNotAllowed(ReadOnlySpan nameBytes) { - string name = JsonHelpers.Utf8GetString(nameBytes); + string name = Encoding.UTF8.GetString(nameBytes); throw new JsonException(SR.Format(SR.DuplicatePropertiesNotAllowed_NameSpan, Truncate(name))); } @@ -781,7 +781,7 @@ public static void ThrowJsonException_MetadataDuplicateIdFound(string id) [DoesNotReturn] public static void ThrowJsonException_DuplicateMetadataProperty(ReadOnlySpan utf8PropertyName) { - ThrowJsonException(SR.Format(SR.DuplicateMetadataProperty, JsonHelpers.Utf8GetString(utf8PropertyName))); + ThrowJsonException(SR.Format(SR.DuplicateMetadataProperty, Encoding.UTF8.GetString(utf8PropertyName))); } [DoesNotReturn] diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.cs b/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.cs index e6a7790d2b757b..a5ddfa5b976e60 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/ThrowHelper.cs @@ -375,7 +375,7 @@ public static void ThrowJsonReaderException(ref Utf8JsonReader json, ExceptionRe [MethodImpl(MethodImplOptions.NoInlining)] public static JsonException GetJsonReaderException(ref Utf8JsonReader json, ExceptionResource resource, byte nextByte, ReadOnlySpan bytes) { - string message = GetResourceString(ref json, resource, nextByte, JsonHelpers.Utf8GetString(bytes)); + string message = GetResourceString(ref json, resource, nextByte, Encoding.UTF8.GetString(bytes)); long lineNumber = json.CurrentState._lineNumber; long bytePositionInLine = json.CurrentState._bytePositionInLine; diff --git a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/JsonWriterHelper.cs b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/JsonWriterHelper.cs index de8173c5d79b66..38ff45cde115ff 100644 --- a/src/libraries/System.Text.Json/src/System/Text/Json/Writer/JsonWriterHelper.cs +++ b/src/libraries/System.Text.Json/src/System/Text/Json/Writer/JsonWriterHelper.cs @@ -265,17 +265,7 @@ public static bool IsValidUtf8String(ReadOnlySpan bytes) #else try { - if (!bytes.IsEmpty) - { - unsafe - { - fixed (byte* ptr = bytes) - { - s_utf8Encoding.GetCharCount(ptr, bytes.Length); - } - } - } - + _ = s_utf8Encoding.GetCharCount(bytes); return true; } catch (DecoderFallbackException) @@ -296,18 +286,7 @@ internal static OperationStatus ToUtf8(ReadOnlySpan source, Span des written = 0; try { - if (!source.IsEmpty) - { - unsafe - { - fixed (char* charPtr = source) - fixed (byte* destPtr = destination) - { - written = s_utf8Encoding.GetBytes(charPtr, source.Length, destPtr, destination.Length); - } - } - } - + written = s_utf8Encoding.GetBytes(source, destination); return OperationStatus.Done; } catch (EncoderFallbackException)