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 0a0b502728f9c4..cba3c974bf0abd 100644 --- a/src/libraries/System.Formats.Cbor/src/System.Formats.Cbor.csproj +++ b/src/libraries/System.Formats.Cbor/src/System.Formats.Cbor.csproj @@ -36,17 +36,16 @@ System.Formats.Cbor.CborWriter + - - 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.cs similarity index 55% rename from src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/CborHelpers.netstandard.cs rename to src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/CborHelpers.cs index adb2eb362c0308..bcfdd1e76526c7 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.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Buffers; using System.Buffers.Binary; using System.Collections.Generic; using System.Diagnostics; @@ -11,12 +12,20 @@ namespace System.Formats.Cbor { - internal static partial class CborHelpers + internal static class CborHelpers { +#if NET + public static readonly DateTimeOffset UnixEpoch = DateTimeOffset.UnixEpoch; +#else private const long UnixEpochTicks = 719162L /*Number of days from 1/1/0001 to 12/31/1969*/ * 10000 * 1000 * 60 * 60 * 24; /* Ticks per day.*/ public static readonly DateTimeOffset UnixEpoch = new DateTimeOffset(UnixEpochTicks, TimeSpan.Zero); +#endif +#if NET + public static BigInteger CreateBigIntegerFromUnsignedBigEndianBytes(byte[] bytes) + => new BigInteger(bytes, isUnsigned: true, isBigEndian: true); +#else public static BigInteger CreateBigIntegerFromUnsignedBigEndianBytes(byte[] bigEndianBytes) { if (bigEndianBytes.Length == 0) @@ -44,7 +53,12 @@ public static BigInteger CreateBigIntegerFromUnsignedBigEndianBytes(byte[] bigEn return new BigInteger(temp); } +#endif +#if NET + public static byte[] CreateUnsignedBigEndianBytesFromBigInteger(BigInteger value) + => value.ToByteArray(isUnsigned: true, isBigEndian: true); +#else public static byte[] CreateUnsignedBigEndianBytesFromBigInteger(BigInteger value) { byte[] littleEndianBytes = value.ToByteArray(); @@ -74,12 +88,22 @@ public static byte[] CreateUnsignedBigEndianBytesFromBigInteger(BigInteger value return start == 0 ? littleEndianBytes : bytesAsSpan.Slice(start).ToArray(); } +#endif +#if NET + public static void GetBitsFromDecimal(decimal d, Span destination) + => decimal.GetBits(d, destination); +#else public static void GetBitsFromDecimal(decimal d, Span destination) { decimal.GetBits(d).CopyTo(destination); } +#endif +#if NET + public static string BuildStringFromIndefiniteLengthTextString(int length, TState state, SpanAction action) + => string.Create(length, state, action); +#else public delegate void SpanAction(Span span, TArg arg); public static string BuildStringFromIndefiniteLengthTextString(int length, TState state, SpanAction action) @@ -88,87 +112,71 @@ public static string BuildStringFromIndefiniteLengthTextString(int lengt action(arr, state); return new string(arr); } +#endif +#if NET + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static Half ReadHalfBigEndian(ReadOnlySpan source) + => BinaryPrimitives.ReadHalfBigEndian(source); +#else [MethodImpl(MethodImplOptions.AggressiveInlining)] public static ushort ReadHalfBigEndian(ReadOnlySpan source) { - ushort value = BitConverter.IsLittleEndian ? - BinaryPrimitives.ReverseEndianness(MemoryMarshal.Read(source)) : - MemoryMarshal.Read(source); - - return value; + return BinaryPrimitives.ReadUInt16BigEndian(source); } +#endif + } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void WriteHalfBigEndian(Span destination, ushort value) +#if !NET + internal static class BinaryPrimitivesPolyfills + { + extension(BinaryPrimitives) { - if (BitConverter.IsLittleEndian) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static double ReadDoubleBigEndian(ReadOnlySpan source) { - ushort tmp = BinaryPrimitives.ReverseEndianness(value); - MemoryMarshal.Write(destination, ref tmp); + return BitConverter.Int64BitsToDouble(BinaryPrimitives.ReadInt64BigEndian(source)); } - else - { - MemoryMarshal.Write(destination, ref value); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static float ReadSingleBigEndian(ReadOnlySpan source) - { - return BitConverter.IsLittleEndian ? - Int32BitsToSingle(BinaryPrimitives.ReverseEndianness(MemoryMarshal.Read(source))) : - MemoryMarshal.Read(source); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void WriteSingleBigEndian(Span destination, float value) - { - if (BitConverter.IsLittleEndian) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static void WriteDoubleBigEndian(Span destination, double value) { - int tmp = BinaryPrimitives.ReverseEndianness(SingleToInt32Bits(value)); - MemoryMarshal.Write(destination, ref tmp); + BinaryPrimitives.WriteInt64BigEndian(destination, BitConverter.DoubleToInt64Bits(value)); } - else - { - MemoryMarshal.Write(destination, ref value); - } - } - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double ReadDoubleBigEndian(ReadOnlySpan source) - { - return BitConverter.IsLittleEndian ? - BitConverter.Int64BitsToDouble(BinaryPrimitives.ReverseEndianness(MemoryMarshal.Read(source))) : - MemoryMarshal.Read(source); - } - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static void WriteDoubleBigEndian(Span destination, double value) - { - if (BitConverter.IsLittleEndian) + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe float ReadSingleBigEndian(ReadOnlySpan source) { - long tmp = BinaryPrimitives.ReverseEndianness(BitConverter.DoubleToInt64Bits(value)); - MemoryMarshal.Write(destination, ref tmp); + int intValue = BinaryPrimitives.ReadInt32BigEndian(source); + return *((float*)&intValue); } - else + + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe void WriteSingleBigEndian(Span destination, float value) { - MemoryMarshal.Write(destination, ref value); + BinaryPrimitives.WriteInt32BigEndian(destination, *((int*)&value)); } } + } - internal static uint SingleToUInt32Bits(float value) - => (uint)SingleToInt32Bits(value); + internal static class BitConverterPolyfills + { + extension(BitConverter) + { + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe int SingleToInt32Bits(float value) => *((int*)&value); - internal static unsafe int SingleToInt32Bits(float value) - => *((int*)&value); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static unsafe float Int32BitsToSingle(int value) => *((float*)&value); - internal static float UInt32BitsToSingle(uint value) - => Int32BitsToSingle((int)value); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static uint SingleToUInt32Bits(float value) => unchecked((uint)BitConverter.SingleToInt32Bits(value)); - internal static unsafe float Int32BitsToSingle(int value) - => *((float*)&value); + [MethodImpl(MethodImplOptions.AggressiveInlining)] + public static float UInt32BitsToSingle(uint value) => BitConverter.Int32BitsToSingle((int)value); + } } +#endif internal static class StackExtensions { 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 deleted file mode 100644 index 95dc9bde882ba4..00000000000000 --- a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/CborHelpers.netcoreapp.cs +++ /dev/null @@ -1,47 +0,0 @@ -// Licensed to the .NET Foundation under one or more agreements. -// The .NET Foundation licenses this file to you under the MIT license. - -using System.Buffers; -using System.Buffers.Binary; -using System.Numerics; -using System.Runtime.CompilerServices; - -namespace System.Formats.Cbor -{ - internal static partial class CborHelpers - { - public static readonly DateTimeOffset UnixEpoch = DateTimeOffset.UnixEpoch; - - public static BigInteger CreateBigIntegerFromUnsignedBigEndianBytes(byte[] bytes) - => new BigInteger(bytes, isUnsigned: true, isBigEndian: true); - - public static byte[] CreateUnsignedBigEndianBytesFromBigInteger(BigInteger value) - => value.ToByteArray(isUnsigned: true, isBigEndian: true); - - public static void GetBitsFromDecimal(decimal d, Span destination) - => decimal.GetBits(d, destination); - - public static string BuildStringFromIndefiniteLengthTextString(int length, TState state, SpanAction action) - => string.Create(length, state, action); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static Half ReadHalfBigEndian(ReadOnlySpan source) - => BinaryPrimitives.ReadHalfBigEndian(source); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static unsafe float ReadSingleBigEndian(ReadOnlySpan source) - => BinaryPrimitives.ReadSingleBigEndian(source); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static double ReadDoubleBigEndian(ReadOnlySpan source) - => BinaryPrimitives.ReadDoubleBigEndian(source); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static unsafe void WriteSingleBigEndian(Span destination, float value) - => BinaryPrimitives.WriteSingleBigEndian(destination, value); - - [MethodImpl(MethodImplOptions.AggressiveInlining)] - public static unsafe void WriteDoubleBigEndian(Span destination, double value) - => BinaryPrimitives.WriteDoubleBigEndian(destination, value); - } -} diff --git a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/HalfHelpers.netstandard.cs b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/HalfHelpers.netstandard.cs index c4d191be9ad54c..890fa148e9fd79 100644 --- a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/HalfHelpers.netstandard.cs +++ b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/HalfHelpers.netstandard.cs @@ -1,4 +1,4 @@ -// Licensed to the .NET Foundation under one or more agreements. +// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Runtime.CompilerServices; @@ -53,7 +53,7 @@ public static float HalfToFloat(ushort value) { if (sig == 0) { - return CborHelpers.UInt32BitsToSingle(sign ? FloatSignMask : 0); // Positive / Negative zero + return BitConverter.UInt32BitsToSingle(sign ? FloatSignMask : 0); // Positive / Negative zero } (exp, sig) = NormSubnormalF16Sig(sig); exp -= 1; @@ -62,7 +62,7 @@ public static float HalfToFloat(ushort value) return CreateSingle(sign, (byte)(exp + 0x70), sig << 13); static float CreateSingle(bool sign, byte exp, uint sig) - => CborHelpers.Int32BitsToSingle((int)(((sign ? 1U : 0U) << FloatSignShift) + ((uint)exp << FloatExponentShift) + sig)); + => BitConverter.Int32BitsToSingle((int)(((sign ? 1U : 0U) << FloatSignShift) + ((uint)exp << FloatExponentShift) + sig)); } public static bool HalfIsNaN(ushort value) @@ -119,7 +119,7 @@ private static float CreateSingleNaN(bool sign, ulong significand) uint signInt = (sign ? 1U : 0U) << FloatSignShift; uint sigInt = (uint)(significand >> 41); - return CborHelpers.UInt32BitsToSingle(signInt | NaNBits | sigInt); + return BitConverter.UInt32BitsToSingle(signInt | NaNBits | sigInt); } #endregion @@ -128,7 +128,7 @@ public static ushort FloatToHalf(float value) { const int SingleMaxExponent = 0xFF; - uint floatInt = CborHelpers.SingleToUInt32Bits(value); + uint floatInt = BitConverter.SingleToUInt32Bits(value); bool sign = (floatInt & FloatSignMask) >> FloatSignShift != 0; int exp = (int)(floatInt & FloatExponentMask) >> FloatExponentShift; uint sig = floatInt & FloatSignificandMask; diff --git a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Reader/CborReader.Simple.cs b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Reader/CborReader.Simple.cs index 228ae0bb78d9d4..ec115bc980b555 100644 --- a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Reader/CborReader.Simple.cs +++ b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Reader/CborReader.Simple.cs @@ -36,7 +36,7 @@ public float ReadSingle() case CborAdditionalInfo.Additional32BitData: EnsureReadCapacity(buffer, 1 + sizeof(float)); - result = CborHelpers.ReadSingleBigEndian(buffer.Slice(1)); + result = BinaryPrimitives.ReadSingleBigEndian(buffer.Slice(1)); AdvanceBuffer(1 + sizeof(float)); AdvanceDataItemCounters(); return result; @@ -77,14 +77,14 @@ public double ReadDouble() case CborAdditionalInfo.Additional32BitData: EnsureReadCapacity(buffer, 1 + sizeof(float)); - result = CborHelpers.ReadSingleBigEndian(buffer.Slice(1)); + result = BinaryPrimitives.ReadSingleBigEndian(buffer.Slice(1)); AdvanceBuffer(1 + sizeof(float)); AdvanceDataItemCounters(); return result; case CborAdditionalInfo.Additional64BitData: EnsureReadCapacity(buffer, 1 + sizeof(double)); - result = CborHelpers.ReadDoubleBigEndian(buffer.Slice(1)); + result = BinaryPrimitives.ReadDoubleBigEndian(buffer.Slice(1)); AdvanceBuffer(1 + sizeof(double)); AdvanceDataItemCounters(); return result; diff --git a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.Simple.cs b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.Simple.cs index 1b7e8dd00074be..72345928dc2d0f 100644 --- a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.Simple.cs +++ b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.Simple.cs @@ -1,6 +1,7 @@ // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. +using System.Buffers.Binary; using System.Runtime.CompilerServices; namespace System.Formats.Cbor @@ -63,7 +64,7 @@ private void WriteSingleCore(float value) { EnsureWriteCapacity(1 + sizeof(float)); WriteInitialByte(new CborInitialByte(CborMajorType.Simple, CborAdditionalInfo.Additional32BitData)); - CborHelpers.WriteSingleBigEndian(_buffer.AsSpan(_offset), value); + BinaryPrimitives.WriteSingleBigEndian(_buffer.AsSpan(_offset), value); _offset += sizeof(float); AdvanceDataItemCounters(); } @@ -72,7 +73,7 @@ private void WriteDoubleCore(double value) { EnsureWriteCapacity(1 + sizeof(double)); WriteInitialByte(new CborInitialByte(CborMajorType.Simple, CborAdditionalInfo.Additional64BitData)); - CborHelpers.WriteDoubleBigEndian(_buffer.AsSpan(_offset), value); + BinaryPrimitives.WriteDoubleBigEndian(_buffer.AsSpan(_offset), value); _offset += sizeof(double); AdvanceDataItemCounters(); } diff --git a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.Simple.netstandard.cs b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.Simple.netstandard.cs index f257ce1f4b4e02..86ccde95d03984 100644 --- a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.Simple.netstandard.cs +++ b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.Simple.netstandard.cs @@ -1,4 +1,4 @@ -// Licensed to the .NET Foundation under one or more agreements. +// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. using System.Buffers.Binary; @@ -27,7 +27,7 @@ private void WriteHalf(ushort value) } else { - CborHelpers.WriteHalfBigEndian(_buffer.AsSpan(_offset), value); + BinaryPrimitives.WriteUInt16BigEndian(_buffer.AsSpan(_offset), value); } _offset += sizeof(ushort); AdvanceDataItemCounters(); @@ -37,7 +37,7 @@ private void WriteHalf(ushort value) internal static bool TryConvertSingleToHalf(float value, out ushort result) { result = HalfHelpers.FloatToHalf(value); - return float.IsNaN(value) || CborHelpers.SingleToInt32Bits(HalfHelpers.HalfToFloat(result)) == CborHelpers.SingleToInt32Bits(value); + return float.IsNaN(value) || BitConverter.SingleToInt32Bits(HalfHelpers.HalfToFloat(result)) == BitConverter.SingleToInt32Bits(value); } } } diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/BlobUtilities.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/BlobUtilities.cs index 56d5dacd85d352..212c42c17ef952 100644 --- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/BlobUtilities.cs +++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/BlobUtilities.cs @@ -21,19 +21,16 @@ public static void WriteBytes(this byte[] buffer, int start, byte value, int byt public static void WriteDouble(this byte[] buffer, int start, double value) { #if NET - WriteUInt64(buffer, start, BitConverter.DoubleToUInt64Bits(value)); + BinaryPrimitives.WriteDoubleLittleEndian(buffer.AsSpan(start), value); #else - unsafe - { - WriteUInt64(buffer, start, *(ulong*)&value); - } + WriteUInt64(buffer, start, unchecked((ulong)BitConverter.DoubleToInt64Bits(value))); #endif } public static void WriteSingle(this byte[] buffer, int start, float value) { #if NET - WriteUInt32(buffer, start, BitConverter.SingleToUInt32Bits(value)); + BinaryPrimitives.WriteSingleLittleEndian(buffer.AsSpan(start), value); #else unsafe { @@ -49,19 +46,19 @@ public static void WriteByte(this byte[] buffer, int start, byte value) } public static void WriteUInt16(this byte[] buffer, int start, ushort value) => - Unsafe.WriteUnaligned(ref buffer[start], !BitConverter.IsLittleEndian ? BinaryPrimitives.ReverseEndianness(value) : value); + BinaryPrimitives.WriteUInt16LittleEndian(buffer.AsSpan(start), value); public static void WriteUInt16BE(this byte[] buffer, int start, ushort value) => - Unsafe.WriteUnaligned(ref buffer[start], BitConverter.IsLittleEndian ? BinaryPrimitives.ReverseEndianness(value) : value); + BinaryPrimitives.WriteUInt16BigEndian(buffer.AsSpan(start), value); public static void WriteUInt32BE(this byte[] buffer, int start, uint value) => - Unsafe.WriteUnaligned(ref buffer[start], BitConverter.IsLittleEndian ? BinaryPrimitives.ReverseEndianness(value) : value); + BinaryPrimitives.WriteUInt32BigEndian(buffer.AsSpan(start), value); public static void WriteUInt32(this byte[] buffer, int start, uint value) => - Unsafe.WriteUnaligned(ref buffer[start], !BitConverter.IsLittleEndian ? BinaryPrimitives.ReverseEndianness(value) : value); + BinaryPrimitives.WriteUInt32LittleEndian(buffer.AsSpan(start), value); public static void WriteUInt64(this byte[] buffer, int start, ulong value) => - Unsafe.WriteUnaligned(ref buffer[start], !BitConverter.IsLittleEndian ? BinaryPrimitives.ReverseEndianness(value) : value); + BinaryPrimitives.WriteUInt64LittleEndian(buffer.AsSpan(start), value); public const int SizeOfSerializedDecimal = sizeof(byte) + 3 * sizeof(uint);