diff --git a/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj b/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj
index 7f38ee4629f8ac..242a4c1f6a6f54 100644
--- a/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj
+++ b/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj
@@ -93,6 +93,7 @@ The System.Reflection.Metadata library is built-in as part of the shared framewo
+
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..f705ac97d924b9 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
@@ -5,7 +5,6 @@
using System.Diagnostics;
using System.Reflection.Internal;
using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
namespace System.Reflection
{
@@ -14,54 +13,29 @@ internal static class BlobUtilities
public static void WriteBytes(this byte[] buffer, int start, byte value, int byteCount)
{
Debug.Assert(buffer.Length > 0);
-
new Span(buffer, start, byteCount).Fill(value);
}
- public static void WriteDouble(this byte[] buffer, int start, double value)
- {
-#if NET
+ public static void WriteDouble(this byte[] buffer, int start, double value) =>
WriteUInt64(buffer, start, BitConverter.DoubleToUInt64Bits(value));
-#else
- unsafe
- {
- WriteUInt64(buffer, start, *(ulong*)&value);
- }
-#endif
- }
- public static void WriteSingle(this byte[] buffer, int start, float value)
- {
-#if NET
+ public static void WriteSingle(this byte[] buffer, int start, float value) =>
WriteUInt32(buffer, start, BitConverter.SingleToUInt32Bits(value));
-#else
- unsafe
- {
- WriteUInt32(buffer, start, *(uint*)&value);
- }
-#endif
- }
-
- public static void WriteByte(this byte[] buffer, int start, byte value)
- {
- // Perf: The compiler emits a check when pinning the buffer. It's thus not worth doing so.
- buffer[start] = 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);
@@ -72,7 +46,7 @@ public static void WriteDecimal(this byte[] buffer, int start, decimal value)
uint low, mid, high;
value.GetBits(out isNegative, out scale, out low, out mid, out high);
- WriteByte(buffer, start, (byte)(scale | (isNegative ? 0x80 : 0x00)));
+ buffer[start] = (byte)(scale | (isNegative ? 0x80 : 0x00));
WriteUInt32(buffer, start + 1, low);
WriteUInt32(buffer, start + 5, mid);
WriteUInt32(buffer, start + 9, high);
@@ -82,45 +56,9 @@ public static void WriteDecimal(this byte[] buffer, int start, decimal value)
public static void WriteGuid(this byte[] buffer, int start, Guid value)
{
-#if NET
bool written = value.TryWriteBytes(buffer.AsSpan(start));
// This function is not public, callers have to ensure that enough space is available.
Debug.Assert(written);
-#else
- unsafe
- {
- fixed (byte* dst = &buffer[start])
- {
- byte* src = (byte*)&value;
-
- uint a = *(uint*)(src + 0);
- unchecked
- {
- dst[0] = (byte)a;
- dst[1] = (byte)(a >> 8);
- dst[2] = (byte)(a >> 16);
- dst[3] = (byte)(a >> 24);
-
- ushort b = *(ushort*)(src + 4);
- dst[4] = (byte)b;
- dst[5] = (byte)(b >> 8);
-
- ushort c = *(ushort*)(src + 6);
- dst[6] = (byte)c;
- dst[7] = (byte)(c >> 8);
- }
-
- dst[8] = src[8];
- dst[9] = src[9];
- dst[10] = src[10];
- dst[11] = src[11];
- dst[12] = src[12];
- dst[13] = src[13];
- dst[14] = src[14];
- dst[15] = src[15];
- }
- }
-#endif
}
public static unsafe void WriteUTF8(this byte[] buffer, int start, char* charPtr, int charCount, int byteCount, bool allowUnpairedSurrogates)
diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/Polyfills.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/Polyfills.cs
new file mode 100644
index 00000000000000..8c91c9ff15f59e
--- /dev/null
+++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/Polyfills.cs
@@ -0,0 +1,55 @@
+// 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
+{
+ internal static class BitConverterPolyfills
+ {
+ extension(BitConverter)
+ {
+ public static uint SingleToUInt32Bits(float value)
+ {
+ unsafe
+ {
+ return *(uint*)&value;
+ }
+ }
+
+ public static ulong DoubleToUInt64Bits(double value)
+ {
+ unsafe
+ {
+ return *(ulong*)&value;
+ }
+ }
+ }
+ }
+
+ internal static class GuidPolyfills
+ {
+ extension(Guid self)
+ {
+ public bool TryWriteBytes(Span destination)
+ {
+ if (destination.Length < 16)
+ return false;
+
+ ref Guid selfRef = ref Unsafe.AsRef(in self);
+ if (BitConverter.IsLittleEndian)
+ {
+ MemoryMarshal.Write(destination, ref selfRef);
+ }
+ else
+ {
+ // slower path for BigEndian
+ self.ToByteArray().AsSpan().CopyTo(destination);
+ }
+
+ return true;
+ }
+ }
+ }
+}
diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/BlobBuilder.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/BlobBuilder.cs
index 97967bba080068..9228bc45f4567a 100644
--- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/BlobBuilder.cs
+++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/BlobBuilder.cs
@@ -822,7 +822,7 @@ public void WriteBoolean(bool value)
public void WriteByte(byte value)
{
int start = ReserveBytesPrimitive(sizeof(byte));
- _buffer.WriteByte(start, value);
+ _buffer[start] = value;
}
/// Builder is not writable, it has been linked with another one.