diff --git a/src/libraries/Common/src/Polyfills/StreamSpanPolyfills.cs b/src/libraries/Common/src/Polyfills/StreamSpanPolyfills.cs
new file mode 100644
index 00000000000000..b8a61e311c2222
--- /dev/null
+++ b/src/libraries/Common/src/Polyfills/StreamSpanPolyfills.cs
@@ -0,0 +1,38 @@
+// 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;
+
+namespace System.IO;
+
+/// Provides downlevel polyfills for Span-based instance methods on .
+internal static class StreamSpanPolyfills
+{
+ extension(Stream stream)
+ {
+ public int ReadAtLeast(Span destination, int minimumBytes, bool throwOnEndOfStream = true)
+ {
+ byte[] buffer = ArrayPool.Shared.Rent(Math.Min(destination.Length, 81920));
+ int totalWritten = 0;
+ while (totalWritten < minimumBytes && !destination.IsEmpty)
+ {
+ int written = stream.Read(buffer, 0, Math.Min(buffer.Length, destination.Length));
+ if (written == 0)
+ {
+ if (throwOnEndOfStream)
+ {
+ ThrowEndOfStreamException();
+ }
+ break;
+ }
+ buffer.AsSpan(0, written).CopyTo(destination);
+ totalWritten += written;
+ destination = destination.Slice(written);
+ }
+ ArrayPool.Shared.Return(buffer);
+ return totalWritten;
+
+ static void ThrowEndOfStreamException() => throw new EndOfStreamException();
+ }
+ }
+}
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 02c844b70e43e9..c7b84cfc9ee3e3 100644
--- a/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj
+++ b/src/libraries/System.Reflection.Metadata/src/System.Reflection.Metadata.csproj
@@ -1,4 +1,4 @@
-
+
$(NetCoreAppCurrent);$(NetCoreAppPrevious);$(NetCoreAppMinimum);netstandard2.0;$(NetFrameworkMinimum)
@@ -27,6 +27,9 @@ The System.Reflection.Metadata library is built-in as part of the shared framewo
+
@@ -111,8 +114,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 f705ac97d924b9..be4c38b380e5b0 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
@@ -99,10 +99,10 @@ public static unsafe void WriteUTF8(this byte[] buffer, int start, char* charPtr
continue;
}
- if (IsSurrogateChar(c))
+ if (char.IsSurrogate(c))
{
// surrogate pair
- if (IsHighSurrogateChar(c) && charPtr < strEnd && IsLowSurrogateChar(*charPtr))
+ if (char.IsHighSurrogate(c) && charPtr < strEnd && char.IsLowSurrogate(*charPtr))
{
int highSurrogate = c;
int lowSurrogate = *charPtr++;
@@ -134,14 +134,6 @@ public static unsafe void WriteUTF8(this byte[] buffer, int start, char* charPtr
}
}
- internal static unsafe int GetUTF8ByteCount(string str)
- {
- fixed (char* ptr = str)
- {
- return GetUTF8ByteCount(ptr, str.Length);
- }
- }
-
internal static unsafe int GetUTF8ByteCount(char* str, int charCount)
{
return GetUTF8ByteCount(str, charCount, int.MaxValue, out _);
@@ -165,7 +157,7 @@ internal static unsafe int GetUTF8ByteCount(char* str, int charCount, int byteLi
{
characterSize = 2;
}
- else if (IsHighSurrogateChar(c) && ptr < end && IsLowSurrogateChar(*ptr))
+ else if (char.IsHighSurrogate(c) && ptr < end && char.IsLowSurrogate(*ptr))
{
// surrogate pair:
characterSize = 4;
@@ -189,21 +181,6 @@ internal static unsafe int GetUTF8ByteCount(char* str, int charCount, int byteLi
return byteCount;
}
- internal static bool IsSurrogateChar(int c)
- {
- return unchecked((uint)(c - 0xD800)) <= 0xDFFF - 0xD800;
- }
-
- internal static bool IsHighSurrogateChar(int c)
- {
- return unchecked((uint)(c - 0xD800)) <= 0xDBFF - 0xD800;
- }
-
- internal static bool IsLowSurrogateChar(int c)
- {
- return unchecked((uint)(c - 0xDC00)) <= 0xDFFF - 0xDC00;
- }
-
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static void ValidateRange(int bufferLength, int start, int byteCount, string byteCountParameterName)
{
diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/EncodingHelper.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/EncodingHelper.cs
index 5c74d8573696f0..94dbbd5bd9ae09 100644
--- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/EncodingHelper.cs
+++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/EncodingHelper.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.Diagnostics;
using System.Reflection.Metadata;
using System.Runtime.InteropServices;
@@ -13,15 +14,7 @@ namespace System.Reflection.Internal
///
internal static unsafe class EncodingHelper
{
- // Size of pooled buffers. The vast majority of metadata strings
- // are quite small so we don't need to waste memory with large buffers.
- public const int PooledBufferSize = 200;
-
- // Use AcquireBuffer(int) and ReleaseBuffer(byte[])
- // instead of the pool directly to implement the size check.
- private static readonly ObjectPool s_pool = new ObjectPool(() => new byte[PooledBufferSize]);
-
- public static string DecodeUtf8(byte* bytes, int byteCount, byte[] prefix, MetadataStringDecoder utf8Decoder)
+ public static string DecodeUtf8(byte* bytes, int byteCount, byte[]? prefix, MetadataStringDecoder utf8Decoder)
{
Debug.Assert(utf8Decoder != null);
@@ -49,7 +42,7 @@ private static string DecodeUtf8Prefixed(byte* bytes, int byteCount, byte[] pref
return string.Empty;
}
- byte[] buffer = AcquireBuffer(prefixedByteCount);
+ byte[] buffer = ArrayPool.Shared.Rent(prefixedByteCount);
prefix.CopyTo(buffer, 0);
Marshal.Copy((IntPtr)bytes, buffer, prefix.Length, byteCount);
@@ -60,26 +53,8 @@ private static string DecodeUtf8Prefixed(byte* bytes, int byteCount, byte[] pref
result = utf8Decoder.GetString(prefixedBytes, prefixedByteCount);
}
- ReleaseBuffer(buffer);
+ ArrayPool.Shared.Return(buffer);
return result;
}
-
- private static byte[] AcquireBuffer(int byteCount)
- {
- if (byteCount > PooledBufferSize)
- {
- return new byte[byteCount];
- }
-
- return s_pool.Allocate();
- }
-
- private static void ReleaseBuffer(byte[] buffer)
- {
- if (buffer.Length == PooledBufferSize)
- {
- s_pool.Free(buffer);
- }
- }
}
}
diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/EncodingHelper.netcoreapp.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/EncodingHelper.netcoreapp.cs
deleted file mode 100644
index 94dbbd5bd9ae09..00000000000000
--- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/EncodingHelper.netcoreapp.cs
+++ /dev/null
@@ -1,60 +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.Diagnostics;
-using System.Reflection.Metadata;
-using System.Runtime.InteropServices;
-
-namespace System.Reflection.Internal
-{
- ///
- /// Provides helpers to decode strings from unmanaged memory to System.String while avoiding
- /// intermediate allocation.
- ///
- internal static unsafe class EncodingHelper
- {
- public static string DecodeUtf8(byte* bytes, int byteCount, byte[]? prefix, MetadataStringDecoder utf8Decoder)
- {
- Debug.Assert(utf8Decoder != null);
-
- if (prefix != null)
- {
- return DecodeUtf8Prefixed(bytes, byteCount, prefix, utf8Decoder);
- }
-
- if (byteCount == 0)
- {
- return string.Empty;
- }
-
- return utf8Decoder.GetString(bytes, byteCount);
- }
-
- private static string DecodeUtf8Prefixed(byte* bytes, int byteCount, byte[] prefix, MetadataStringDecoder utf8Decoder)
- {
- Debug.Assert(utf8Decoder != null);
-
- int prefixedByteCount = byteCount + prefix.Length;
-
- if (prefixedByteCount == 0)
- {
- return string.Empty;
- }
-
- byte[] buffer = ArrayPool.Shared.Rent(prefixedByteCount);
-
- prefix.CopyTo(buffer, 0);
- Marshal.Copy((IntPtr)bytes, buffer, prefix.Length, byteCount);
-
- string result;
- fixed (byte* prefixedBytes = &buffer[0])
- {
- result = utf8Decoder.GetString(prefixedBytes, prefixedByteCount);
- }
-
- ArrayPool.Shared.Return(buffer);
- return result;
- }
- }
-}
diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/Hash.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/Hash.cs
index d083ff1307c3c3..26f51152cb28fc 100644
--- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/Hash.cs
+++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/Hash.cs
@@ -17,11 +17,6 @@ internal static int Combine(uint newKey, int currentKey)
return unchecked((currentKey * (int)0xA5555529) + (int)newKey);
}
- internal static int Combine(bool newKeyPart, int currentKey)
- {
- return Combine(currentKey, newKeyPart ? 1 : 0);
- }
-
///
/// The offset bias value used in the FNV-1a algorithm
/// See http://en.wikipedia.org/wiki/Fowler%E2%80%93Noll%E2%80%93Vo_hash_function
diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/StreamExtensions.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/StreamExtensions.cs
index b8495aa9fcc079..336278d0700189 100644
--- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/StreamExtensions.cs
+++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Internal/Utilities/StreamExtensions.cs
@@ -46,29 +46,6 @@ internal static int TryReadAll(this Stream stream, byte[] buffer, int offset, in
return totalBytesRead;
}
-#if NET
- internal static int TryReadAll(this Stream stream, Span buffer)
-#if NET
- => stream.ReadAtLeast(buffer, buffer.Length, throwOnEndOfStream: false);
-#else
- {
- int totalBytesRead = 0;
- while (totalBytesRead < buffer.Length)
- {
- int bytesRead = stream.Read(buffer.Slice(totalBytesRead));
- if (bytesRead == 0)
- {
- break;
- }
-
- totalBytesRead += bytesRead;
- }
-
- return totalBytesRead;
- }
-#endif
-#endif
-
///
/// Resolve image size as either the given user-specified size or distance from current position to end-of-stream.
/// Also performs the relevant argument validation and publicly visible caller has same argument names.
diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/BlobWriter.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/BlobWriter.cs
index 4be040305ad989..b143adf20a9604 100644
--- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/BlobWriter.cs
+++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/BlobWriter.cs
@@ -6,6 +6,7 @@
using System.IO;
using System.Reflection.Internal;
using System.Runtime.InteropServices;
+using System.Text;
namespace System.Reflection.Metadata
{
@@ -469,7 +470,7 @@ private unsafe void WriteUTF8(string str, int start, int length, bool allowUnpai
fixed (char* strPtr = str)
{
char* charPtr = strPtr + start;
- int byteCount = BlobUtilities.GetUTF8ByteCount(charPtr, length);
+ int byteCount = Encoding.UTF8.GetByteCount(charPtr, length);
if (prependSize)
{
diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/MetadataBuilder.Heaps.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/MetadataBuilder.Heaps.cs
index ec99c415fe8d3c..5bded8d832a13b 100644
--- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/MetadataBuilder.Heaps.cs
+++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/MetadataBuilder.Heaps.cs
@@ -5,6 +5,7 @@
using System.Collections.Immutable;
using System.Reflection.Internal;
using System.Runtime.InteropServices;
+using System.Text;
namespace System.Reflection.Metadata.Ecma335
{
@@ -553,10 +554,10 @@ private static ImmutableArray SerializeStringHeap(
int position = stringHeapStartOffset + heapBuilder.Count;
// It is important to use ordinal comparison otherwise we'll use the current culture!
- if (prev.EndsWith(entry.Key, StringComparison.Ordinal) && !BlobUtilities.IsLowSurrogateChar(entry.Key[0]))
+ if (prev.EndsWith(entry.Key, StringComparison.Ordinal) && !char.IsLowSurrogate(entry.Key[0]))
{
// Map over the tail of prev string. Watch for null-terminator of prev string.
- stringVirtualIndexToHeapOffsetMap[entry.Value.GetWriterVirtualIndex()] = position - (BlobUtilities.GetUTF8ByteCount(entry.Key) + 1);
+ stringVirtualIndexToHeapOffsetMap[entry.Value.GetWriterVirtualIndex()] = position - (Encoding.UTF8.GetByteCount(entry.Key) + 1);
}
else
{
diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/MetadataBuilder.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/MetadataBuilder.cs
index c0c576cf806021..c7bfdd82c5638c 100644
--- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/MetadataBuilder.cs
+++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/MetadataBuilder.cs
@@ -57,10 +57,7 @@ internal static void SerializeMetadataHeader(BlobBuilder builder, string metadat
builder.WriteByte(0);
int metadataVersionEnd = builder.Count;
- for (int i = 0; i < sizes.MetadataVersionPaddedLength - (metadataVersionEnd - metadataVersionStart); i++)
- {
- builder.WriteByte(0);
- }
+ builder.WriteBytes(0, sizes.MetadataVersionPaddedLength - (metadataVersionEnd - metadataVersionStart));
// reserved
builder.WriteUInt16(0);
@@ -74,45 +71,39 @@ internal static void SerializeMetadataHeader(BlobBuilder builder, string metadat
// emit the #Pdb stream first so that only a single page has to be read in order to find out PDB ID
if (sizes.IsStandaloneDebugMetadata)
{
- SerializeStreamHeader(ref offsetFromStartOfMetadata, sizes.StandalonePdbStreamSize, "#Pdb", builder);
+ SerializeStreamHeader(ref offsetFromStartOfMetadata, sizes.StandalonePdbStreamSize, "#Pdb"u8, builder);
}
// Spec: Some compilers store metadata in a #- stream, which holds an uncompressed, or non-optimized, representation of metadata tables;
// this includes extra metadata -Ptr tables. Such PE files do not form part of ECMA-335 standard.
//
// Note: EnC delta is stored as uncompressed metadata stream.
- SerializeStreamHeader(ref offsetFromStartOfMetadata, sizes.MetadataTableStreamSize, (sizes.IsCompressed ? "#~" : "#-"), builder);
+ SerializeStreamHeader(ref offsetFromStartOfMetadata, sizes.MetadataTableStreamSize, (sizes.IsCompressed ? "#~"u8 : "#-"u8), builder);
- SerializeStreamHeader(ref offsetFromStartOfMetadata, sizes.GetAlignedHeapSize(HeapIndex.String), "#Strings", builder);
- SerializeStreamHeader(ref offsetFromStartOfMetadata, sizes.GetAlignedHeapSize(HeapIndex.UserString), "#US", builder);
- SerializeStreamHeader(ref offsetFromStartOfMetadata, sizes.GetAlignedHeapSize(HeapIndex.Guid), "#GUID", builder);
- SerializeStreamHeader(ref offsetFromStartOfMetadata, sizes.GetAlignedHeapSize(HeapIndex.Blob), "#Blob", builder);
+ SerializeStreamHeader(ref offsetFromStartOfMetadata, sizes.GetAlignedHeapSize(HeapIndex.String), "#Strings"u8, builder);
+ SerializeStreamHeader(ref offsetFromStartOfMetadata, sizes.GetAlignedHeapSize(HeapIndex.UserString), "#US"u8, builder);
+ SerializeStreamHeader(ref offsetFromStartOfMetadata, sizes.GetAlignedHeapSize(HeapIndex.Guid), "#GUID"u8, builder);
+ SerializeStreamHeader(ref offsetFromStartOfMetadata, sizes.GetAlignedHeapSize(HeapIndex.Blob), "#Blob"u8, builder);
if (sizes.IsEncDelta)
{
- SerializeStreamHeader(ref offsetFromStartOfMetadata, 0, "#JTD", builder);
+ SerializeStreamHeader(ref offsetFromStartOfMetadata, 0, "#JTD"u8, builder);
}
int endOffset = builder.Count;
Debug.Assert(endOffset - startOffset == sizes.MetadataHeaderSize);
}
- private static void SerializeStreamHeader(ref int offsetFromStartOfMetadata, int alignedStreamSize, string streamName, BlobBuilder builder)
+ private static void SerializeStreamHeader(ref int offsetFromStartOfMetadata, int alignedStreamSize, ReadOnlySpan streamName, BlobBuilder builder)
{
// 4 for the first uint (offset), 4 for the second uint (padded size), length of stream name + 1 for null terminator (then padded)
int sizeOfStreamHeader = MetadataSizes.GetMetadataStreamHeaderSize(streamName);
builder.WriteInt32(offsetFromStartOfMetadata);
builder.WriteInt32(alignedStreamSize);
- foreach (char ch in streamName)
- {
- builder.WriteByte((byte)ch);
- }
+ builder.WriteBytes(streamName);
// After offset, size, and stream name, write 0-bytes until we reach our padded size.
- for (uint i = 8 + (uint)streamName.Length; i < sizeOfStreamHeader; i++)
- {
- builder.WriteByte(0);
- }
+ builder.WriteBytes(0, sizeOfStreamHeader - (8 + streamName.Length));
offsetFromStartOfMetadata += alignedStreamSize;
}
diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/MetadataRootBuilder.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/MetadataRootBuilder.cs
index 2945d14acbfb52..241d4132c69269 100644
--- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/MetadataRootBuilder.cs
+++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/MetadataRootBuilder.cs
@@ -3,6 +3,7 @@
using System.Collections.Immutable;
using System.Diagnostics;
+using System.Text;
namespace System.Reflection.Metadata.Ecma335
{
@@ -58,8 +59,8 @@ public MetadataRootBuilder(MetadataBuilder tablesAndHeaps, string? metadataVersi
Throw.ArgumentNull(nameof(tablesAndHeaps));
}
- Debug.Assert(BlobUtilities.GetUTF8ByteCount(DefaultMetadataVersionString) == DefaultMetadataVersionString.Length);
- int metadataVersionByteCount = metadataVersion != null ? BlobUtilities.GetUTF8ByteCount(metadataVersion) : DefaultMetadataVersionString.Length;
+ Debug.Assert(Encoding.UTF8.GetByteCount(DefaultMetadataVersionString) == DefaultMetadataVersionString.Length);
+ int metadataVersionByteCount = metadataVersion != null ? Encoding.UTF8.GetByteCount(metadataVersion) : DefaultMetadataVersionString.Length;
if (metadataVersionByteCount > MetadataSizes.MaxMetadataVersionByteCount)
{
diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/MetadataSizes.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/MetadataSizes.cs
index 7e8ffaafe47143..5a7d6ce08f3aa6 100644
--- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/MetadataSizes.cs
+++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/MetadataSizes.cs
@@ -361,14 +361,14 @@ internal int MetadataHeaderSize
const int StandalonePdbStreamHeaderSize = 16;
Debug.Assert(RegularStreamHeaderSizes ==
- GetMetadataStreamHeaderSize("#~") +
- GetMetadataStreamHeaderSize("#Strings") +
- GetMetadataStreamHeaderSize("#US") +
- GetMetadataStreamHeaderSize("#GUID") +
- GetMetadataStreamHeaderSize("#Blob"));
+ GetMetadataStreamHeaderSize("#~"u8) +
+ GetMetadataStreamHeaderSize("#Strings"u8) +
+ GetMetadataStreamHeaderSize("#US"u8) +
+ GetMetadataStreamHeaderSize("#GUID"u8) +
+ GetMetadataStreamHeaderSize("#Blob"u8));
- Debug.Assert(EncDeltaMarkerStreamHeaderSize == GetMetadataStreamHeaderSize("#JTD"));
- Debug.Assert(StandalonePdbStreamHeaderSize == GetMetadataStreamHeaderSize("#Pdb"));
+ Debug.Assert(EncDeltaMarkerStreamHeaderSize == GetMetadataStreamHeaderSize("#JTD"u8));
+ Debug.Assert(StandalonePdbStreamHeaderSize == GetMetadataStreamHeaderSize("#Pdb"u8));
return
sizeof(uint) + // signature
@@ -385,7 +385,7 @@ internal int MetadataHeaderSize
}
}
- internal static int GetMetadataStreamHeaderSize(string streamName)
+ internal static int GetMetadataStreamHeaderSize(ReadOnlySpan streamName)
{
return
sizeof(int) + // offset
diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/PortablePdbBuilder.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/PortablePdbBuilder.cs
index dfd862daee2340..28a138c247b286 100644
--- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/PortablePdbBuilder.cs
+++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/PortablePdbBuilder.cs
@@ -4,6 +4,7 @@
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Diagnostics;
+using System.Text;
namespace System.Reflection.Metadata.Ecma335
{
@@ -60,7 +61,7 @@ public PortablePdbBuilder(
_builder = tablesAndHeaps;
_entryPoint = entryPoint;
- Debug.Assert(BlobUtilities.GetUTF8ByteCount(MetadataVersion) == MetadataVersion.Length);
+ Debug.Assert(Encoding.UTF8.GetByteCount(MetadataVersion) == MetadataVersion.Length);
_serializedMetadata = tablesAndHeaps.GetSerializedMetadata(typeSystemRowCounts, MetadataVersion.Length, isStandaloneDebugMetadata: true);
IdProvider = idProvider ?? BlobContentId.GetTimeBasedProvider();
diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/IL/MethodBodyBlock.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/IL/MethodBodyBlock.cs
index 6085b95d0f4b90..0d9c72f377cc92 100644
--- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/IL/MethodBodyBlock.cs
+++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/IL/MethodBodyBlock.cs
@@ -191,8 +191,8 @@ public static MethodBodyBlock Create(BlobReader reader)
private static ImmutableArray ReadSmallExceptionHandlers(ref BlobReader memReader, int count)
{
- var result = new ExceptionRegion[count];
- for (int i = 0; i < result.Length; i++)
+ var result = ImmutableArray.CreateBuilder(count);
+ for (int i = 0; i < count; i++)
{
var kind = (ExceptionRegionKind)memReader.ReadUInt16();
var tryOffset = memReader.ReadUInt16();
@@ -200,27 +200,27 @@ private static ImmutableArray ReadSmallExceptionHandlers(ref Bl
var handlerOffset = memReader.ReadUInt16();
var handlerLength = memReader.ReadByte();
var classTokenOrFilterOffset = memReader.ReadInt32();
- result[i] = new ExceptionRegion(kind, tryOffset, tryLength, handlerOffset, handlerLength, classTokenOrFilterOffset);
+ result.Add(new ExceptionRegion(kind, tryOffset, tryLength, handlerOffset, handlerLength, classTokenOrFilterOffset));
}
- return ImmutableArray.Create(result);
+ return result.MoveToImmutable();
}
private static ImmutableArray ReadFatExceptionHandlers(ref BlobReader memReader, int count)
{
- var result = new ExceptionRegion[count];
- for (int i = 0; i < result.Length; i++)
+ var result = ImmutableArray.CreateBuilder(count);
+ for (int i = 0; i < count; i++)
{
- var sehFlags = (ExceptionRegionKind)memReader.ReadUInt32();
+ var kind = (ExceptionRegionKind)memReader.ReadUInt32();
int tryOffset = memReader.ReadInt32();
int tryLength = memReader.ReadInt32();
int handlerOffset = memReader.ReadInt32();
int handlerLength = memReader.ReadInt32();
int classTokenOrFilterOffset = memReader.ReadInt32();
- result[i] = new ExceptionRegion(sehFlags, tryOffset, tryLength, handlerOffset, handlerLength, classTokenOrFilterOffset);
+ result.Add(new ExceptionRegion(kind, tryOffset, tryLength, handlerOffset, handlerLength, classTokenOrFilterOffset));
}
- return ImmutableArray.Create(result);
+ return result.MoveToImmutable();
}
}
}
diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Internal/BlobHeap.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Internal/BlobHeap.cs
index 00bac867344a61..19c342445a03c0 100644
--- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Internal/BlobHeap.cs
+++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Internal/BlobHeap.cs
@@ -85,12 +85,11 @@ internal BlobHeap(MemoryBlock block, MetadataKind metadataKind)
}
}
- internal byte[] GetBytes(BlobHandle handle)
+ internal byte[] GetBytes(BlobHandle handle, bool unique = true)
{
if (handle.IsVirtual)
{
- // consider: if we returned an ImmutableArray we wouldn't need to copy
- return GetVirtualBlobBytes(handle, unique: true);
+ return GetVirtualBlobBytes(handle, unique);
}
int offset = handle.GetHeapOffset();
diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/MetadataReader.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/MetadataReader.cs
index fc0bfd054042e8..f170f67573d5cb 100644
--- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/MetadataReader.cs
+++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/MetadataReader.cs
@@ -1080,8 +1080,7 @@ public byte[] GetBlobBytes(BlobHandle handle)
public ImmutableArray GetBlobContent(BlobHandle handle)
{
- // TODO: We can skip a copy for virtual blobs.
- byte[]? bytes = GetBlobBytes(handle);
+ byte[]? bytes = BlobHeap.GetBytes(handle, unique: false);
return ImmutableCollectionsMarshal.AsImmutableArray(bytes);
}
diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/ManagedTextSection.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/ManagedTextSection.cs
index 7ed8d1381c2737..c7201870d4741d 100644
--- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/ManagedTextSection.cs
+++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/ManagedTextSection.cs
@@ -275,11 +275,9 @@ public void Serialize(
}
// strong name signature:
- strongNameSignature = builder.ReserveBytes(StrongNameSignatureSize);
-
// The bytes are required to be 0 for the purpose of calculating hash of the PE content
- // when strong name signing.
- new BlobWriter(strongNameSignature).WriteBytes(0, StrongNameSignatureSize);
+ // when strong name signing. This is already handled by ReserveBytes.
+ strongNameSignature = builder.ReserveBytes(StrongNameSignatureSize);
// debug directory and data:
if (debugDataBuilderOpt != null)
diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEBuilder.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEBuilder.cs
index 22fec2c1d4d12f..8389ff7359c1b0 100644
--- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEBuilder.cs
+++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEBuilder.cs
@@ -150,23 +150,16 @@ private ImmutableArray SerializeSections()
return result.MoveToImmutable();
}
- private static unsafe void WritePESignature(BlobBuilder builder)
+ private static void WritePESignature(BlobBuilder builder)
{
// MS-DOS stub (128 bytes)
- ReadOnlySpan header = DosHeader;
- Debug.Assert(DosHeader.Length == DosHeaderSize);
- fixed (byte* ptr = header)
- {
- builder.WriteBytes(ptr, header.Length);
- }
+ builder.WriteBytes(DosHeader);
// PE Signature "PE\0\0"
builder.WriteUInt32(PEHeaders.PESignature);
}
- internal const int DosHeaderSize = 0x80;
-
- private static ReadOnlySpan DosHeader => // DosHeaderSize
+ internal static ReadOnlySpan DosHeader =>
[
0x4d, 0x5a, 0x90, 0x00, 0x03, 0x00, 0x00, 0x00,
0x04, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00,
diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEHeaderBuilder.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEHeaderBuilder.cs
index adf2334da9c5bc..9b6764fcb6d007 100644
--- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEHeaderBuilder.cs
+++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEHeaderBuilder.cs
@@ -108,7 +108,7 @@ public static PEHeaderBuilder CreateLibraryHeader()
internal bool Is32Bit => Machine != Machine.Amd64 && Machine != Machine.IA64 && Machine != Machine.Arm64 && Machine != Machine.LoongArch64 && Machine != Machine.RiscV64;
internal int ComputeSizeOfPEHeaders(int sectionCount) =>
- PEBuilder.DosHeaderSize +
+ PEBuilder.DosHeader.Length +
PEHeaders.PESignatureSize +
CoffHeader.Size +
PEHeader.Size(Is32Bit) +
diff --git a/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEReader.EmbeddedPortablePdb.cs b/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEReader.EmbeddedPortablePdb.cs
index cf8aeb00bcc0da..5fc2814f1c199a 100644
--- a/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEReader.EmbeddedPortablePdb.cs
+++ b/src/libraries/System.Reflection.Metadata/src/System/Reflection/PortableExecutable/PEReader.EmbeddedPortablePdb.cs
@@ -99,13 +99,7 @@ internal static unsafe NativeHeapMemoryBlock DecodeEmbeddedPortablePdbDebugDirec
try
{
-#if NET
- actualLength = deflate.TryReadAll(new Span(decompressed.Pointer, decompressed.Size));
-#else
- using var decompressedStream = new UnmanagedMemoryStream(decompressed.Pointer, decompressed.Size, decompressed.Size, FileAccess.Write);
- deflate.CopyTo(decompressedStream);
- actualLength = (int)decompressedStream.Position;
-#endif
+ actualLength = deflate.ReadAtLeast(new Span(decompressed.Pointer, decompressed.Size), decompressed.Size, throwOnEndOfStream: false);
}
catch (Exception e)
{
diff --git a/src/libraries/System.Reflection.Metadata/tests/Utilities/HashTests.cs b/src/libraries/System.Reflection.Metadata/tests/Utilities/HashTests.cs
index b1cc1c0108f29a..08ad13dc15e770 100644
--- a/src/libraries/System.Reflection.Metadata/tests/Utilities/HashTests.cs
+++ b/src/libraries/System.Reflection.Metadata/tests/Utilities/HashTests.cs
@@ -32,11 +32,5 @@ public void CombineUIntInt()
{
Assert.Equal(536869063, Hash.Combine((uint)13, 42));
}
-
- [Fact]
- public void CombineBoolInt()
- {
- Assert.Equal(-1521134253, Hash.Combine(true, 42));
- }
}
}