< Summary

Line coverage
0%
Covered lines: 0
Uncovered lines: 63
Coverable lines: 63
Total lines: 157
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 20
Branch coverage: 0%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity NPath complexity Sequence coverage
.ctor(...)0%440%
ValidateTypeSystemRowCounts(...)0%12120%
SerializeStandalonePdbStream(...)0%220%
Serialize(...)0%220%

File(s)

https://raw.githubusercontent.com/dotnet/runtime/811a7eabb75c42db53440e8ba3f60c07511cfd1f/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/Ecma335/PortablePdbBuilder.cs

#LineLine coverage
 1// Licensed to the .NET Foundation under one or more agreements.
 2// The .NET Foundation licenses this file to you under the MIT license.
 3
 4using System.Collections.Generic;
 5using System.Collections.Immutable;
 6using System.Diagnostics;
 7using System.Text;
 8
 9namespace System.Reflection.Metadata.Ecma335
 10{
 11    /// <summary>
 12    /// Builder of a Portable PDB image.
 13    /// </summary>
 14    public sealed class PortablePdbBuilder
 15    {
 016        public string MetadataVersion => PortablePdbVersions.DefaultMetadataVersion;
 017        public ushort FormatVersion => PortablePdbVersions.DefaultFormatVersion;
 18
 19        private Blob _pdbIdBlob;
 20        private readonly MethodDefinitionHandle _entryPoint;
 21        private readonly MetadataBuilder _builder;
 22        private readonly SerializedMetadata _serializedMetadata;
 23
 024        public Func<IEnumerable<Blob>, BlobContentId> IdProvider { get; }
 25
 26        /// <summary>
 27        /// Creates a builder of a Portable PDB image.
 28        /// </summary>
 29        /// <param name="tablesAndHeaps">
 30        /// Builder populated with debug metadata entities stored in tables and values stored in heaps.
 31        /// The entities and values will be enumerated when serializing the Portable PDB image.
 32        /// </param>
 33        /// <param name="typeSystemRowCounts">
 34        /// Row counts of all tables that the associated type-system metadata contain.
 35        /// Each slot in the array corresponds to a table (<see cref="TableIndex"/>).
 36        /// The length of the array must be equal to <see cref="MetadataTokens.TableCount"/>.
 37        /// </param>
 38        /// <param name="entryPoint">
 39        /// Entry point method definition handle.
 40        /// </param>
 41        /// <param name="idProvider">
 42        /// Function calculating id of content represented as a sequence of blobs.
 43        /// If not specified a default function that ignores the content and returns current time-based content id is us
 44        /// (<see cref="BlobContentId.GetTimeBasedProvider()"/>).
 45        /// You must specify a deterministic function to produce a deterministic Portable PDB image.
 46        /// </param>
 47        /// <exception cref="ArgumentNullException"><paramref name="tablesAndHeaps"/> or <paramref name="typeSystemRowCo
 048        public PortablePdbBuilder(
 049            MetadataBuilder tablesAndHeaps,
 050            ImmutableArray<int> typeSystemRowCounts,
 051            MethodDefinitionHandle entryPoint,
 052            Func<IEnumerable<Blob>, BlobContentId>? idProvider = null)
 053        {
 054            if (tablesAndHeaps is null)
 055            {
 056                Throw.ArgumentNull(nameof(tablesAndHeaps));
 57            }
 58
 059            ValidateTypeSystemRowCounts(typeSystemRowCounts);
 60
 061            _builder = tablesAndHeaps;
 062            _entryPoint = entryPoint;
 63
 064            Debug.Assert(Encoding.UTF8.GetByteCount(MetadataVersion) == MetadataVersion.Length);
 065            _serializedMetadata = tablesAndHeaps.GetSerializedMetadata(typeSystemRowCounts, MetadataVersion.Length, isSt
 66
 067            IdProvider = idProvider ?? BlobContentId.GetTimeBasedProvider();
 068        }
 69
 70        private static void ValidateTypeSystemRowCounts(ImmutableArray<int> typeSystemRowCounts)
 071        {
 072            if (typeSystemRowCounts.IsDefault)
 073            {
 074                Throw.ArgumentNull(nameof(typeSystemRowCounts));
 75            }
 76
 077            if (typeSystemRowCounts.Length != MetadataTokens.TableCount)
 078            {
 079                throw new ArgumentException(SR.Format(SR.ExpectedArrayOfSize, MetadataTokens.TableCount), nameof(typeSys
 80            }
 81
 082            for (int i = 0; i < typeSystemRowCounts.Length; i++)
 083            {
 084                if (typeSystemRowCounts[i] == 0)
 085                {
 086                    continue;
 87                }
 88
 089                if ((unchecked((uint)typeSystemRowCounts[i]) & ~TokenTypeIds.RIDMask) != 0)
 090                {
 091                    throw new ArgumentOutOfRangeException(nameof(typeSystemRowCounts), SR.Format(SR.RowCountOutOfRange, 
 92                }
 93
 094                if (((1UL << i) & (ulong)TableMask.ValidPortablePdbExternalTables) == 0)
 095                {
 096                    throw new ArgumentException(SR.Format(SR.RowCountMustBeZero, i), nameof(typeSystemRowCounts));
 97                }
 098            }
 099        }
 100
 101        /// <summary>
 102        /// Serialized #Pdb stream.
 103        /// </summary>
 104        private void SerializeStandalonePdbStream(BlobBuilder builder)
 0105        {
 0106            int startPosition = builder.Count;
 107
 108            // the id will be filled in later
 0109            _pdbIdBlob = builder.ReserveBytes(MetadataSizes.PdbIdSize);
 110
 0111            builder.WriteInt32(_entryPoint.IsNil ? 0 : MetadataTokens.GetToken(_entryPoint));
 112
 0113            builder.WriteUInt64(_serializedMetadata.Sizes.ExternalTablesMask);
 0114            MetadataWriterUtilities.SerializeRowCounts(builder, _serializedMetadata.Sizes.ExternalRowCounts);
 115
 0116            int endPosition = builder.Count;
 0117            Debug.Assert(_serializedMetadata.Sizes.CalculateStandalonePdbStreamSize() == endPosition - startPosition);
 0118        }
 119
 120        /// <summary>
 121        /// Serializes Portable PDB content into the given <see cref="BlobBuilder"/>.
 122        /// </summary>
 123        /// <param name="builder">Builder to write to.</param>
 124        /// <returns>The id of the serialized content.</returns>
 125        /// <exception cref="ArgumentNullException"><paramref name="builder"/> is null.</exception>
 126        public BlobContentId Serialize(BlobBuilder builder)
 0127        {
 0128            if (builder is null)
 0129            {
 0130                Throw.ArgumentNull(nameof(builder));
 131            }
 132
 133            // header:
 0134            MetadataBuilder.SerializeMetadataHeader(builder, MetadataVersion, _serializedMetadata.Sizes);
 135
 136            // #Pdb stream
 0137            SerializeStandalonePdbStream(builder);
 138
 139            // #~ or #- stream:
 0140            _builder.SerializeMetadataTables(builder, _serializedMetadata.Sizes, _serializedMetadata.StringMap, methodBo
 141
 142            // #Strings, #US, #Guid and #Blob streams:
 0143            _builder.WriteHeapsTo(builder, _serializedMetadata.StringHeap);
 144
 0145            var contentId = IdProvider(builder.GetBlobs());
 146
 147            // fill in the id:
 0148            var idWriter = new BlobWriter(_pdbIdBlob);
 0149            idWriter.WriteGuid(contentId.Guid);
 0150            idWriter.WriteUInt32(contentId.Stamp);
 0151            Debug.Assert(idWriter.RemainingBytes == 0);
 152
 0153            return contentId;
 0154        }
 155    }
 156}
 157