diff --git a/src/libraries/Common/src/Polyfills/BigIntegerPolyfills.cs b/src/libraries/Common/src/Polyfills/BigIntegerPolyfills.cs
new file mode 100644
index 00000000000000..1f5fee7e88a281
--- /dev/null
+++ b/src/libraries/Common/src/Polyfills/BigIntegerPolyfills.cs
@@ -0,0 +1,49 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace System.Numerics;
+
+/// Provides downlevel polyfills for instance methods on .
+internal static class BigIntegerPolyfills
+{
+ extension(BigInteger self)
+ {
+ public byte[] ToByteArray(bool isUnsigned, bool isBigEndian)
+ {
+ if (isUnsigned && self.Sign < 0)
+ throw new OverflowException();
+
+ byte[] littleEndianBytes = self.ToByteArray();
+
+ if (!isUnsigned && !isBigEndian)
+ return littleEndianBytes;
+
+ int length = littleEndianBytes.Length;
+
+ // For unsigned, trim a single most-significant 0x00 sign-extension byte
+ // from the end of the little-endian array.
+ if (isUnsigned && length > 1 && littleEndianBytes[length - 1] == 0x00)
+ length--;
+
+ if (isBigEndian)
+ {
+ byte[] result = new byte[length];
+
+ for (int i = 0; i < length; i++)
+ {
+ result[i] = littleEndianBytes[length - 1 - i];
+ }
+
+ return result;
+ }
+
+ if (length == littleEndianBytes.Length)
+ return littleEndianBytes;
+
+ byte[] trimmed = new byte[length];
+ Array.Copy(littleEndianBytes, trimmed, length);
+
+ return trimmed;
+ }
+ }
+}
diff --git a/src/libraries/Common/src/Polyfills/BinaryPrimitivesPolyfills.cs b/src/libraries/Common/src/Polyfills/BinaryPrimitivesPolyfills.cs
new file mode 100644
index 00000000000000..502e9b28948539
--- /dev/null
+++ b/src/libraries/Common/src/Polyfills/BinaryPrimitivesPolyfills.cs
@@ -0,0 +1,80 @@
+// 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;
+using System.Runtime.InteropServices;
+
+namespace System.Buffers.Binary;
+
+/// Provides downlevel polyfills for static methods on .
+internal static class BinaryPrimitivesPolyfills
+{
+ extension(BinaryPrimitives)
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static ushort ReadHalfBigEndian(ReadOnlySpan source)
+ {
+ return BitConverter.IsLittleEndian
+ ? BinaryPrimitives.ReverseEndianness(MemoryMarshal.Read(source))
+ : MemoryMarshal.Read(source);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static void WriteHalfBigEndian(Span destination, ushort value)
+ {
+ if (BitConverter.IsLittleEndian)
+ {
+ ushort tmp = BinaryPrimitives.ReverseEndianness(value);
+ MemoryMarshal.Write(destination, ref tmp);
+ }
+ else
+ {
+ MemoryMarshal.Write(destination, ref value);
+ }
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static float ReadSingleBigEndian(ReadOnlySpan source)
+ {
+ return BitConverter.IsLittleEndian
+ ? BitConverter.Int32BitsToSingle(BinaryPrimitives.ReverseEndianness(MemoryMarshal.Read(source)))
+ : MemoryMarshal.Read(source);
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static void WriteSingleBigEndian(Span destination, float value)
+ {
+ if (BitConverter.IsLittleEndian)
+ {
+ int tmp = BinaryPrimitives.ReverseEndianness(BitConverter.SingleToInt32Bits(value));
+ MemoryMarshal.Write(destination, ref tmp);
+ }
+ 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)
+ {
+ long tmp = BinaryPrimitives.ReverseEndianness(BitConverter.DoubleToInt64Bits(value));
+ MemoryMarshal.Write(destination, ref tmp);
+ }
+ else
+ {
+ MemoryMarshal.Write(destination, ref value);
+ }
+ }
+ }
+}
diff --git a/src/libraries/Common/src/Polyfills/BitConverterPolyfills.cs b/src/libraries/Common/src/Polyfills/BitConverterPolyfills.cs
index dd418d32f94406..befcdcd49f5e75 100644
--- a/src/libraries/Common/src/Polyfills/BitConverterPolyfills.cs
+++ b/src/libraries/Common/src/Polyfills/BitConverterPolyfills.cs
@@ -8,20 +8,29 @@ internal static class BitConverterPolyfills
{
extension(BitConverter)
{
+ public static int SingleToInt32Bits(float value)
+ {
+ unsafe { return *(int*)&value; }
+ }
+
+ public static float Int32BitsToSingle(int value)
+ {
+ unsafe { return *(float*)&value; }
+ }
+
public static uint SingleToUInt32Bits(float value)
{
- unsafe
- {
- return *(uint*)&value;
- }
+ unsafe { return *(uint*)&value; }
+ }
+
+ public static float UInt32BitsToSingle(uint value)
+ {
+ unsafe { return *(float*)&value; }
}
public static ulong DoubleToUInt64Bits(double value)
{
- unsafe
- {
- return *(ulong*)&value;
- }
+ unsafe { return *(ulong*)&value; }
}
}
}
diff --git a/src/libraries/Common/src/Polyfills/DateTimeOffsetPolyfills.cs b/src/libraries/Common/src/Polyfills/DateTimeOffsetPolyfills.cs
index 1dcbae615775ad..600e89d4934d81 100644
--- a/src/libraries/Common/src/Polyfills/DateTimeOffsetPolyfills.cs
+++ b/src/libraries/Common/src/Polyfills/DateTimeOffsetPolyfills.cs
@@ -3,12 +3,19 @@
namespace System;
-/// Provides downlevel polyfills for instance members on .
+/// Provides downlevel polyfills for members on .
internal static class DateTimeOffsetPolyfills
{
+ private const long UnixEpochTicks = 719162L * 10000 * 1000 * 60 * 60 * 24;
+
extension(DateTimeOffset value)
{
public int TotalOffsetMinutes =>
(int)(value.Offset.Ticks / TimeSpan.TicksPerMinute);
}
+
+ extension(DateTimeOffset)
+ {
+ public static DateTimeOffset UnixEpoch => new DateTimeOffset(UnixEpochTicks, TimeSpan.Zero);
+ }
}
diff --git a/src/libraries/Common/src/Polyfills/DecimalPolyfills.cs b/src/libraries/Common/src/Polyfills/DecimalPolyfills.cs
new file mode 100644
index 00000000000000..2eef0ab0727297
--- /dev/null
+++ b/src/libraries/Common/src/Polyfills/DecimalPolyfills.cs
@@ -0,0 +1,16 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+namespace System;
+
+/// Provides downlevel polyfills for static methods on .
+internal static class DecimalPolyfills
+{
+ extension(decimal)
+ {
+ public static void GetBits(decimal d, Span destination)
+ {
+ decimal.GetBits(d).CopyTo(destination);
+ }
+ }
+}
diff --git a/src/libraries/Common/src/Polyfills/StackPolyfills.cs b/src/libraries/Common/src/Polyfills/StackPolyfills.cs
new file mode 100644
index 00000000000000..1f786d4d60cb14
--- /dev/null
+++ b/src/libraries/Common/src/Polyfills/StackPolyfills.cs
@@ -0,0 +1,25 @@
+// 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.CodeAnalysis;
+
+namespace System.Collections.Generic;
+
+/// Provides downlevel polyfills for instance methods on .
+internal static class StackPolyfills
+{
+ extension(Stack stack)
+ {
+ public bool TryPop([MaybeNullWhen(false)] out T result)
+ {
+ if (stack.Count > 0)
+ {
+ result = stack.Pop();
+ return true;
+ }
+
+ result = default;
+ return false;
+ }
+ }
+}
diff --git a/src/libraries/Common/src/System/StringPolyfills.cs b/src/libraries/Common/src/System/StringPolyfills.cs
index da679b268204f4..08b423087040ff 100644
--- a/src/libraries/Common/src/System/StringPolyfills.cs
+++ b/src/libraries/Common/src/System/StringPolyfills.cs
@@ -16,6 +16,19 @@ public static bool EndsWith(this string s, char value) =>
public static bool Contains(this string s, char value) =>
s.IndexOf(value) >= 0;
+
+ internal delegate void SpanAction(Span span, TArg arg);
+
+ extension(string)
+ {
+ public static string Create(int length, TState state, SpanAction action)
+ {
+ char[] arr = new char[length];
+ action(arr, state);
+
+ return new string(arr);
+ }
+ }
}
}
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 04dfc7a44cf491..6988d80473b6a0 100644
--- a/src/libraries/System.Formats.Cbor/src/System.Formats.Cbor.csproj
+++ b/src/libraries/System.Formats.Cbor/src/System.Formats.Cbor.csproj
@@ -38,20 +38,25 @@ System.Formats.Cbor.CborWriter
+
+
+
+
-
-
-
+
-
-
+
+
+
+
+
-
+
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/CborHelpers.netstandard.cs b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/CborHelpers.netstandard.cs
deleted file mode 100644
index adb2eb362c0308..00000000000000
--- a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/CborHelpers.netstandard.cs
+++ /dev/null
@@ -1,187 +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.Binary;
-using System.Collections.Generic;
-using System.Diagnostics;
-using System.Diagnostics.CodeAnalysis;
-using System.Numerics;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-namespace System.Formats.Cbor
-{
- internal static partial class CborHelpers
- {
- 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);
-
- public static BigInteger CreateBigIntegerFromUnsignedBigEndianBytes(byte[] bigEndianBytes)
- {
- if (bigEndianBytes.Length == 0)
- {
- return new BigInteger(bigEndianBytes);
- }
-
- byte[] temp;
- if ((bigEndianBytes[0] & 0x80) != 0) // Is negative?
- {
- // To prevent positive values from being misinterpreted as negative values,
- // you can add a zero-byte value to the most significant side of the array.
- // Right in this case as it is Big-endian.
- var bytesPlusOne = new byte[bigEndianBytes.Length + 1];
- bigEndianBytes.CopyTo(bytesPlusOne.AsSpan(1));
- temp = bytesPlusOne;
- }
- else
- {
- temp = bigEndianBytes;
- }
-
- // Reverse endianness
- temp.AsSpan().Reverse();
-
- return new BigInteger(temp);
- }
-
- public static byte[] CreateUnsignedBigEndianBytesFromBigInteger(BigInteger value)
- {
- byte[] littleEndianBytes = value.ToByteArray();
-
- if (littleEndianBytes.Length == 1)
- {
- return littleEndianBytes;
- }
-
- Span bytesAsSpan = littleEndianBytes;
- bytesAsSpan.Reverse();
-
- int start = 0;
- for (int i = 0; i < bytesAsSpan.Length; i++)
- {
- if (bytesAsSpan[i] == 0x00)
- {
- start++;
- }
- else
- {
- break;
- }
- }
-
- Debug.Assert(start <= 1); // If there is a case where we trim more than one byte, we want to add it to our tests.
-
- return start == 0 ? littleEndianBytes : bytesAsSpan.Slice(start).ToArray();
- }
-
- public static void GetBitsFromDecimal(decimal d, Span destination)
- {
- decimal.GetBits(d).CopyTo(destination);
- }
-
- public delegate void SpanAction(Span span, TArg arg);
-
- public static string BuildStringFromIndefiniteLengthTextString(int length, TState state, SpanAction action)
- {
- char[] arr = new char[length];
- action(arr, state);
- return new string(arr);
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static ushort ReadHalfBigEndian(ReadOnlySpan source)
- {
- ushort value = BitConverter.IsLittleEndian ?
- BinaryPrimitives.ReverseEndianness(MemoryMarshal.Read(source)) :
- MemoryMarshal.Read(source);
-
- return value;
- }
-
- [MethodImpl(MethodImplOptions.AggressiveInlining)]
- public static void WriteHalfBigEndian(Span destination, ushort value)
- {
- if (BitConverter.IsLittleEndian)
- {
- ushort tmp = BinaryPrimitives.ReverseEndianness(value);
- MemoryMarshal.Write(destination, ref tmp);
- }
- 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)
- {
- int tmp = BinaryPrimitives.ReverseEndianness(SingleToInt32Bits(value));
- MemoryMarshal.Write(destination, ref tmp);
- }
- 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)
- {
- long tmp = BinaryPrimitives.ReverseEndianness(BitConverter.DoubleToInt64Bits(value));
- MemoryMarshal.Write(destination, ref tmp);
- }
- else
- {
- MemoryMarshal.Write(destination, ref value);
- }
- }
-
- internal static uint SingleToUInt32Bits(float value)
- => (uint)SingleToInt32Bits(value);
-
- internal static unsafe int SingleToInt32Bits(float value)
- => *((int*)&value);
-
- internal static float UInt32BitsToSingle(uint value)
- => Int32BitsToSingle((int)value);
-
- internal static unsafe float Int32BitsToSingle(int value)
- => *((float*)&value);
- }
-
- internal static class StackExtensions
- {
- public static bool TryPop(this Stack stack, [MaybeNullWhen(false)] out T result)
- {
- if (stack.Count > 0)
- {
- result = stack.Pop();
- return true;
- }
-
- result = default;
- return false;
- }
- }
-}
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.cs
similarity index 91%
rename from src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/HalfHelpers.netstandard.cs
rename to src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/HalfHelpers.cs
index c4d191be9ad54c..618da7820f635a 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.cs
@@ -6,8 +6,15 @@
namespace System.Formats.Cbor
{
- internal static partial class HalfHelpers
+ internal static class HalfHelpers
{
+#if NET
+ public static float HalfToFloat(Half value)
+ => (float)value;
+
+ public static double HalfToDouble(Half value)
+ => (double)value;
+#else
// Half constants
private const ushort HalfExponentMask = 0x7C00;
private const ushort HalfExponentShift = 10;
@@ -53,7 +60,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 +69,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 +126,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 +135,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;
@@ -201,5 +208,6 @@ private static ushort RoundPackToHalf(bool sign, short exp, ushort sig)
private static uint ShiftRightJam(uint i, int dist)
=> dist < 31 ? (i >> dist) | (i << (-dist & 31) != 0 ? 1U : 0U) : (i != 0 ? 1U : 0U);
#endregion
+#endif
}
}
diff --git a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/HalfHelpers.netcoreapp.cs b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/HalfHelpers.netcoreapp.cs
deleted file mode 100644
index 96514354547b24..00000000000000
--- a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/HalfHelpers.netcoreapp.cs
+++ /dev/null
@@ -1,17 +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.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
-
-namespace System.Formats.Cbor
-{
- internal static partial class HalfHelpers
- {
- public static unsafe float HalfToFloat(Half value)
- => (float)value;
-
- public static unsafe double HalfToDouble(Half value)
- => (double)value;
- }
-}
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..9eaaafed5b4244 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
@@ -29,14 +29,14 @@ public float ReadSingle()
{
case CborAdditionalInfo.Additional16BitData:
EnsureReadCapacity(buffer, 1 + sizeof(ushort));
- result = HalfHelpers.HalfToFloat(CborHelpers.ReadHalfBigEndian(buffer.Slice(1)));
+ result = HalfHelpers.HalfToFloat(BinaryPrimitives.ReadHalfBigEndian(buffer.Slice(1)));
AdvanceBuffer(1 + sizeof(ushort));
AdvanceDataItemCounters();
return result;
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;
@@ -70,21 +70,21 @@ public double ReadDouble()
{
case CborAdditionalInfo.Additional16BitData:
EnsureReadCapacity(buffer, 1 + sizeof(short));
- result = HalfHelpers.HalfToDouble(CborHelpers.ReadHalfBigEndian(buffer.Slice(1)));
+ result = HalfHelpers.HalfToDouble(BinaryPrimitives.ReadHalfBigEndian(buffer.Slice(1)));
AdvanceBuffer(1 + sizeof(short));
AdvanceDataItemCounters();
return result;
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/Reader/CborReader.String.cs b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Reader/CborReader.String.cs
index 8ddb9986212974..64dfe490620423 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
@@ -387,7 +387,7 @@ private string ReadIndefiniteLengthTextStringConcatenated()
}
// build the string using range data
- string output = CborHelpers.BuildStringFromIndefiniteLengthTextString(concatenatedStringSize, (ranges, _data.Slice(_offset), utf8Encoding), BuildString);
+ string output = string.Create(concatenatedStringSize, (ranges, _data.Slice(_offset), utf8Encoding), BuildString);
AdvanceBuffer(encodingLength);
AdvanceDataItemCounters();
diff --git a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Reader/CborReader.Tag.cs b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Reader/CborReader.Tag.cs
index 2dd4c4d1d9abe1..5ea7e9950baac9 100644
--- a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Reader/CborReader.Tag.cs
+++ b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Reader/CborReader.Tag.cs
@@ -125,7 +125,7 @@ public DateTimeOffset ReadUnixTimeSeconds()
}
TimeSpan timespan = TimeSpan.FromSeconds(seconds);
- return CborHelpers.UnixEpoch + timespan;
+ return DateTimeOffset.UnixEpoch + timespan;
default:
throw new CborContentException(SR.Cbor_Reader_InvalidUnixTimeEncoding);
@@ -175,7 +175,7 @@ public BigInteger ReadBigInteger()
}
byte[] unsignedBigEndianEncoding = ReadByteString();
- BigInteger unsignedValue = CborHelpers.CreateBigIntegerFromUnsignedBigEndianBytes(unsignedBigEndianEncoding);
+ BigInteger unsignedValue = CreateBigIntegerFromUnsignedBigEndianBytes(unsignedBigEndianEncoding);
return isNegative ? -1 - unsignedValue : unsignedValue;
}
catch
@@ -291,5 +291,29 @@ private CborTag PeekTagCore(out int bytesRead)
return result;
}
+
+ private static BigInteger CreateBigIntegerFromUnsignedBigEndianBytes(byte[] bigEndianBytes)
+#if NET
+ => new BigInteger(bigEndianBytes, isUnsigned: true, isBigEndian: true);
+#else
+ {
+ if (bigEndianBytes.Length == 0)
+ return BigInteger.Zero;
+
+ byte[] littleEndianBytes = (byte[])bigEndianBytes.Clone();
+ Array.Reverse(littleEndianBytes);
+
+ // BigInteger(byte[]) expects little-endian signed (two's complement).
+ // If the high bit is set, append a 0x00 so BigInteger doesn't interpret it as negative.
+ if ((littleEndianBytes[littleEndianBytes.Length - 1] & 0x80) != 0)
+ {
+ byte[] extended = new byte[littleEndianBytes.Length + 1];
+ Array.Copy(littleEndianBytes, extended, littleEndianBytes.Length);
+ littleEndianBytes = extended;
+ }
+
+ return new BigInteger(littleEndianBytes);
+ }
+#endif
}
}
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..9ca15fc591d0df 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
@@ -27,7 +27,7 @@ private void WriteHalf(ushort value)
}
else
{
- CborHelpers.WriteHalfBigEndian(_buffer.AsSpan(_offset), value);
+ BinaryPrimitives.WriteHalfBigEndian(_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.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.Tag.cs b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.Tag.cs
index a3b4cd4470e6f1..594fcf66edf8c3 100644
--- a/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.Tag.cs
+++ b/src/libraries/System.Formats.Cbor/src/System/Formats/Cbor/Writer/CborWriter.Tag.cs
@@ -89,7 +89,7 @@ public void WriteBigInteger(BigInteger value)
{
bool isUnsigned = value.Sign >= 0;
BigInteger unsignedValue = isUnsigned ? value : -1 - value;
- byte[] unsignedBigEndianEncoding = CborHelpers.CreateUnsignedBigEndianBytesFromBigInteger(unsignedValue);
+ byte[] unsignedBigEndianEncoding = unsignedValue.ToByteArray(isUnsigned: true, isBigEndian: true);
WriteTag(isUnsigned ? CborTag.UnsignedBigNum : CborTag.NegativeBigNum);
WriteByteString(unsignedBigEndianEncoding);
@@ -143,8 +143,7 @@ internal static class DecimalHelpers
public static void Deconstruct(decimal value, out decimal mantissa, out byte scale)
{
Span buf = stackalloc int[4];
- CborHelpers.GetBitsFromDecimal(value, buf);
-
+ decimal.GetBits(value, buf);
int flags = buf[3];
bool isNegative = (flags & SignMask) == SignMask;
mantissa = new decimal(lo: buf[0], mid: buf[1], hi: buf[2], isNegative: isNegative, scale: 0);
@@ -155,8 +154,7 @@ public static void Deconstruct(decimal value, out decimal mantissa, out byte sca
private static decimal ReconstructFromNegativeScale(decimal mantissa, byte scale)
{
Span buf = stackalloc int[4];
- CborHelpers.GetBitsFromDecimal(mantissa, buf);
-
+ decimal.GetBits(mantissa, buf);
int flags = buf[3];
bool isNegative = (flags & SignMask) == SignMask;
Debug.Assert((flags & ScaleMask) == 0, "mantissa argument should be integral.");