< Summary

Line coverage
0%
Covered lines: 0
Uncovered lines: 72
Coverable lines: 72
Total lines: 133
Line coverage: 0%
Branch coverage
0%
Covered branches: 0
Total branches: 18
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(...)100%110%
.ctor(...)0%220%
.ctor(...)0%220%
Initialize(...)0%220%
FromHash(...)0%220%
FromHash(...)0%220%
FromHash(...)0%220%
GetTimeBasedProvider()100%110%
Equals(...)0%220%
Equals(...)0%220%
GetHashCode()100%110%
op_Equality(...)100%110%
op_Inequality(...)100%110%

File(s)

https://raw.githubusercontent.com/dotnet/runtime/811a7eabb75c42db53440e8ba3f60c07511cfd1f/src/libraries/System.Reflection.Metadata/src/System/Reflection/Metadata/BlobContentId.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.CodeAnalysis;
 7using System.Reflection.Internal;
 8
 9namespace System.Reflection.Metadata
 10{
 11    public readonly struct BlobContentId : IEquatable<BlobContentId>
 12    {
 13        private const int Size = BlobUtilities.SizeOfGuid + sizeof(uint);
 14
 15        private readonly Guid _guid;
 16        private readonly uint _stamp;
 17
 018        public Guid Guid => _guid;
 019        public uint Stamp => _stamp;
 20
 21        public BlobContentId(Guid guid, uint stamp)
 022        {
 023            _guid = guid;
 024            _stamp = stamp;
 025        }
 26
 27        public BlobContentId(ImmutableArray<byte> id)
 028        {
 029            if (id.IsDefault)
 030            {
 031                Throw.ArgumentNull(nameof(id));
 32            }
 33
 034            Initialize(id.AsSpan(), out _guid, out _stamp);
 035        }
 36
 37        public BlobContentId(byte[] id)
 038        {
 039            if (id is null)
 040            {
 041                Throw.ArgumentNull(nameof(id));
 42            }
 43
 044            Initialize(id, out _guid, out _stamp);
 045        }
 46
 47        private static unsafe void Initialize(ReadOnlySpan<byte> id, out Guid guid, out uint stamp)
 048        {
 049            if (id.Length != Size)
 050            {
 051                throw new ArgumentException(SR.Format(SR.UnexpectedArrayLength, Size), nameof(id));
 52            }
 53
 054            fixed (byte* ptr = &id[0])
 055            {
 056                var reader = new BlobReader(ptr, id.Length);
 057                guid = reader.ReadGuid();
 058                stamp = reader.ReadUInt32();
 059            }
 060        }
 61
 062        public bool IsDefault => Guid == default(Guid) && Stamp == 0;
 63
 64        public static BlobContentId FromHash(ImmutableArray<byte> hashCode)
 065        {
 066            if (hashCode.IsDefault)
 067            {
 068                Throw.ArgumentNull(nameof(hashCode));
 69            }
 70
 071            return FromHash(hashCode.AsSpan());
 072        }
 73
 74        public static BlobContentId FromHash(byte[] hashCode)
 075        {
 076            if (hashCode is null)
 077            {
 078                Throw.ArgumentNull(nameof(hashCode));
 79            }
 80
 081            return FromHash(hashCode.AsSpan());
 082        }
 83
 84        private static BlobContentId FromHash(ReadOnlySpan<byte> hashCode)
 085        {
 86            const int minHashSize = 20;
 87
 088            if (hashCode.Length < minHashSize)
 089            {
 090                throw new ArgumentException(SR.Format(SR.HashTooShort, minHashSize), nameof(hashCode));
 91            }
 92
 93            // extract guid components from input data
 094            uint a = ((uint)hashCode[3] << 24 | (uint)hashCode[2] << 16 | (uint)hashCode[1] << 8 | hashCode[0]);
 095            ushort b = (ushort)(hashCode[5] << 8 | hashCode[4]);
 096            ushort c = (ushort)(hashCode[7] << 8 | hashCode[6]);
 097            byte d = hashCode[8];
 098            byte e = hashCode[9];
 099            byte f = hashCode[10];
 0100            byte g = hashCode[11];
 0101            byte h = hashCode[12];
 0102            byte i = hashCode[13];
 0103            byte j = hashCode[14];
 0104            byte k = hashCode[15];
 105
 106            // modify the guid data so it decodes to the form of a "random" guid ala rfc4122
 0107            c = (ushort)((c & 0x0fff) | (4 << 12));
 0108            d = (byte)((d & 0x3f) | (2 << 6));
 0109            Guid guid = new Guid((int)a, (short)b, (short)c, d, e, f, g, h, i, j, k);
 110
 111            // compute a random-looking stamp from the remaining bits, but with the upper bit set
 0112            uint stamp = 0x80000000u | ((uint)hashCode[19] << 24 | (uint)hashCode[18] << 16 | (uint)hashCode[17] << 8 | 
 113
 0114            return new BlobContentId(guid, stamp);
 0115        }
 116
 117        public static Func<IEnumerable<Blob>, BlobContentId> GetTimeBasedProvider()
 0118        {
 119            // In the PE File Header this is a "Time/Date Stamp" whose description is "Time and date
 120            // the file was created in seconds since January 1st 1970 00:00:00 or 0"
 121            // However, when we want to make it deterministic we fill it in (later) with bits from the hash of the full 
 0122            uint timestamp = (uint)DateTimeOffset.UtcNow.ToUnixTimeSeconds();
 0123            return content => new BlobContentId(Guid.NewGuid(), timestamp);
 0124        }
 125
 0126        public bool Equals(BlobContentId other) => Guid == other.Guid && Stamp == other.Stamp;
 0127        public override bool Equals([NotNullWhen(true)] object? obj) => obj is BlobContentId bcid && Equals(bcid);
 0128        public override int GetHashCode() => Hash.Combine(Stamp, Guid.GetHashCode());
 0129        public static bool operator ==(BlobContentId left, BlobContentId right) => left.Equals(right);
 0130        public static bool operator !=(BlobContentId left, BlobContentId right) => !left.Equals(right);
 131    }
 132}
 133