diff --git a/src/System.Reflection.Metadata/src/Resources/Strings.resx b/src/System.Reflection.Metadata/src/Resources/Strings.resx index 830e1e557f9d..2e42af0cb46c 100644 --- a/src/System.Reflection.Metadata/src/Resources/Strings.resx +++ b/src/System.Reflection.Metadata/src/Resources/Strings.resx @@ -426,6 +426,9 @@ Hash must be at least {0}B long. + + Expected array of length {0}. + Value must be multiple of {0}. diff --git a/src/System.Reflection.Metadata/src/System/Reflection/Metadata/BlobContentId.cs b/src/System.Reflection.Metadata/src/System/Reflection/Metadata/BlobContentId.cs index 1d6d9ab4a918..5ae3e82be900 100644 --- a/src/System.Reflection.Metadata/src/System/Reflection/Metadata/BlobContentId.cs +++ b/src/System.Reflection.Metadata/src/System/Reflection/Metadata/BlobContentId.cs @@ -10,6 +10,8 @@ namespace System.Reflection.Metadata { public struct BlobContentId { + private const int Size = BlobUtilities.SizeOfGuid + sizeof(uint); + public Guid Guid { get; } public uint Stamp { get; } @@ -19,6 +21,31 @@ public BlobContentId(Guid guid, uint stamp) Stamp = stamp; } + public BlobContentId(ImmutableArray id) + : this(ImmutableByteArrayInterop.DangerousGetUnderlyingArray(id)) + { + } + + public unsafe BlobContentId(byte[] id) + { + if (id == null) + { + throw new ArgumentNullException(nameof(id)); + } + + if (id.Length != Size) + { + throw new ArgumentException(SR.Format(SR.UnexpectedArrayLength, Size), nameof(id)); + } + + fixed (byte* ptr = id) + { + var reader = new BlobReader(ptr, id.Length); + Guid = reader.ReadGuid(); + Stamp = reader.ReadUInt32(); + } + } + public bool IsDefault => Guid == default(Guid) && Stamp == 0; public static BlobContentId FromHash(ImmutableArray hashCode) diff --git a/src/System.Reflection.Metadata/tests/Metadata/BlobContentIdTests.cs b/src/System.Reflection.Metadata/tests/Metadata/BlobContentIdTests.cs index c8dcba134325..15107a5d10a7 100644 --- a/src/System.Reflection.Metadata/tests/Metadata/BlobContentIdTests.cs +++ b/src/System.Reflection.Metadata/tests/Metadata/BlobContentIdTests.cs @@ -22,9 +22,25 @@ public void Ctor() Assert.Equal(0x12345678u, id2.Stamp); Assert.False(id2.IsDefault); + var id3 = new BlobContentId(new byte[] { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14 }); + Assert.Equal(new Guid("04030201-0605-0807-090a-0b0c0d0e0f10"), id3.Guid); + Assert.Equal(0x14131211u, id3.Stamp); + Assert.False(id3.IsDefault); + Assert.True(default(BlobContentId).IsDefault); } + [Fact] + public void Ctor_Errors() + { + Assert.Throws("id", () => new BlobContentId(null)); + Assert.Throws("id", () => new BlobContentId(default(ImmutableArray))); + Assert.Throws("id", () => new BlobContentId(ImmutableArray.Create())); + Assert.Throws("id", () => new BlobContentId(ImmutableArray.Create(0))); + Assert.Throws("id", () => new BlobContentId(ImmutableArray.Create(0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13))); + Assert.Throws("id", () => new BlobContentId(ImmutableArray.Create(0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15))); + } + [Fact] public void FromHash() {