// 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;
}
}
}