public sealed class DelayImportDirectoryParser
{
    public IReadOnlyList<DelayImportInfo> Parse(byte[] rawBytes, NtHeaders nt, IReadOnlyList<SectionInfo> sections)
    {
        if (nt.OptionalHeader.DataDirectories.Count <= 13)
        {
            return Array.Empty<DelayImportInfo>();
        }

        var dir = nt.OptionalHeader.DataDirectories[13];
        if (dir.VirtualAddress == 0 || dir.Size == 0)
        {
            return Array.Empty<DelayImportInfo>();
        }

        var offset = RvaMapper.RvaToFileOffset(dir.VirtualAddress, sections, nt.OptionalHeader.SizeOfHeaders);
        if (offset is null)
        {
            return Array.Empty<DelayImportInfo>();
        }

        var items = new List<DelayImportInfo>();
        var pos = offset.Value;
        while (pos + 32 <= rawBytes.Length)
        {
            var attributes = BitConverter.ToUInt32(rawBytes, pos);
            var nameRva = BitConverter.ToUInt32(rawBytes, pos + 4);
            var moduleHandle = BitConverter.ToUInt32(rawBytes, pos + 8);
            var iat = BitConverter.ToUInt32(rawBytes, pos + 12);
            var intRva = BitConverter.ToUInt32(rawBytes, pos + 16);
            var biat = BitConverter.ToUInt32(rawBytes, pos + 20);
            var uiat = BitConverter.ToUInt32(rawBytes, pos + 24);
            var tds = BitConverter.ToUInt32(rawBytes, pos + 28);

            if (attributes == 0 && nameRva == 0 && moduleHandle == 0 && iat == 0 && intRva == 0 && biat == 0 && uiat == 0 && tds == 0)
            {
                break;
            }

            var dllName = DirectoryParserHelpers.ReadAsciiAtRva(rawBytes, nameRva, nt, sections, 512);
            items.Add(new DelayImportInfo(dllName, attributes, nameRva, moduleHandle, iat, intRva, biat, uiat, tds));
            pos += 32;
        }

        return items;
    }
}