// dnlib: See LICENSE.txt for more info using System; using dnlib.IO; namespace dnlib.DotNet.MD { /// /// Represents the #Blob stream /// public sealed class BlobStream : HeapStream { /// public BlobStream() { } /// public BlobStream(DataReaderFactory mdReaderFactory, uint metadataBaseOffset, StreamHeader streamHeader) : base(mdReaderFactory, metadataBaseOffset, streamHeader) { } /// /// Reads data /// /// Offset of data /// The data or null if invalid offset public byte[] Read(uint offset) { // The CLR has a special check for offset 0. It always interprets it as // 0-length data, even if that first byte isn't 0 at all. if (offset == 0) return Array2.Empty(); if (!TryCreateReader(offset, out var reader)) return null; return reader.ToArray(); } /// /// Reads data just like , but returns an empty array if /// offset is invalid /// /// Offset of data /// The data public byte[] ReadNoNull(uint offset) => Read(offset) ?? Array2.Empty(); /// /// Creates a reader that can access a blob /// /// Offset of blob /// A new stream public DataReader CreateReader(uint offset) { if (TryCreateReader(offset, out var reader)) return reader; return default; } /// /// Creates a reader that can access a blob or returns false on failure /// /// Offset of blob /// Updated with the reader /// public bool TryCreateReader(uint offset, out DataReader reader) { reader = dataReader; if (!IsValidOffset(offset)) return false; reader.Position = offset; if (!reader.TryReadCompressedUInt32(out uint length)) return false; if (!reader.CanRead(length)) return false; reader = reader.Slice(reader.Position, length); return true; } } }