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()
{