#include "binary_annotator.h"

#include <algorithm>
#include <cstdint>
#include <iostream>
#include <limits>
#include <string>
#include <vector>

#include "flatbuffers/base.h"
#include "flatbuffers/reflection.h"
#include "flatbuffers/util.h"
#include "flatbuffers/verifier.h"

namespace flatbuffers {
namespace {

static bool BinaryRegionSort(const BinaryRegion& a, const BinaryRegion& b) {
  return a.offset < b.offset;
}

static void SetError(BinaryRegionComment& comment, BinaryRegionStatus status,
                     std::string message = "") {
  comment.status = status;
  comment.status_message = message;
}

static BinaryRegion MakeBinaryRegion(
    const uint64_t offset = 0, const uint64_t length = 0,
    const BinaryRegionType type = BinaryRegionType::Unknown,
    const uint64_t array_length = 0, const uint64_t points_to_offset = 0,
    BinaryRegionComment comment = {}) {
  BinaryRegion region;
  region.offset = offset;
  region.length = length;
  region.type = type;
  region.array_length = array_length;
  region.points_to_offset = points_to_offset;
  region.comment = std::move(comment);
  return region;
}

static BinarySection MakeBinarySection(const std::string& name,
                                       const BinarySectionType type,
                                       std::vector<BinaryRegion> regions) {
  BinarySection section;
  section.name = name;
  section.type = type;
  section.regions = std::move(regions);
  return section;
}

static BinarySection MakeSingleRegionBinarySection(const std::string& name,
                                                   const BinarySectionType type,
                                                   const BinaryRegion& region) {
  std::vector<BinaryRegion> regions;
  regions.push_back(region);
  return MakeBinarySection(name, type, std::move(regions));
}

static bool IsNonZeroRegion(const uint64_t offset, const uint64_t length,
                            const uint8_t* const binary) {
  for (uint64_t i = offset; i < offset + length; ++i) {
    if (binary[i] != 0) {
      return true;
    }
  }
  return false;
}

static bool IsPrintableRegion(const uint64_t offset, const uint64_t length,
                              const uint8_t* const binary) {
  for (uint64_t i = offset; i < offset + length; ++i) {
    if (!isprint(binary[i])) {
      return false;
    }
  }
  return true;
}

static BinarySection GenerateMissingSection(const uint64_t offset,
                                            const uint64_t length,
                                            const uint8_t* const binary) {
  std::vector<BinaryRegion> regions;

  // Check if the region is all zeros or not, as that can tell us if it is
  // padding or not.
  if (IsNonZeroRegion(offset, length, binary)) {
    // Some of the padding bytes are non-zero, so this might be an unknown
    // section of the binary.
    // TODO(dbaileychess): We could be a bit smarter with different sized
    // alignments. For now, the 8 byte check encompasses all the smaller
    // alignments.
    BinaryRegionComment comment;
    comment.type = BinaryRegionCommentType::Unknown;
    if (length >= 8) {
      SetError(comment, BinaryRegionStatus::WARN_NO_REFERENCES);
    } else {
      SetError(comment, BinaryRegionStatus::WARN_CORRUPTED_PADDING);
    }

    regions.push_back(MakeBinaryRegion(offset, length * sizeof(uint8_t),
                                       BinaryRegionType::Unknown, length, 0,
                                       comment));

    return MakeBinarySection("no known references", BinarySectionType::Unknown,
                             std::move(regions));
  }

  BinaryRegionComment comment;
  comment.type = BinaryRegionCommentType::Padding;
  if (length >= 8) {
    SetError(comment, BinaryRegionStatus::WARN_PADDING_LENGTH);
  }

  // This region is most likely padding.
  regions.push_back(MakeBinaryRegion(offset, length * sizeof(uint8_t),
                                     BinaryRegionType::Uint8, length, 0,
                                     comment));

  return MakeBinarySection("", BinarySectionType::Padding, std::move(regions));
}

}  // namespace

std::map<uint64_t, BinarySection> BinaryAnnotator::Annotate() {
  if (bfbs_ != nullptr && bfbs_length_ != 0) {
    flatbuffers::Verifier verifier(bfbs_, static_cast<size_t>(bfbs_length_));
    if ((is_size_prefixed_ &&
         !reflection::VerifySizePrefixedSchemaBuffer(verifier)) ||
        !reflection::VerifySchemaBuffer(verifier)) {
      return {};
    }
  }

  // The binary is too short to read as a flatbuffers.
  if (binary_length_ < FLATBUFFERS_MIN_BUFFER_SIZE) {
    return {};
  }

  // Make sure we start with a clean slate.
  vtables_.clear();
  sections_.clear();

  // First parse the header region which always start at offset 0.
  // The returned offset will point to the root_table location.
  const uint64_t root_table_offset = BuildHeader(0);

  if (IsValidOffset(root_table_offset)) {
    // Build the root table, and all else will be referenced from it.
    BuildTable(root_table_offset, BinarySectionType::RootTable, RootTable());
  }

  // Now that all the sections are built, make sure the binary sections are
  // contiguous.
  FixMissingRegions();

  // Then scan the area between BinarySections insert padding sections that are
  // implied.
  FixMissingSections();

  return sections_;
}

uint64_t BinaryAnnotator::BuildHeader(const uint64_t header_offset) {
  uint64_t offset = header_offset;
  std::vector<BinaryRegion> regions;

  // If this binary is a size prefixed one, attempt to parse the size.
  if (is_size_prefixed_) {
    BinaryRegionComment prefix_length_comment;
    prefix_length_comment.type = BinaryRegionCommentType::SizePrefix;

    bool has_prefix_value = false;
    const auto prefix_length = ReadScalar<uoffset64_t>(offset);
    if (*prefix_length <= binary_length_) {
      regions.push_back(MakeBinaryRegion(offset, sizeof(uoffset64_t),
                                         BinaryRegionType::Uint64, 0, 0,
                                         prefix_length_comment));
      offset += sizeof(uoffset64_t);
      has_prefix_value = true;
    }

    if (!has_prefix_value) {
      const auto prefix_length = ReadScalar<uoffset_t>(offset);
      if (*prefix_length <= binary_length_) {
        regions.push_back(MakeBinaryRegion(offset, sizeof(uoffset_t),
                                           BinaryRegionType::Uint32, 0, 0,
                                           prefix_length_comment));
        offset += sizeof(uoffset_t);
        has_prefix_value = true;
      }
    }

    if (!has_prefix_value) {
      SetError(prefix_length_comment, BinaryRegionStatus::ERROR);
    }
  }

  const auto root_table_offset = ReadScalar<uint32_t>(offset);

  if (!root_table_offset.has_value()) {
    // This shouldn't occur, since we validate the min size of the buffer
    // before. But for completion sake, we shouldn't read passed the binary end.
    return std::numeric_limits<uint64_t>::max();
  }

  const auto root_table_loc = offset + *root_table_offset;

  BinaryRegionComment root_offset_comment;
  root_offset_comment.type = BinaryRegionCommentType::RootTableOffset;
  root_offset_comment.name = RootTable()->name()->str();

  if (!IsValidOffset(root_table_loc)) {
    SetError(root_offset_comment,
             BinaryRegionStatus::ERROR_OFFSET_OUT_OF_BINARY);
  }

  regions.push_back(MakeBinaryRegion(offset, sizeof(uint32_t),
                                     BinaryRegionType::UOffset, 0,
                                     root_table_loc, root_offset_comment));
  offset += sizeof(uint32_t);

  if (IsValidRead(offset, flatbuffers::kFileIdentifierLength) &&
      IsPrintableRegion(offset, flatbuffers::kFileIdentifierLength, binary_)) {
    BinaryRegionComment comment;
    comment.type = BinaryRegionCommentType::FileIdentifier;
    // Check if the file identifier region has non-zero data, and assume its
    // the file identifier. Otherwise, it will get filled in with padding
    // later.
    regions.push_back(MakeBinaryRegion(
        offset, flatbuffers::kFileIdentifierLength * sizeof(uint8_t),
        BinaryRegionType::Char, flatbuffers::kFileIdentifierLength, 0,
        comment));
  }

  AddSection(header_offset, MakeBinarySection("", BinarySectionType::Header,
                                              std::move(regions)));

  return root_table_loc;
}

BinaryAnnotator::VTable* BinaryAnnotator::GetOrBuildVTable(
    const uint64_t vtable_offset, const reflection::Object* const table,
    const uint64_t offset_of_referring_table) {
  // Get a list of vtables (if any) already defined at this offset.
  std::list<VTable>& vtables = vtables_[vtable_offset];

  // See if this vtable for the table type has been generated before.
  for (VTable& vtable : vtables) {
    if (vtable.referring_table == table) {
      return &vtable;
    }
  }

  // If we are trying to make a new vtable and it is already encompassed by
  // another binary section, something is corrupted.
  if (vtables.empty() && ContainsSection(vtable_offset)) {
    return nullptr;
  }

  const std::string referring_table_name = table->name()->str();

  BinaryRegionComment vtable_size_comment;
  vtable_size_comment.type = BinaryRegionCommentType::VTableSize;

  const auto vtable_length = ReadScalar<uint16_t>(vtable_offset);
  if (!vtable_length.has_value()) {
    const uint64_t remaining = RemainingBytes(vtable_offset);

    SetError(vtable_size_comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
             "2");

    AddSection(vtable_offset,
               MakeSingleRegionBinarySection(
                   referring_table_name, BinarySectionType::VTable,
                   MakeBinaryRegion(vtable_offset, remaining,
                                    BinaryRegionType::Unknown, remaining, 0,
                                    vtable_size_comment)));
    return nullptr;
  }

  // Vtables start with the size of the vtable
  const uint16_t vtable_size = vtable_length.value();

  if (!IsValidOffset(vtable_offset + vtable_size - 1)) {
    SetError(vtable_size_comment, BinaryRegionStatus::ERROR_LENGTH_TOO_LONG);
    // The vtable_size points to off the end of the binary.
    AddSection(vtable_offset,
               MakeSingleRegionBinarySection(
                   referring_table_name, BinarySectionType::VTable,
                   MakeBinaryRegion(vtable_offset, sizeof(uint16_t),
                                    BinaryRegionType::Uint16, 0, 0,
                                    vtable_size_comment)));

    return nullptr;
  } else if (vtable_size < 2 * sizeof(uint16_t)) {
    SetError(vtable_size_comment, BinaryRegionStatus::ERROR_LENGTH_TOO_SHORT,
             "4");
    // The size includes itself and the table size which are both uint16_t.
    AddSection(vtable_offset,
               MakeSingleRegionBinarySection(
                   referring_table_name, BinarySectionType::VTable,
                   MakeBinaryRegion(vtable_offset, sizeof(uint16_t),
                                    BinaryRegionType::Uint16, 0, 0,
                                    vtable_size_comment)));
    return nullptr;
  }

  std::vector<BinaryRegion> regions;

  regions.push_back(MakeBinaryRegion(vtable_offset, sizeof(uint16_t),
                                     BinaryRegionType::Uint16, 0, 0,
                                     vtable_size_comment));
  uint64_t offset = vtable_offset + sizeof(uint16_t);

  BinaryRegionComment ref_table_len_comment;
  ref_table_len_comment.type =
      BinaryRegionCommentType::VTableRefferingTableLength;

  // Ensure we can read the next uint16_t field, which is the size of the
  // referring table.
  const auto table_length = ReadScalar<uint16_t>(offset);

  if (!table_length.has_value()) {
    const uint64_t remaining = RemainingBytes(offset);
    SetError(ref_table_len_comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
             "2");

    AddSection(offset, MakeSingleRegionBinarySection(
                           referring_table_name, BinarySectionType::VTable,
                           MakeBinaryRegion(
                               offset, remaining, BinaryRegionType::Unknown,
                               remaining, 0, ref_table_len_comment)));
    return nullptr;
  }

  // Then they have the size of the table they reference.
  const uint16_t table_size = table_length.value();

  if (!IsValidOffset(offset_of_referring_table + table_size - 1)) {
    SetError(ref_table_len_comment, BinaryRegionStatus::ERROR_LENGTH_TOO_LONG);
  } else if (table_size < 4) {
    SetError(ref_table_len_comment, BinaryRegionStatus::ERROR_LENGTH_TOO_SHORT,
             "4");
  }

  regions.push_back(MakeBinaryRegion(offset, sizeof(uint16_t),
                                     BinaryRegionType::Uint16, 0, 0,
                                     ref_table_len_comment));
  offset += sizeof(uint16_t);

  const uint64_t offset_start = offset;

  // A mapping between field (and its id) to the relative offset (uint16_t) from
  // the start of the table.
  std::map<uint16_t, VTable::Entry> fields;

  // Counter for determining if the binary has more vtable entries than the
  // schema provided. This can occur if the binary was created at a newer schema
  // version and is being processed with an older one.
  uint16_t fields_processed = 0;

  // Loop over all the fields.
  ForAllFields(table, /*reverse=*/false, [&](const reflection::Field* field) {
    const uint64_t field_offset = offset_start + field->id() * sizeof(uint16_t);

    if (field_offset >= vtable_offset + vtable_size) {
      // This field_offset is too large for this vtable, so it must come from a
      // newer schema than the binary was create with or the binary writer did
      // not write it. For either case, it is safe to ignore.

      // TODO(dbaileychess): We could show which fields are not set an their
      // default values if we want. We just need a way to make it obvious that
      // it isn't part of the buffer.
      return;
    }

    BinaryRegionComment field_comment;
    field_comment.type = BinaryRegionCommentType::VTableFieldOffset;
    field_comment.name = std::string(field->name()->c_str()) +
                         "` (id: " + std::to_string(field->id()) + ")";

    const auto offset_from_table = ReadScalar<uint16_t>(field_offset);

    if (!offset_from_table.has_value()) {
      const uint64_t remaining = RemainingBytes(field_offset);

      SetError(field_comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY, "2");
      regions.push_back(MakeBinaryRegion(field_offset, remaining,
                                         BinaryRegionType::Unknown, remaining,
                                         0, field_comment));

      return;
    }

    if (!IsValidOffset(offset_of_referring_table + offset_from_table.value() -
                       1)) {
      SetError(field_comment, BinaryRegionStatus::ERROR_OFFSET_OUT_OF_BINARY);
      regions.push_back(MakeBinaryRegion(field_offset, sizeof(uint16_t),
                                         BinaryRegionType::VOffset, 0, 0,
                                         field_comment));
      return;
    }

    VTable::Entry entry;
    entry.field = field;
    entry.offset_from_table = offset_from_table.value();
    fields.insert(std::make_pair(field->id(), entry));

    std::string default_label;
    if (offset_from_table.value() == 0) {
      // Not present, so could be default or be optional.
      if (field->required()) {
        SetError(field_comment,
                 BinaryRegionStatus::ERROR_REQUIRED_FIELD_NOT_PRESENT);
        // If this is a required field, make it known this is an error.
        regions.push_back(MakeBinaryRegion(field_offset, sizeof(uint16_t),
                                           BinaryRegionType::VOffset, 0, 0,
                                           field_comment));
        return;
      } else {
        // Its an optional field, so get the default value and interpret and
        // provided an annotation for it.
        if (IsScalar(field->type()->base_type())) {
          default_label += "<defaults to ";
          default_label += IsFloat(field->type()->base_type())
                               ? std::to_string(field->default_real())
                               : std::to_string(field->default_integer());
          default_label += "> (";
        } else {
          default_label += "<null> (";
        }
        default_label +=
            reflection::EnumNameBaseType(field->type()->base_type());
        default_label += ")";
      }
    }
    field_comment.default_value = default_label;

    regions.push_back(MakeBinaryRegion(field_offset, sizeof(uint16_t),
                                       BinaryRegionType::VOffset, 0, 0,
                                       field_comment));

    fields_processed++;
  });

  // Check if we covered all the expectant fields. If not, we need to add them
  // as unknown fields.
  uint16_t expectant_vtable_fields =
      (vtable_size - sizeof(uint16_t) - sizeof(uint16_t)) / sizeof(uint16_t);

  // Prevent a bad binary from declaring a really large vtable_size, that we can
  // not independently verify.
  expectant_vtable_fields = std::min(
      static_cast<uint16_t>(fields_processed * 3), expectant_vtable_fields);

  for (uint16_t id = fields_processed; id < expectant_vtable_fields; ++id) {
    const uint64_t field_offset = offset_start + id * sizeof(uint16_t);

    const auto offset_from_table = ReadScalar<uint16_t>(field_offset);

    BinaryRegionComment field_comment;
    field_comment.type = BinaryRegionCommentType::VTableUnknownFieldOffset;
    field_comment.index = id;

    if (!offset_from_table.has_value()) {
      const uint64_t remaining = RemainingBytes(field_offset);
      SetError(field_comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY, "2");
      regions.push_back(MakeBinaryRegion(field_offset, remaining,
                                         BinaryRegionType::Unknown, remaining,
                                         0, field_comment));
      continue;
    }

    VTable::Entry entry;
    entry.field = nullptr;  // No field to reference.
    entry.offset_from_table = offset_from_table.value();
    fields.insert(std::make_pair(id, entry));

    regions.push_back(MakeBinaryRegion(field_offset, sizeof(uint16_t),
                                       BinaryRegionType::VOffset, 0, 0,
                                       field_comment));
  }

  // If we have never added this vtable before record the Binary section.
  if (vtables.empty()) {
    sections_[vtable_offset] = MakeBinarySection(
        referring_table_name, BinarySectionType::VTable, std::move(regions));
  } else {
    // Add the current table name to the name of the section.
    sections_[vtable_offset].name += ", " + referring_table_name;
  }

  VTable vtable;
  vtable.referring_table = table;
  vtable.fields = std::move(fields);
  vtable.table_size = table_size;
  vtable.vtable_size = vtable_size;

  // Add this vtable to the collection of vtables at this offset.
  vtables.push_back(std::move(vtable));

  // Return the vtable we just added.
  return &vtables.back();
}

void BinaryAnnotator::BuildTable(const uint64_t table_offset,
                                 const BinarySectionType type,
                                 const reflection::Object* const table) {
  if (ContainsSection(table_offset)) {
    return;
  }

  BinaryRegionComment vtable_offset_comment;
  vtable_offset_comment.type = BinaryRegionCommentType::TableVTableOffset;

  const auto vtable_soffset = ReadScalar<int32_t>(table_offset);

  if (!vtable_soffset.has_value()) {
    const uint64_t remaining = RemainingBytes(table_offset);
    SetError(vtable_offset_comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
             "4");

    AddSection(
        table_offset,
        MakeSingleRegionBinarySection(
            table->name()->str(), type,
            MakeBinaryRegion(table_offset, remaining, BinaryRegionType::Unknown,
                             remaining, 0, vtable_offset_comment)));

    // If there aren't enough bytes left to read the vtable offset, there is
    // nothing we can do.
    return;
  }

  // Tables start with the vtable
  const uint64_t vtable_offset = table_offset - vtable_soffset.value();

  if (!IsValidOffset(vtable_offset)) {
    SetError(vtable_offset_comment,
             BinaryRegionStatus::ERROR_OFFSET_OUT_OF_BINARY);

    AddSection(table_offset,
               MakeSingleRegionBinarySection(
                   table->name()->str(), type,
                   MakeBinaryRegion(table_offset, sizeof(int32_t),
                                    BinaryRegionType::SOffset, 0, vtable_offset,
                                    vtable_offset_comment)));

    // There isn't much to do with an invalid vtable offset, as we won't be able
    // to intepret the rest of the table fields.
    return;
  }

  std::vector<BinaryRegion> regions;
  regions.push_back(MakeBinaryRegion(table_offset, sizeof(int32_t),
                                     BinaryRegionType::SOffset, 0,
                                     vtable_offset, vtable_offset_comment));

  // Parse the vtable first so we know what the rest of the fields in the table
  // are.
  const VTable* const vtable =
      GetOrBuildVTable(vtable_offset, table, table_offset);

  if (vtable == nullptr) {
    // There is no valid vtable for this table, so we cannot process the rest of
    // the table entries.
    return;
  }

  // This is the size and length of this table.
  const uint16_t table_size = vtable->table_size;
  uint64_t table_end_offset = table_offset + table_size;

  if (!IsValidOffset(table_end_offset - 1)) {
    // We already validated the table size in BuildVTable, but we have to make
    // sure we don't use a bad value here.
    table_end_offset = binary_length_;
  }

  // We need to iterate over the vtable fields by their offset in the binary,
  // not by their IDs. So copy them over to another vector that we can sort on
  // the offset_from_table property.
  std::vector<VTable::Entry> fields;
  for (const auto& vtable_field : vtable->fields) {
    fields.push_back(vtable_field.second);
  }

  std::stable_sort(fields.begin(), fields.end(),
                   [](const VTable::Entry& a, const VTable::Entry& b) {
                     return a.offset_from_table < b.offset_from_table;
                   });

  // Iterate over all the fields by order of their offset.
  for (size_t i = 0; i < fields.size(); ++i) {
    const reflection::Field* field = fields[i].field;
    const uint16_t offset_from_table = fields[i].offset_from_table;

    if (offset_from_table == 0) {
      // Skip non-present fields.
      continue;
    }

    // The field offsets are relative to the start of the table.
    const uint64_t field_offset = table_offset + offset_from_table;

    if (!IsValidOffset(field_offset)) {
      // The field offset is larger than the binary, nothing we can do.
      continue;
    }

    // We have a vtable entry for a non-existant field, that means its a binary
    // generated by a newer schema than we are currently processing.
    if (field == nullptr) {
      // Calculate the length of this unknown field.
      const uint64_t unknown_field_length =
          // Check if there is another unknown field after this one.
          ((i + 1 < fields.size())
               ? table_offset + fields[i + 1].offset_from_table
               // Otherwise use the known end of the table.
               : table_end_offset) -
          field_offset;

      if (unknown_field_length == 0) {
        continue;
      }

      std::string hint;

      if (unknown_field_length == 4) {
        const auto relative_offset = ReadScalar<uint32_t>(field_offset);
        if (relative_offset.has_value()) {
          // The field is 4 in length, so it could be an offset? Provide a hint.
          hint += "<possibly an offset? Check Loc: +0x";
          hint += ToHex(field_offset + relative_offset.value());
          hint += ">";
        }
      }

      BinaryRegionComment unknown_field_comment;
      unknown_field_comment.type = BinaryRegionCommentType::TableUnknownField;

      if (!IsValidRead(field_offset, unknown_field_length)) {
        const uint64_t remaining = RemainingBytes(field_offset);

        SetError(unknown_field_comment,
                 BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
                 std::to_string(unknown_field_length));

        regions.push_back(MakeBinaryRegion(field_offset, remaining,
                                           BinaryRegionType::Unknown, remaining,
                                           0, unknown_field_comment));
        continue;
      }

      unknown_field_comment.default_value = hint;

      regions.push_back(MakeBinaryRegion(
          field_offset, unknown_field_length, BinaryRegionType::Unknown,
          unknown_field_length, 0, unknown_field_comment));
      continue;
    }

    if (IsScalar(field->type()->base_type())) {
      // These are the raw values store in the table.
      const uint64_t type_size = GetTypeSize(field->type()->base_type());
      const BinaryRegionType region_type =
          GetRegionType(field->type()->base_type());

      BinaryRegionComment scalar_field_comment;
      scalar_field_comment.type = BinaryRegionCommentType::TableField;
      scalar_field_comment.name =
          std::string(field->name()->c_str()) + "` (" +
          reflection::EnumNameBaseType(field->type()->base_type()) + ")";

      if (!IsValidRead(field_offset, type_size)) {
        const uint64_t remaining = RemainingBytes(field_offset);
        SetError(scalar_field_comment,
                 BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
                 std::to_string(type_size));

        regions.push_back(MakeBinaryRegion(field_offset, remaining,
                                           BinaryRegionType::Unknown, remaining,
                                           0, scalar_field_comment));
        continue;
      }

      if (IsUnionType(field)) {
        // This is a type for a union. Validate the value
        const auto enum_value = ReadScalar<uint8_t>(field_offset);

        // This should always have a value, due to the IsValidRead check above.
        if (!IsValidUnionValue(field, enum_value.value())) {
          SetError(scalar_field_comment,
                   BinaryRegionStatus::ERROR_INVALID_UNION_TYPE);

          regions.push_back(MakeBinaryRegion(field_offset, type_size,
                                             region_type, 0, 0,
                                             scalar_field_comment));
          continue;
        }
      }

      regions.push_back(MakeBinaryRegion(field_offset, type_size, region_type,
                                         0, 0, scalar_field_comment));
      continue;
    }

    // Read the offset
    uint64_t offset = 0;
    uint64_t length = sizeof(uint32_t);
    BinaryRegionType region_type = BinaryRegionType::UOffset;

    if (field->offset64()) {
      length = sizeof(uint64_t);
      region_type = BinaryRegionType::UOffset64;
      offset = ReadScalar<uint64_t>(field_offset).value_or(0);
    } else {
      offset = ReadScalar<uint32_t>(field_offset).value_or(0);
    }
    // const auto offset_from_field = ReadScalar<uint32_t>(field_offset);
    uint64_t offset_of_next_item = 0;
    BinaryRegionComment offset_field_comment;
    offset_field_comment.type = BinaryRegionCommentType::TableOffsetField;
    offset_field_comment.name = field->name()->c_str();
    const std::string offset_prefix =
        "offset to field `" + std::string(field->name()->c_str()) + "`";

    // Validate any field that isn't inline (i.e., non-structs).
    if (!IsInlineField(field)) {
      if (offset == 0) {
        const uint64_t remaining = RemainingBytes(field_offset);

        SetError(offset_field_comment,
                 BinaryRegionStatus::ERROR_INCOMPLETE_BINARY, "4");

        regions.push_back(MakeBinaryRegion(field_offset, remaining,
                                           BinaryRegionType::Unknown, remaining,
                                           0, offset_field_comment));
        continue;
      }

      offset_of_next_item = field_offset + offset;

      if (!IsValidOffset(offset_of_next_item)) {
        SetError(offset_field_comment,
                 BinaryRegionStatus::ERROR_OFFSET_OUT_OF_BINARY);
        regions.push_back(MakeBinaryRegion(field_offset, length, region_type, 0,
                                           offset_of_next_item,
                                           offset_field_comment));
        continue;
      }
    }

    switch (field->type()->base_type()) {
      case reflection::BaseType::Obj: {
        const reflection::Object* next_object =
            schema_->objects()->Get(field->type()->index());

        if (next_object->is_struct()) {
          // Structs are stored inline.
          BuildStruct(field_offset, regions, field->name()->c_str(),
                      next_object);
        } else {
          offset_field_comment.default_value = "(table)";

          regions.push_back(MakeBinaryRegion(field_offset, length, region_type,
                                             0, offset_of_next_item,
                                             offset_field_comment));

          BuildTable(offset_of_next_item, BinarySectionType::Table,
                     next_object);
        }
      } break;

      case reflection::BaseType::String: {
        offset_field_comment.default_value = "(string)";
        regions.push_back(MakeBinaryRegion(field_offset, length, region_type, 0,
                                           offset_of_next_item,
                                           offset_field_comment));
        BuildString(offset_of_next_item, table, field);
      } break;

      case reflection::BaseType::Vector: {
        offset_field_comment.default_value = "(vector)";
        regions.push_back(MakeBinaryRegion(field_offset, length, region_type, 0,
                                           offset_of_next_item,
                                           offset_field_comment));
        BuildVector(offset_of_next_item, table, field, table_offset,
                    vtable->fields);
      } break;
      case reflection::BaseType::Vector64: {
        offset_field_comment.default_value = "(vector64)";
        regions.push_back(MakeBinaryRegion(field_offset, length, region_type, 0,
                                           offset_of_next_item,
                                           offset_field_comment));
        BuildVector(offset_of_next_item, table, field, table_offset,
                    vtable->fields);
      } break;

      case reflection::BaseType::Union: {
        const uint64_t union_offset = offset_of_next_item;

        // The union type field is always one less than the union itself.
        const uint16_t union_type_id = field->id() - 1;

        auto vtable_field = vtable->fields.find(union_type_id);
        if (vtable_field == vtable->fields.end()) {
          // TODO(dbaileychess): need to capture this error condition.
          break;
        }
        offset_field_comment.default_value = "(union)";

        const uint64_t type_offset =
            table_offset + vtable_field->second.offset_from_table;

        const auto realized_type = ReadScalar<uint8_t>(type_offset);
        if (!realized_type.has_value()) {
          const uint64_t remaining = RemainingBytes(type_offset);
          SetError(offset_field_comment,
                   BinaryRegionStatus::ERROR_INCOMPLETE_BINARY, "1");
          regions.push_back(MakeBinaryRegion(
              type_offset, remaining, BinaryRegionType::Unknown, remaining, 0,
              offset_field_comment));
          continue;
        }

        if (!IsValidUnionValue(field, realized_type.value())) {
          // We already export an error in the union type field, so just skip
          // building the union itself and it will default to an unreference
          // Binary section.
          continue;
        }

        const std::string enum_type =
            BuildUnion(union_offset, realized_type.value(), field);

        offset_field_comment.default_value =
            "(union of type `" + enum_type + "`)";

        regions.push_back(MakeBinaryRegion(field_offset, length, region_type, 0,
                                           union_offset, offset_field_comment));

      } break;

      default:
        break;
    }
  }

  // Handle the case where there is padding after the last known binary
  // region. Calculate where we left off towards the expected end of the
  // table.
  const uint64_t i = regions.back().offset + regions.back().length + 1;

  if (i < table_end_offset) {
    const uint64_t pad_bytes = table_end_offset - i + 1;

    BinaryRegionComment padding_comment;
    padding_comment.type = BinaryRegionCommentType::Padding;

    regions.push_back(MakeBinaryRegion(i - 1, pad_bytes * sizeof(uint8_t),
                                       BinaryRegionType::Uint8, pad_bytes, 0,
                                       padding_comment));
  }

  AddSection(table_offset,
             MakeBinarySection(table->name()->str(), type, std::move(regions)));
}

uint64_t BinaryAnnotator::BuildStruct(const uint64_t struct_offset,
                                      std::vector<BinaryRegion>& regions,
                                      const std::string referring_field_name,
                                      const reflection::Object* const object) {
  if (!object->is_struct()) {
    return struct_offset;
  }
  uint64_t offset = struct_offset;

  // Loop over all the fields in increasing order
  ForAllFields(object, /*reverse=*/false, [&](const reflection::Field* field) {
    if (IsScalar(field->type()->base_type())) {
      // Structure Field value
      const uint64_t type_size = GetTypeSize(field->type()->base_type());
      const BinaryRegionType region_type =
          GetRegionType(field->type()->base_type());

      BinaryRegionComment comment;
      comment.type = BinaryRegionCommentType::StructField;
      comment.name = referring_field_name + "." + field->name()->str();
      comment.default_value = "of '" + object->name()->str() + "' (" +
                              std::string(reflection::EnumNameBaseType(
                                  field->type()->base_type())) +
                              ")";

      if (!IsValidRead(offset, type_size)) {
        const uint64_t remaining = RemainingBytes(offset);
        SetError(comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
                 std::to_string(type_size));
        regions.push_back(MakeBinaryRegion(offset, remaining,
                                           BinaryRegionType::Unknown, remaining,
                                           0, comment));

        // TODO(dbaileychess): Should I bail out here? This sets offset to the
        // end of the binary. So all other reads in the loop should fail.
        offset += remaining;
        return;
      }

      regions.push_back(
          MakeBinaryRegion(offset, type_size, region_type, 0, 0, comment));
      offset += type_size;
    } else if (field->type()->base_type() == reflection::BaseType::Obj) {
      // Structs are stored inline, even when nested.
      offset = BuildStruct(offset, regions,
                           referring_field_name + "." + field->name()->str(),
                           schema_->objects()->Get(field->type()->index()));
    } else if (field->type()->base_type() == reflection::BaseType::Array) {
      const bool is_scalar = IsScalar(field->type()->element());
      const uint64_t type_size = GetTypeSize(field->type()->element());
      const BinaryRegionType region_type =
          GetRegionType(field->type()->element());

      // Arrays are just repeated structures.
      for (uint16_t i = 0; i < field->type()->fixed_length(); ++i) {
        if (is_scalar) {
          BinaryRegionComment array_comment;
          array_comment.type = BinaryRegionCommentType::ArrayField;
          array_comment.name =
              referring_field_name + "." + field->name()->str();
          array_comment.index = i;
          array_comment.default_value =
              "of '" + object->name()->str() + "' (" +
              std::string(
                  reflection::EnumNameBaseType(field->type()->element())) +
              ")";

          if (!IsValidRead(offset, type_size)) {
            const uint64_t remaining = RemainingBytes(offset);

            SetError(array_comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
                     std::to_string(type_size));

            regions.push_back(MakeBinaryRegion(offset, remaining,
                                               BinaryRegionType::Unknown,
                                               remaining, 0, array_comment));

            // TODO(dbaileychess): Should I bail out here? This sets offset to
            // the end of the binary. So all other reads in the loop should
            // fail.
            offset += remaining;
            break;
          }

          regions.push_back(MakeBinaryRegion(offset, type_size, region_type, 0,
                                             0, array_comment));

          offset += type_size;
        } else {
          // Array of Structs.
          //
          // TODO(dbaileychess): This works, but the comments on the fields lose
          // some context. Need to figure a way how to plumb the nested arrays
          // comments together that isn't too confusing.
          offset =
              BuildStruct(offset, regions,
                          referring_field_name + "." + field->name()->str(),
                          schema_->objects()->Get(field->type()->index()));
        }
      }
    }

    // Insert any padding after this field.
    const uint16_t padding = field->padding();
    if (padding > 0 && IsValidOffset(offset + padding)) {
      BinaryRegionComment padding_comment;
      padding_comment.type = BinaryRegionCommentType::Padding;

      regions.push_back(MakeBinaryRegion(offset, padding,
                                         BinaryRegionType::Uint8, padding, 0,
                                         padding_comment));
      offset += padding;
    }
  });

  return offset;
}

void BinaryAnnotator::BuildString(const uint64_t string_offset,
                                  const reflection::Object* const table,
                                  const reflection::Field* const field) {
  // Check if we have already generated this string section, and this is a
  // shared string instance.
  if (ContainsSection(string_offset)) {
    return;
  }

  std::vector<BinaryRegion> regions;
  const auto string_length = ReadScalar<uint32_t>(string_offset);

  BinaryRegionComment string_length_comment;
  string_length_comment.type = BinaryRegionCommentType::StringLength;

  if (!string_length.has_value()) {
    const uint64_t remaining = RemainingBytes(string_offset);

    SetError(string_length_comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
             "4");

    regions.push_back(MakeBinaryRegion(string_offset, remaining,
                                       BinaryRegionType::Unknown, remaining, 0,
                                       string_length_comment));

  } else {
    const uint32_t string_size = string_length.value();
    const uint64_t string_end =
        string_offset + sizeof(uint32_t) + string_size + sizeof(char);

    if (!IsValidOffset(string_end - 1)) {
      SetError(string_length_comment,
               BinaryRegionStatus::ERROR_LENGTH_TOO_LONG);

      regions.push_back(MakeBinaryRegion(string_offset, sizeof(uint32_t),
                                         BinaryRegionType::Uint32, 0, 0,
                                         string_length_comment));
    } else {
      regions.push_back(MakeBinaryRegion(string_offset, sizeof(uint32_t),
                                         BinaryRegionType::Uint32, 0, 0,
                                         string_length_comment));

      BinaryRegionComment string_comment;
      string_comment.type = BinaryRegionCommentType::StringValue;

      regions.push_back(MakeBinaryRegion(string_offset + sizeof(uint32_t),
                                         string_size, BinaryRegionType::Char,
                                         string_size, 0, string_comment));

      BinaryRegionComment string_terminator_comment;
      string_terminator_comment.type =
          BinaryRegionCommentType::StringTerminator;

      regions.push_back(MakeBinaryRegion(
          string_offset + sizeof(uint32_t) + string_size, sizeof(char),
          BinaryRegionType::Char, 0, 0, string_terminator_comment));
    }
  }

  AddSection(string_offset,
             MakeBinarySection(std::string(table->name()->c_str()) + "." +
                                   field->name()->c_str(),
                               BinarySectionType::String, std::move(regions)));
}

void BinaryAnnotator::BuildVector(
    const uint64_t vector_offset, const reflection::Object* const table,
    const reflection::Field* const field, const uint64_t parent_table_offset,
    const std::map<uint16_t, VTable::Entry> vtable_fields) {
  if (ContainsSection(vector_offset)) {
    return;
  }

  BinaryRegionComment vector_length_comment;
  vector_length_comment.type = BinaryRegionCommentType::VectorLength;

  const bool is_64_bit_vector =
      field->type()->base_type() == reflection::BaseType::Vector64;

  flatbuffers::Optional<uint64_t> vector_length;
  uint32_t vector_length_size_type = 0;
  BinaryRegionType region_type = BinaryRegionType::Uint32;
  BinarySectionType section_type = BinarySectionType::Vector;

  if (is_64_bit_vector) {
    auto v = ReadScalar<uint64_t>(vector_offset);
    if (v.has_value()) {
      vector_length = v.value();
    }
    vector_length_size_type = sizeof(uint64_t);
    region_type = BinaryRegionType::Uint64;
    section_type = BinarySectionType::Vector64;
  } else {
    auto v = ReadScalar<uint32_t>(vector_offset);
    if (v.has_value()) {
      vector_length = v.value();
    }
    vector_length_size_type = sizeof(uint32_t);
    region_type = BinaryRegionType::Uint32;
    section_type = BinarySectionType::Vector;
  }

  if (!vector_length.has_value()) {
    const uint64_t remaining = RemainingBytes(vector_offset);
    SetError(vector_length_comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
             "4");

    AddSection(
        vector_offset,
        MakeSingleRegionBinarySection(
            std::string(table->name()->c_str()) + "." + field->name()->c_str(),
            BinarySectionType::Vector,
            MakeBinaryRegion(vector_offset, remaining,
                             BinaryRegionType::Unknown, remaining, 0,
                             vector_length_comment)));
    return;
  }

  // Validate there are enough bytes left in the binary to process all the
  // items.
  const uint64_t last_item_offset =
      vector_offset + vector_length_size_type +
      vector_length.value() * GetElementSize(field);

  if (!IsValidOffset(last_item_offset - 1)) {
    SetError(vector_length_comment, BinaryRegionStatus::ERROR_LENGTH_TOO_LONG);
    AddSection(
        vector_offset,
        MakeSingleRegionBinarySection(
            std::string(table->name()->c_str()) + "." + field->name()->c_str(),
            BinarySectionType::Vector,
            MakeBinaryRegion(vector_offset, vector_length_size_type,
                             region_type, 0, 0, vector_length_comment)));

    return;
  }

  std::vector<BinaryRegion> regions;

  regions.push_back(MakeBinaryRegion(vector_offset, vector_length_size_type,
                                     region_type, 0, 0, vector_length_comment));
  // Consume the vector length offset.
  uint64_t offset = vector_offset + vector_length_size_type;

  switch (field->type()->element()) {
    case reflection::BaseType::Obj: {
      const reflection::Object* object =
          schema_->objects()->Get(field->type()->index());

      if (object->is_struct()) {
        // Vector of structs
        for (size_t i = 0; i < vector_length.value(); ++i) {
          // Structs are inline to the vector.
          const uint64_t next_offset =
              BuildStruct(offset, regions, "[" + NumToString(i) + "]", object);
          if (next_offset == offset) {
            break;
          }
          offset = next_offset;
        }
      } else {
        // Vector of objects
        for (size_t i = 0; i < vector_length.value(); ++i) {
          BinaryRegionComment vector_object_comment;
          vector_object_comment.type =
              BinaryRegionCommentType::VectorTableValue;
          vector_object_comment.index = i;

          const auto table_relative_offset = ReadScalar<uint32_t>(offset);
          if (!table_relative_offset.has_value()) {
            const uint64_t remaining = RemainingBytes(offset);
            SetError(vector_object_comment,
                     BinaryRegionStatus::ERROR_INCOMPLETE_BINARY, "4");

            regions.push_back(
                MakeBinaryRegion(offset, remaining, BinaryRegionType::Unknown,
                                 remaining, 0, vector_object_comment));
            break;
          }

          // The table offset is relative from the offset location itself.
          const uint64_t table_offset = offset + table_relative_offset.value();

          if (!IsValidOffset(table_offset)) {
            SetError(vector_object_comment,
                     BinaryRegionStatus::ERROR_OFFSET_OUT_OF_BINARY);
            regions.push_back(MakeBinaryRegion(
                offset, sizeof(uint32_t), BinaryRegionType::UOffset, 0,
                table_offset, vector_object_comment));

            offset += sizeof(uint32_t);
            continue;
          }

          if (table_offset == parent_table_offset) {
            SetError(vector_object_comment,
                     BinaryRegionStatus::ERROR_CYCLE_DETECTED);
            // A cycle detected where a table vector field is pointing to
            // itself. This should only happen in corrupted files.
            regions.push_back(MakeBinaryRegion(
                offset, sizeof(uint32_t), BinaryRegionType::UOffset, 0,
                table_offset, vector_object_comment));

            offset += sizeof(uint32_t);
            continue;
          }

          regions.push_back(MakeBinaryRegion(
              offset, sizeof(uint32_t), BinaryRegionType::UOffset, 0,
              table_offset, vector_object_comment));

          // Consume the offset to the table.
          offset += sizeof(uint32_t);

          BuildTable(table_offset, BinarySectionType::Table, object);
        }
      }
    } break;
    case reflection::BaseType::String: {
      // Vector of strings
      for (size_t i = 0; i < vector_length.value(); ++i) {
        BinaryRegionComment vector_object_comment;
        vector_object_comment.type = BinaryRegionCommentType::VectorStringValue;
        vector_object_comment.index = i;

        const auto string_relative_offset = ReadScalar<uint32_t>(offset);
        if (!string_relative_offset.has_value()) {
          const uint64_t remaining = RemainingBytes(offset);

          SetError(vector_object_comment,
                   BinaryRegionStatus::ERROR_INCOMPLETE_BINARY, "4");

          regions.push_back(
              MakeBinaryRegion(offset, remaining, BinaryRegionType::Unknown,
                               remaining, 0, vector_object_comment));
          break;
        }

        // The string offset is relative from the offset location itself.
        const uint64_t string_offset = offset + string_relative_offset.value();

        if (!IsValidOffset(string_offset)) {
          SetError(vector_object_comment,
                   BinaryRegionStatus::ERROR_OFFSET_OUT_OF_BINARY);
          regions.push_back(MakeBinaryRegion(
              offset, sizeof(uint32_t), BinaryRegionType::UOffset, 0,
              string_offset, vector_object_comment));

          offset += sizeof(uint32_t);
          continue;
        }

        regions.push_back(MakeBinaryRegion(
            offset, sizeof(uint32_t), BinaryRegionType::UOffset, 0,
            string_offset, vector_object_comment));

        BuildString(string_offset, table, field);

        offset += sizeof(uint32_t);
      }
    } break;
    case reflection::BaseType::Union: {
      // Vector of unions
      // Unions have both their realized type (uint8_t for now) that are
      // stored separately. These are stored in the field->index() - 1
      // location.
      const uint16_t union_type_vector_id = field->id() - 1;

      auto vtable_entry = vtable_fields.find(union_type_vector_id);
      if (vtable_entry == vtable_fields.end()) {
        // TODO(dbaileychess): need to capture this error condition.
        break;
      }

      const uint64_t union_type_vector_field_offset =
          parent_table_offset + vtable_entry->second.offset_from_table;

      const auto union_type_vector_field_relative_offset =
          ReadScalar<uint16_t>(union_type_vector_field_offset);

      if (!union_type_vector_field_relative_offset.has_value()) {
        const uint64_t remaining = RemainingBytes(offset);
        BinaryRegionComment vector_union_comment;
        vector_union_comment.type = BinaryRegionCommentType::VectorUnionValue;
        SetError(vector_union_comment,
                 BinaryRegionStatus::ERROR_INCOMPLETE_BINARY, "2");

        regions.push_back(MakeBinaryRegion(offset, remaining,
                                           BinaryRegionType::Unknown, remaining,
                                           0, vector_union_comment));

        break;
      }

      // Get the offset to the first type (the + sizeof(uint32_t) is to skip
      // over the vector length which we already know). Validation happens
      // within the loop below.
      const uint64_t union_type_vector_data_offset =
          union_type_vector_field_offset +
          union_type_vector_field_relative_offset.value() + sizeof(uint32_t);

      for (size_t i = 0; i < vector_length.value(); ++i) {
        BinaryRegionComment comment;
        comment.type = BinaryRegionCommentType::VectorUnionValue;
        comment.index = i;

        const auto union_relative_offset = ReadScalar<uint32_t>(offset);
        if (!union_relative_offset.has_value()) {
          const uint64_t remaining = RemainingBytes(offset);

          SetError(comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY, "4");

          regions.push_back(MakeBinaryRegion(offset, remaining,
                                             BinaryRegionType::Unknown,
                                             remaining, 0, comment));

          break;
        }

        // The union offset is relative from the offset location itself.
        const uint64_t union_offset = offset + union_relative_offset.value();

        if (!IsValidOffset(union_offset)) {
          SetError(comment, BinaryRegionStatus::ERROR_OFFSET_OUT_OF_BINARY);

          regions.push_back(MakeBinaryRegion(offset, sizeof(uint32_t),
                                             BinaryRegionType::UOffset, 0,
                                             union_offset, comment));
          continue;
        }

        const auto realized_type =
            ReadScalar<uint8_t>(union_type_vector_data_offset + i);

        if (!realized_type.has_value()) {
          SetError(comment, BinaryRegionStatus::ERROR_INCOMPLETE_BINARY, "1");
          regions.push_back(MakeBinaryRegion(
              offset, 0, BinaryRegionType::Unknown, 0, 0, comment));
          continue;
        }

        if (!IsValidUnionValue(vtable_entry->second.field->type()->index(),
                               realized_type.value())) {
          // We already export an error in the union type field, so just skip
          // building the union itself and it will default to an unreference
          // Binary section.
          offset += sizeof(uint32_t);
          continue;
        }

        const std::string enum_type =
            BuildUnion(union_offset, realized_type.value(), field);

        comment.default_value = "(`" + enum_type + "`)";
        regions.push_back(MakeBinaryRegion(offset, sizeof(uint32_t),
                                           BinaryRegionType::UOffset, 0,
                                           union_offset, comment));

        offset += sizeof(uint32_t);
      }
    } break;
    default: {
      if (IsScalar(field->type()->element())) {
        const BinaryRegionType binary_region_type =
            GetRegionType(field->type()->element());

        const uint64_t type_size = GetTypeSize(field->type()->element());

        // TODO(dbaileychess): It might be nicer to user the
        // BinaryRegion.array_length field to indicate this.
        for (size_t i = 0; i < vector_length.value(); ++i) {
          BinaryRegionComment vector_scalar_comment;
          vector_scalar_comment.type = BinaryRegionCommentType::VectorValue;
          vector_scalar_comment.index = i;

          if (!IsValidRead(offset, type_size)) {
            const uint64_t remaining = RemainingBytes(offset);

            SetError(vector_scalar_comment,
                     BinaryRegionStatus::ERROR_INCOMPLETE_BINARY,
                     std::to_string(type_size));

            regions.push_back(
                MakeBinaryRegion(offset, remaining, BinaryRegionType::Unknown,
                                 remaining, 0, vector_scalar_comment));
            break;
          }

          if (IsUnionType(field->type()->element())) {
            // This is a type for a union. Validate the value
            const auto enum_value = ReadScalar<uint8_t>(offset);

            // This should always have a value, due to the IsValidRead check
            // above.
            if (!IsValidUnionValue(field->type()->index(),
                                   enum_value.value())) {
              SetError(vector_scalar_comment,
                       BinaryRegionStatus::ERROR_INVALID_UNION_TYPE);
              regions.push_back(MakeBinaryRegion(offset, type_size,
                                                 binary_region_type, 0, 0,
                                                 vector_scalar_comment));
              offset += type_size;
              continue;
            }
          }

          regions.push_back(MakeBinaryRegion(offset, type_size,
                                             binary_region_type, 0, 0,
                                             vector_scalar_comment));
          offset += type_size;
        }
      }
    } break;
  }
  AddSection(vector_offset,
             MakeBinarySection(std::string(table->name()->c_str()) + "." +
                                   field->name()->c_str(),
                               section_type, std::move(regions)));
}

std::string BinaryAnnotator::BuildUnion(const uint64_t union_offset,
                                        const uint8_t realized_type,
                                        const reflection::Field* const field) {
  const reflection::Enum* next_enum =
      schema_->enums()->Get(field->type()->index());

  const reflection::EnumVal* enum_val = next_enum->values()->Get(realized_type);

  if (ContainsSection(union_offset)) {
    return enum_val->name()->c_str();
  }

  const reflection::Type* union_type = enum_val->union_type();

  if (union_type->base_type() == reflection::BaseType::Obj) {
    const reflection::Object* object =
        schema_->objects()->Get(union_type->index());

    if (object->is_struct()) {
      // Union of vectors point to a new Binary section
      std::vector<BinaryRegion> regions;

      BuildStruct(union_offset, regions, field->name()->c_str(), object);

      AddSection(
          union_offset,
          MakeBinarySection(std::string(object->name()->c_str()) + "." +
                                field->name()->c_str(),
                            BinarySectionType::Union, std::move(regions)));
    } else {
      BuildTable(union_offset, BinarySectionType::Table, object);
    }
  }
  // TODO(dbaileychess): handle the other union types.

  return enum_val->name()->c_str();
}

void BinaryAnnotator::FixMissingRegions() {
  std::vector<BinaryRegion> regions_to_insert;
  for (auto& current_section : sections_) {
    BinarySection& section = current_section.second;
    if (section.regions.empty()) {
      // TODO(dbaileychess): is this possible?
      continue;
    }

    uint64_t offset = section.regions[0].offset + section.regions[0].length;
    for (size_t i = 1; i < section.regions.size(); ++i) {
      BinaryRegion& region = section.regions[i];

      const uint64_t next_offset = region.offset;
      if (!IsValidOffset(next_offset)) {
        // TODO(dbaileychess): figure out how we get into this situation.
        continue;
      }

      if (offset < next_offset) {
        const uint64_t padding_bytes = next_offset - offset;

        BinaryRegionComment comment;
        comment.type = BinaryRegionCommentType::Padding;

        if (IsNonZeroRegion(offset, padding_bytes, binary_)) {
          SetError(comment, BinaryRegionStatus::WARN_NO_REFERENCES);
          regions_to_insert.push_back(
              MakeBinaryRegion(offset, padding_bytes, BinaryRegionType::Unknown,
                               padding_bytes, 0, comment));
        } else {
          regions_to_insert.push_back(
              MakeBinaryRegion(offset, padding_bytes, BinaryRegionType::Uint8,
                               padding_bytes, 0, comment));
        }
      }
      offset = next_offset + region.length;
    }

    if (!regions_to_insert.empty()) {
      section.regions.insert(section.regions.end(), regions_to_insert.begin(),
                             regions_to_insert.end());
      std::stable_sort(section.regions.begin(), section.regions.end(),
                       BinaryRegionSort);
      regions_to_insert.clear();
    }
  }
}

void BinaryAnnotator::FixMissingSections() {
  uint64_t offset = 0;

  std::vector<BinarySection> sections_to_insert;

  for (auto& current_section : sections_) {
    BinarySection& section = current_section.second;
    const uint64_t section_start_offset = current_section.first;
    const uint64_t section_end_offset =
        section.regions.back().offset + section.regions.back().length;

    if (offset < section_start_offset) {
      // We are at an offset that is less then the current section.
      const uint64_t pad_bytes = section_start_offset - offset + 1;

      sections_to_insert.push_back(
          GenerateMissingSection(offset - 1, pad_bytes, binary_));
    }
    offset = section_end_offset + 1;
  }

  // Handle the case where there are still bytes left in the binary that are
  // unaccounted for.
  if (offset < binary_length_) {
    const uint64_t pad_bytes = binary_length_ - offset + 1;
    sections_to_insert.push_back(
        GenerateMissingSection(offset - 1, pad_bytes, binary_));
  }

  for (const BinarySection& section_to_insert : sections_to_insert) {
    AddSection(section_to_insert.regions[0].offset, section_to_insert);
  }
}

bool BinaryAnnotator::ContainsSection(const uint64_t offset) {
  auto it = sections_.lower_bound(offset);
  // If the section is found, check that it is exactly equal its offset.
  if (it != sections_.end() && it->first == offset) {
    return true;
  }

  // If this was the first section, there are no other previous sections to
  // check.
  if (it == sections_.begin()) {
    return false;
  }

  // Go back one section.
  --it;

  // And check that if the offset is covered by the section.
  return offset >= it->first && offset < it->second.regions.back().offset +
                                             it->second.regions.back().length;
}

const reflection::Object* BinaryAnnotator::RootTable() const {
  if (!root_table_.empty()) {
    return schema_->objects()->LookupByKey(root_table_);
  }
  return schema_->root_table();
}

}  // namespace flatbuffers
