/*
 * Copyright 2021 Google Inc. All rights reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#ifndef FLATBUFFERS_FLATBUFFER_BUILDER_H_
#define FLATBUFFERS_FLATBUFFER_BUILDER_H_

#include <algorithm>
#include <cstdint>
#include <functional>
#include <initializer_list>
#include <type_traits>

#include "flatbuffers/allocator.h"
#include "flatbuffers/array.h"
#include "flatbuffers/base.h"
#include "flatbuffers/buffer.h"
#include "flatbuffers/buffer_ref.h"
#include "flatbuffers/default_allocator.h"
#include "flatbuffers/detached_buffer.h"
#include "flatbuffers/stl_emulation.h"
#include "flatbuffers/string.h"
#include "flatbuffers/struct.h"
#include "flatbuffers/table.h"
#include "flatbuffers/vector.h"
#include "flatbuffers/vector_downward.h"
#include "flatbuffers/verifier.h"

namespace flatbuffers {

// Converts a Field ID to a virtual table offset.
inline voffset_t FieldIndexToOffset(voffset_t field_id) {
  // Should correspond to what EndTable() below builds up.
  const voffset_t fixed_fields =
      2 * sizeof(voffset_t);  // Vtable size and Object Size.
  size_t offset = fixed_fields + field_id * sizeof(voffset_t);
  FLATBUFFERS_ASSERT(offset < std::numeric_limits<voffset_t>::max());
  return static_cast<voffset_t>(offset);
}

template <typename T, typename Alloc = std::allocator<T>>
const T* data(const std::vector<T, Alloc>& v) {
  // Eventually the returned pointer gets passed down to memcpy, so
  // we need it to be non-null to avoid undefined behavior.
  static uint8_t t;
  return v.empty() ? reinterpret_cast<const T*>(&t) : &v.front();
}
template <typename T, typename Alloc = std::allocator<T>>
T* data(std::vector<T, Alloc>& v) {
  // Eventually the returned pointer gets passed down to memcpy, so
  // we need it to be non-null to avoid undefined behavior.
  static uint8_t t;
  return v.empty() ? reinterpret_cast<T*>(&t) : &v.front();
}

/// @addtogroup flatbuffers_cpp_api
/// @{
/// @class FlatBufferBuilder
/// @brief Helper class to hold data needed in creation of a FlatBuffer.
/// To serialize data, you typically call one of the `Create*()` functions in
/// the generated code, which in turn call a sequence of `StartTable`/
/// `PushElement`/`AddElement`/`EndTable`, or the builtin `CreateString`/
/// `CreateVector` functions. Do this is depth-first order to build up a tree to
/// the root. `Finish()` wraps up the buffer ready for transport.
template <bool Is64Aware = false>
class FlatBufferBuilderImpl {
 public:
  // This switches the size type of the builder, based on if its 64-bit aware
  // (uoffset64_t) or not (uoffset_t).
  typedef
      typename std::conditional<Is64Aware, uoffset64_t, uoffset_t>::type SizeT;

  /// @brief Default constructor for FlatBufferBuilder.
  /// @param[in] initial_size The initial size of the buffer, in bytes. Defaults
  /// to `1024`.
  /// @param[in] allocator An `Allocator` to use. If null will use
  /// `DefaultAllocator`.
  /// @param[in] own_allocator Whether the builder/vector should own the
  /// allocator. Defaults to / `false`.
  /// @param[in] buffer_minalign Force the buffer to be aligned to the given
  /// minimum alignment upon reallocation. Only needed if you intend to store
  /// types with custom alignment AND you wish to read the buffer in-place
  /// directly after creation.
  explicit FlatBufferBuilderImpl(
      size_t initial_size = 1024, Allocator* allocator = nullptr,
      bool own_allocator = false,
      size_t buffer_minalign = AlignOf<largest_scalar_t>())
      : buf_(initial_size, allocator, own_allocator, buffer_minalign,
             static_cast<SizeT>(Is64Aware ? FLATBUFFERS_MAX_64_BUFFER_SIZE
                                          : FLATBUFFERS_MAX_BUFFER_SIZE)),
        num_field_loc(0),
        max_voffset_(0),
        length_of_64_bit_region_(0),
        nested(false),
        finished(false),
        minalign_(1),
        force_defaults_(false),
        dedup_vtables_(true),
        string_pool(nullptr) {
    EndianCheck();
  }

  /// @brief Move constructor for FlatBufferBuilder.
  FlatBufferBuilderImpl(FlatBufferBuilderImpl&& other) noexcept
      : buf_(1024, nullptr, false, AlignOf<largest_scalar_t>(),
             static_cast<SizeT>(Is64Aware ? FLATBUFFERS_MAX_64_BUFFER_SIZE
                                          : FLATBUFFERS_MAX_BUFFER_SIZE)),
        num_field_loc(0),
        max_voffset_(0),
        length_of_64_bit_region_(0),
        nested(false),
        finished(false),
        minalign_(1),
        force_defaults_(false),
        dedup_vtables_(true),
        string_pool(nullptr) {
    EndianCheck();
    // Default construct and swap idiom.
    // Lack of delegating constructors in vs2010 makes it more verbose than
    // needed.
    Swap(other);
  }

  /// @brief Move assignment operator for FlatBufferBuilder.
  FlatBufferBuilderImpl& operator=(FlatBufferBuilderImpl&& other) noexcept {
    // Move construct a temporary and swap idiom
    FlatBufferBuilderImpl temp(std::move(other));
    Swap(temp);
    return *this;
  }

  void Swap(FlatBufferBuilderImpl& other) {
    using std::swap;
    buf_.swap(other.buf_);
    swap(num_field_loc, other.num_field_loc);
    swap(max_voffset_, other.max_voffset_);
    swap(length_of_64_bit_region_, other.length_of_64_bit_region_);
    swap(nested, other.nested);
    swap(finished, other.finished);
    swap(minalign_, other.minalign_);
    swap(force_defaults_, other.force_defaults_);
    swap(dedup_vtables_, other.dedup_vtables_);
    swap(string_pool, other.string_pool);
  }

  ~FlatBufferBuilderImpl() {
    if (string_pool) delete string_pool;
  }

  void Reset() {
    Clear();       // clear builder state
    buf_.reset();  // deallocate buffer
  }

  /// @brief Reset all the state in this FlatBufferBuilder so it can be reused
  /// to construct another buffer.
  void Clear() {
    ClearOffsets();
    buf_.clear();
    nested = false;
    finished = false;
    minalign_ = 1;
    length_of_64_bit_region_ = 0;
    if (string_pool) string_pool->clear();
  }

  /// @brief The current size of the serialized buffer, counting from the end.
  /// @return Returns an `SizeT` with the current size of the buffer.
  SizeT GetSize() const { return buf_.size(); }

  /// @brief The current size of the serialized buffer relative to the end of
  /// the 32-bit region.
  /// @return Returns an `uoffset_t` with the current size of the buffer.
  template <bool is_64 = Is64Aware>
  // Only enable this method for the 64-bit builder, as only that builder is
  // concerned with the 32/64-bit boundary, and should be the one to bare any
  // run time costs.
  typename std::enable_if<is_64, uoffset_t>::type GetSizeRelative32BitRegion()
      const {
    //[32-bit region][64-bit region]
    //         [XXXXXXXXXXXXXXXXXXX] GetSize()
    //               [YYYYYYYYYYYYY] length_of_64_bit_region_
    //         [ZZZZ]                return size
    return static_cast<uoffset_t>(GetSize() - length_of_64_bit_region_);
  }

  template <bool is_64 = Is64Aware>
  // Only enable this method for the 32-bit builder.
  typename std::enable_if<!is_64, uoffset_t>::type GetSizeRelative32BitRegion()
      const {
    return static_cast<uoffset_t>(GetSize());
  }

  /// @brief Get the serialized buffer (after you call `Finish()`).
  /// @return Returns an `uint8_t` pointer to the FlatBuffer data inside the
  /// buffer.
  uint8_t* GetBufferPointer() const {
    Finished();
    return buf_.data();
  }

  /// @brief Get the serialized buffer (after you call `Finish()`) as a span.
  /// @return Returns a constructed flatbuffers::span that is a view over the
  /// FlatBuffer data inside the buffer.
  flatbuffers::span<uint8_t> GetBufferSpan() const {
    Finished();
    return flatbuffers::span<uint8_t>(buf_.data(), buf_.size());
  }

  /// @brief Get a pointer to an unfinished buffer.
  /// @return Returns a `uint8_t` pointer to the unfinished buffer.
  uint8_t* GetCurrentBufferPointer() const { return buf_.data(); }

  /// @brief Get the released DetachedBuffer.
  /// @return A `DetachedBuffer` that owns the buffer and its allocator.
  DetachedBuffer Release() {
    Finished();
    DetachedBuffer buffer = buf_.release();
    Clear();
    return buffer;
  }

  /// @brief Get the released pointer to the serialized buffer.
  /// @param size The size of the memory block containing
  /// the serialized `FlatBuffer`.
  /// @param offset The offset from the released pointer where the finished
  /// `FlatBuffer` starts.
  /// @return A raw pointer to the start of the memory block containing
  /// the serialized `FlatBuffer`.
  /// @remark If the allocator is owned, it gets deleted when the destructor is
  /// called.
  uint8_t* ReleaseRaw(size_t& size, size_t& offset) {
    Finished();
    uint8_t* raw = buf_.release_raw(size, offset);
    Clear();
    return raw;
  }

  /// @brief get the minimum alignment this buffer needs to be accessed
  /// properly. This is only known once all elements have been written (after
  /// you call Finish()). You can use this information if you need to embed
  /// a FlatBuffer in some other buffer, such that you can later read it
  /// without first having to copy it into its own buffer.
  size_t GetBufferMinAlignment() const {
    Finished();
    return minalign_;
  }

  /// @cond FLATBUFFERS_INTERNAL
  void Finished() const {
    // If you get this assert, you're attempting to get access a buffer
    // which hasn't been finished yet. Be sure to call
    // FlatBufferBuilder::Finish with your root table.
    // If you really need to access an unfinished buffer, call
    // GetCurrentBufferPointer instead.
    FLATBUFFERS_ASSERT(finished);
  }
  /// @endcond

  /// @brief In order to save space, fields that are set to their default value
  /// don't get serialized into the buffer.
  /// @param[in] fd When set to `true`, always serializes default values that
  /// are set. Optional fields which are not set explicitly, will still not be
  /// serialized.
  void ForceDefaults(bool fd) { force_defaults_ = fd; }

  /// @brief By default vtables are deduped in order to save space.
  /// @param[in] dedup When set to `true`, dedup vtables.
  void DedupVtables(bool dedup) { dedup_vtables_ = dedup; }

  /// @cond FLATBUFFERS_INTERNAL
  void Pad(size_t num_bytes) { buf_.fill(num_bytes); }

  void TrackMinAlign(size_t elem_size) {
    if (elem_size > minalign_) minalign_ = elem_size;
  }

  void Align(size_t elem_size) {
    TrackMinAlign(elem_size);
    buf_.fill(PaddingBytes(buf_.size(), elem_size));
  }

  void PushFlatBuffer(const uint8_t* bytes, size_t size) {
    PushBytes(bytes, size);
    finished = true;
  }

  void PushBytes(const uint8_t* bytes, size_t size) { buf_.push(bytes, size); }

  void PopBytes(size_t amount) { buf_.pop(amount); }

  template <typename T>
  void AssertScalarT() {
    // The code assumes power of 2 sizes and endian-swap-ability.
    static_assert(flatbuffers::is_scalar<T>::value, "T must be a scalar type");
  }

  // Write a single aligned scalar to the buffer
  template <typename T, typename ReturnT = uoffset_t>
  ReturnT PushElement(T element) {
    AssertScalarT<T>();
    Align(sizeof(T));
    buf_.push_small(EndianScalar(element));
    return CalculateOffset<ReturnT>();
  }

  template <typename T, template <typename> class OffsetT = Offset>
  uoffset_t PushElement(OffsetT<T> off) {
    // Special case for offsets: see ReferTo below.
    return PushElement(ReferTo(off.o));
  }

  // When writing fields, we track where they are, so we can create correct
  // vtables later.
  void TrackField(voffset_t field, uoffset_t off) {
    FieldLoc fl = {off, field};
    buf_.scratch_push_small(fl);
    num_field_loc++;
    if (field > max_voffset_) {
      max_voffset_ = field;
    }
  }

  // Like PushElement, but additionally tracks the field this represents.
  template <typename T>
  void AddElement(voffset_t field, T e, T def) {
    // We don't serialize values equal to the default.
    if (IsTheSameAs(e, def) && !force_defaults_) return;
    TrackField(field, PushElement(e));
  }

  template <typename T>
  void AddElement(voffset_t field, T e) {
    TrackField(field, PushElement(e));
  }

  template <typename T>
  void AddOffset(voffset_t field, Offset<T> off) {
    if (off.IsNull()) return;  // Don't store.
    AddElement(field, ReferTo(off.o), static_cast<uoffset_t>(0));
  }

  template <typename T>
  void AddOffset(voffset_t field, Offset64<T> off) {
    if (off.IsNull()) return;  // Don't store.
    AddElement(field, ReferTo(off.o), static_cast<uoffset64_t>(0));
  }

  template <typename T>
  void AddStruct(voffset_t field, const T* structptr) {
    if (!structptr) return;  // Default, don't store.
    Align(AlignOf<T>());
    buf_.push_small(*structptr);
    TrackField(field, CalculateOffset<uoffset_t>());
  }

  void AddStructOffset(voffset_t field, uoffset_t off) {
    TrackField(field, off);
  }

  // Offsets initially are relative to the end of the buffer (downwards).
  // This function converts them to be relative to the current location
  // in the buffer (when stored here), pointing upwards.
  uoffset_t ReferTo(uoffset_t off) {
    // Align to ensure GetSizeRelative32BitRegion() below is correct.
    Align(sizeof(uoffset_t));
    // 32-bit offsets are relative to the tail of the 32-bit region of the
    // buffer. For most cases (without 64-bit entities) this is equivalent to
    // size of the whole buffer (e.g. GetSize())
    return ReferTo(off, GetSizeRelative32BitRegion());
  }

  uoffset64_t ReferTo(uoffset64_t off) {
    // Align to ensure GetSize() below is correct.
    Align(sizeof(uoffset64_t));
    // 64-bit offsets are relative to tail of the whole buffer
    return ReferTo(off, GetSize());
  }

  template <typename T, typename T2>
  T ReferTo(const T off, const T2 size) {
    FLATBUFFERS_ASSERT(off && off <= size);
    return size - off + static_cast<T>(sizeof(T));
  }

  template <typename T>
  T ReferTo(const T off, const T size) {
    FLATBUFFERS_ASSERT(off && off <= size);
    return size - off + static_cast<T>(sizeof(T));
  }

  void NotNested() {
    // If you hit this, you're trying to construct a Table/Vector/String
    // during the construction of its parent table (between the MyTableBuilder
    // and table.Finish().
    // Move the creation of these sub-objects to above the MyTableBuilder to
    // not get this assert.
    // Ignoring this assert may appear to work in simple cases, but the reason
    // it is here is that storing objects in-line may cause vtable offsets
    // to not fit anymore. It also leads to vtable duplication.
    FLATBUFFERS_ASSERT(!nested);
    // If you hit this, fields were added outside the scope of a table.
    FLATBUFFERS_ASSERT(!num_field_loc);
  }

  // From generated code (or from the parser), we call StartTable/EndTable
  // with a sequence of AddElement calls in between.
  uoffset_t StartTable() {
    NotNested();
    nested = true;
    return GetSizeRelative32BitRegion();
  }

  // This finishes one serialized object by generating the vtable if it's a
  // table, comparing it against existing vtables, and writing the
  // resulting vtable offset.
  uoffset_t EndTable(uoffset_t start) {
    // If you get this assert, a corresponding StartTable wasn't called.
    FLATBUFFERS_ASSERT(nested);
    // Write the vtable offset, which is the start of any Table.
    // We fill its value later.
    // This is relative to the end of the 32-bit region.
    const uoffset_t vtable_offset_loc =
        static_cast<uoffset_t>(PushElement<soffset_t>(0));
    // Write a vtable, which consists entirely of voffset_t elements.
    // It starts with the number of offsets, followed by a type id, followed
    // by the offsets themselves. In reverse:
    // Include space for the last offset and ensure empty tables have a
    // minimum size.
    max_voffset_ =
        (std::max)(static_cast<voffset_t>(max_voffset_ + sizeof(voffset_t)),
                   FieldIndexToOffset(0));
    buf_.fill_big(max_voffset_);
    const uoffset_t table_object_size = vtable_offset_loc - start;
    // Vtable use 16bit offsets.
    FLATBUFFERS_ASSERT(table_object_size < 0x10000);
    WriteScalar<voffset_t>(buf_.data() + sizeof(voffset_t),
                           static_cast<voffset_t>(table_object_size));
    WriteScalar<voffset_t>(buf_.data(), max_voffset_);
    // Write the offsets into the table
    for (auto it = buf_.scratch_end() - num_field_loc * sizeof(FieldLoc);
         it < buf_.scratch_end(); it += sizeof(FieldLoc)) {
      auto field_location = reinterpret_cast<FieldLoc*>(it);
      const voffset_t pos =
          static_cast<voffset_t>(vtable_offset_loc - field_location->off);
      // If this asserts, it means you've set a field twice.
      FLATBUFFERS_ASSERT(
          !ReadScalar<voffset_t>(buf_.data() + field_location->id));
      WriteScalar<voffset_t>(buf_.data() + field_location->id, pos);
    }
    ClearOffsets();
    auto vt1 = reinterpret_cast<voffset_t*>(buf_.data());
    auto vt1_size = ReadScalar<voffset_t>(vt1);
    auto vt_use = GetSizeRelative32BitRegion();
    // See if we already have generated a vtable with this exact same
    // layout before. If so, make it point to the old one, remove this one.
    if (dedup_vtables_) {
      for (auto it = buf_.scratch_data(); it < buf_.scratch_end();
           it += sizeof(uoffset_t)) {
        auto vt_offset_ptr = reinterpret_cast<uoffset_t*>(it);
        auto vt2 = reinterpret_cast<voffset_t*>(
            buf_.data_at(*vt_offset_ptr + length_of_64_bit_region_));
        auto vt2_size = ReadScalar<voffset_t>(vt2);
        if (vt1_size != vt2_size || 0 != memcmp(vt2, vt1, vt1_size)) continue;
        vt_use = *vt_offset_ptr;
        buf_.pop(GetSizeRelative32BitRegion() - vtable_offset_loc);
        break;
      }
    }
    // If this is a new vtable, remember it.
    if (vt_use == GetSizeRelative32BitRegion()) {
      buf_.scratch_push_small(vt_use);
    }
    // Fill the vtable offset we created above.
    // The offset points from the beginning of the object to where the vtable is
    // stored.
    // Offsets default direction is downward in memory for future format
    // flexibility (storing all vtables at the start of the file).
    WriteScalar(buf_.data_at(vtable_offset_loc + length_of_64_bit_region_),
                static_cast<soffset_t>(vt_use) -
                    static_cast<soffset_t>(vtable_offset_loc));
    nested = false;
    return vtable_offset_loc;
  }

  FLATBUFFERS_ATTRIBUTE([[deprecated("call the version above instead")]])
  uoffset_t EndTable(uoffset_t start, voffset_t /*numfields*/) {
    return EndTable(start);
  }

  // This checks a required field has been set in a given table that has
  // just been constructed.
  template <typename T>
  void Required(Offset<T> table, voffset_t field) {
    auto table_ptr = reinterpret_cast<const Table*>(buf_.data_at(table.o));
    bool ok = table_ptr->GetOptionalFieldOffset(field) != 0;
    // If this fails, the caller will show what field needs to be set.
    FLATBUFFERS_ASSERT(ok);
    (void)ok;
  }

  uoffset_t StartStruct(size_t alignment) {
    Align(alignment);
    return GetSizeRelative32BitRegion();
  }

  uoffset_t EndStruct() { return GetSizeRelative32BitRegion(); }

  void ClearOffsets() {
    buf_.scratch_pop(num_field_loc * sizeof(FieldLoc));
    num_field_loc = 0;
    max_voffset_ = 0;
  }

  // Aligns such that when "len" bytes are written, an object can be written
  // after it (forward in the buffer) with "alignment" without padding.
  void PreAlign(size_t len, size_t alignment) {
    if (len == 0) return;
    TrackMinAlign(alignment);
    buf_.fill(PaddingBytes(GetSize() + len, alignment));
  }

  // Aligns such than when "len" bytes are written, an object of type `AlignT`
  // can be written after it (forward in the buffer) without padding.
  template <typename AlignT>
  void PreAlign(size_t len) {
    AssertScalarT<AlignT>();
    PreAlign(len, AlignOf<AlignT>());
  }
  /// @endcond

  /// @brief Store a string in the buffer, which can contain any binary data.
  /// @param[in] str A const char pointer to the data to be stored as a string.
  /// @param[in] len The number of bytes that should be stored from `str`.
  /// @return Returns the offset in the buffer where the string starts.
  template <template <typename> class OffsetT = Offset>
  OffsetT<String> CreateString(const char* str, size_t len) {
    CreateStringImpl(str, len);
    return OffsetT<String>(
        CalculateOffset<typename OffsetT<String>::offset_type>());
  }

  /// @brief Store a string in the buffer, which is null-terminated.
  /// @param[in] str A const char pointer to a C-string to add to the buffer.
  /// @return Returns the offset in the buffer where the string starts.
  template <template <typename> class OffsetT = Offset>
  OffsetT<String> CreateString(const char* str) {
    return CreateString<OffsetT>(str, strlen(str));
  }

  /// @brief Store a string in the buffer, which is null-terminated.
  /// @param[in] str A char pointer to a C-string to add to the buffer.
  /// @return Returns the offset in the buffer where the string starts.
  template <template <typename> class OffsetT = Offset>
  OffsetT<String> CreateString(char* str) {
    return CreateString<OffsetT>(str, strlen(str));
  }

  /// @brief Store a string in the buffer, which can contain any binary data.
  /// @param[in] str A const reference to a std::string to store in the buffer.
  /// @return Returns the offset in the buffer where the string starts.
  template <template <typename> class OffsetT = Offset>
  OffsetT<String> CreateString(const std::string& str) {
    return CreateString<OffsetT>(str.c_str(), str.length());
  }

  // clang-format off
  #ifdef FLATBUFFERS_HAS_STRING_VIEW
  /// @brief Store a string in the buffer, which can contain any binary data.
  /// @param[in] str A const string_view to copy in to the buffer.
  /// @return Returns the offset in the buffer where the string starts.
  template<template <typename> class OffsetT = Offset>
  OffsetT<String>CreateString(flatbuffers::string_view str) {
    return CreateString<OffsetT>(str.data(), str.size());
  }
  #endif // FLATBUFFERS_HAS_STRING_VIEW
  // clang-format on

  /// @brief Store a string in the buffer, which can contain any binary data.
  /// @param[in] str A const pointer to a `String` struct to add to the buffer.
  /// @return Returns the offset in the buffer where the string starts
  template <template <typename> class OffsetT = Offset>
  OffsetT<String> CreateString(const String* str) {
    return str ? CreateString<OffsetT>(str->c_str(), str->size()) : 0;
  }

  /// @brief Store a string in the buffer, which can contain any binary data.
  /// @param[in] str A const reference to a std::string like type with support
  /// of T::data() and T::length() to store in the buffer.
  /// @return Returns the offset in the buffer where the string starts.
  template <template <typename> class OffsetT = Offset,
            // No need to explicitly declare the T type, let the compiler deduce
            // it.
            int&... ExplicitArgumentBarrier, typename T>
  OffsetT<String> CreateString(const T& str) {
    return CreateString<OffsetT>(str.data(), str.length());
  }

  /// @brief Store a string in the buffer, which can contain any binary data.
  /// If a string with this exact contents has already been serialized before,
  /// instead simply returns the offset of the existing string. This uses a map
  /// stored on the heap, but only stores the numerical offsets.
  /// @param[in] str A const char pointer to the data to be stored as a string.
  /// @param[in] len The number of bytes that should be stored from `str`.
  /// @return Returns the offset in the buffer where the string starts.
  Offset<String> CreateSharedString(const char* str, size_t len) {
    FLATBUFFERS_ASSERT(FLATBUFFERS_GENERAL_HEAP_ALLOC_OK);
    if (!string_pool) {
      string_pool = new StringOffsetMap(StringOffsetCompare(buf_));
    }

    const size_t size_before_string = buf_.size();
    // Must first serialize the string, since the set is all offsets into
    // buffer.
    const Offset<String> off = CreateString<Offset>(str, len);
    auto it = string_pool->find(off);
    // If it exists we reuse existing serialized data!
    if (it != string_pool->end()) {
      // We can remove the string we serialized.
      buf_.pop(buf_.size() - size_before_string);
      return *it;
    }
    // Record this string for future use.
    string_pool->insert(off);
    return off;
  }

#ifdef FLATBUFFERS_HAS_STRING_VIEW
  /// @brief Store a string in the buffer, which can contain any binary data.
  /// If a string with this exact contents has already been serialized before,
  /// instead simply returns the offset of the existing string. This uses a map
  /// stored on the heap, but only stores the numerical offsets.
  /// @param[in] str A const std::string_view to store in the buffer.
  /// @return Returns the offset in the buffer where the string starts
  Offset<String> CreateSharedString(const flatbuffers::string_view str) {
    return CreateSharedString(str.data(), str.size());
  }
#else
  /// @brief Store a string in the buffer, which null-terminated.
  /// If a string with this exact contents has already been serialized before,
  /// instead simply returns the offset of the existing string. This uses a map
  /// stored on the heap, but only stores the numerical offsets.
  /// @param[in] str A const char pointer to a C-string to add to the buffer.
  /// @return Returns the offset in the buffer where the string starts.
  Offset<String> CreateSharedString(const char* str) {
    return CreateSharedString(str, strlen(str));
  }

  /// @brief Store a string in the buffer, which can contain any binary data.
  /// If a string with this exact contents has already been serialized before,
  /// instead simply returns the offset of the existing string. This uses a map
  /// stored on the heap, but only stores the numerical offsets.
  /// @param[in] str A const reference to a std::string to store in the buffer.
  /// @return Returns the offset in the buffer where the string starts.
  Offset<String> CreateSharedString(const std::string& str) {
    return CreateSharedString(str.c_str(), str.length());
  }
#endif

  /// @brief Store a string in the buffer, which can contain any binary data.
  /// If a string with this exact contents has already been serialized before,
  /// instead simply returns the offset of the existing string. This uses a map
  /// stored on the heap, but only stores the numerical offsets.
  /// @param[in] str A const pointer to a `String` struct to add to the buffer.
  /// @return Returns the offset in the buffer where the string starts
  Offset<String> CreateSharedString(const String* str) {
    return str ? CreateSharedString(str->c_str(), str->size()) : 0;
  }

  /// @cond FLATBUFFERS_INTERNAL
  template <typename LenT = uoffset_t, typename ReturnT = uoffset_t>
  ReturnT EndVector(size_t len) {
    FLATBUFFERS_ASSERT(nested);  // Hit if no corresponding StartVector.
    nested = false;
    return PushElement<LenT, ReturnT>(static_cast<LenT>(len));
  }

  template <template <typename> class OffsetT = Offset,
            typename LenT = uint32_t>
  void StartVector(size_t len, size_t elemsize, size_t alignment) {
    NotNested();
    nested = true;
    // Align to the Length type of the vector (either 32-bit or 64-bit), so
    // that the length of the buffer can be added without padding.
    PreAlign<LenT>(len * elemsize);
    PreAlign(len * elemsize, alignment);  // Just in case elemsize > uoffset_t.
  }

  template <typename T, template <typename> class OffsetT = Offset,
            typename LenT = uint32_t>
  void StartVector(size_t len) {
    return StartVector<OffsetT, LenT>(len, sizeof(T), AlignOf<T>());
  }

  // Call this right before StartVector/CreateVector if you want to force the
  // alignment to be something different than what the element size would
  // normally dictate.
  // This is useful when storing a nested_flatbuffer in a vector of bytes,
  // or when storing SIMD floats, etc.
  void ForceVectorAlignment(const size_t len, const size_t elemsize,
                            const size_t alignment) {
    if (len == 0) return;
    FLATBUFFERS_ASSERT(VerifyAlignmentRequirements(alignment));
    PreAlign(len * elemsize, alignment);
  }

  template <bool is_64 = Is64Aware>
  typename std::enable_if<is_64, void>::type ForceVectorAlignment64(
      const size_t len, const size_t elemsize, const size_t alignment) {
    // If you hit this assertion, you are trying to force alignment on a
    // vector with offset64 after serializing a 32-bit offset.
    FLATBUFFERS_ASSERT(GetSize() == length_of_64_bit_region_);

    // Call through.
    ForceVectorAlignment(len, elemsize, alignment);

    // Update the 64 bit region.
    length_of_64_bit_region_ = GetSize();
  }

  // Similar to ForceVectorAlignment but for String fields.
  void ForceStringAlignment(size_t len, size_t alignment) {
    if (len == 0) return;
    FLATBUFFERS_ASSERT(VerifyAlignmentRequirements(alignment));
    PreAlign((len + 1) * sizeof(char), alignment);
  }

  /// @endcond

  /// @brief Serialize an array into a FlatBuffer `vector`.
  /// @tparam T The data type of the array elements.
  /// @tparam OffsetT the type of offset to return
  /// @tparam VectorT the type of vector to cast to.
  /// @param[in] v A pointer to the array of type `T` to serialize into the
  /// buffer as a `vector`.
  /// @param[in] len The number of elements to serialize.
  /// @return Returns a typed `TOffset` into the serialized data indicating
  /// where the vector is stored.
  template <typename T, template <typename...> class OffsetT = Offset,
            template <typename...> class VectorT = Vector>
  OffsetT<VectorT<T>> CreateVector(const T* v, size_t len) {
    // The type of the length field in the vector.
    typedef typename VectorT<T>::size_type LenT;
    typedef typename OffsetT<VectorT<T>>::offset_type offset_type;
    // If this assert hits, you're specifying a template argument that is
    // causing the wrong overload to be selected, remove it.
    AssertScalarT<T>();
    StartVector<T, OffsetT, LenT>(len);
    if (len > 0) {
      // clang-format off
      #if FLATBUFFERS_LITTLEENDIAN
        PushBytes(reinterpret_cast<const uint8_t *>(v), len * sizeof(T));
      #else
        if (sizeof(T) == 1) {
          PushBytes(reinterpret_cast<const uint8_t *>(v), len);
        } else {
          for (auto i = len; i > 0; ) {
            PushElement(v[--i]);
          }
        }
      #endif
      // clang-format on
    }
    return OffsetT<VectorT<T>>(EndVector<LenT, offset_type>(len));
  }

  /// @brief Serialize an array like object into a FlatBuffer `vector`.
  /// @tparam T The data type of the array elements.
  /// @tparam C The type of the array.
  /// @param[in] array A reference to an array like object of type `T` to
  /// serialize into the buffer as a `vector`.
  /// @return Returns a typed `Offset` into the serialized data indicating
  /// where the vector is stored.
  template <typename T, class C>
  Offset<Vector<T>> CreateVector(const C& array) {
    return CreateVector(array.data(), array.size());
  }

  /// @brief Serialize an initializer list into a FlatBuffer `vector`.
  /// @tparam T The data type of the initializer list elements.
  /// @param[in] v The value of the initializer list.
  /// @return Returns a typed `Offset` into the serialized data indicating
  /// where the vector is stored.
  template <typename T>
  Offset<Vector<T>> CreateVector(std::initializer_list<T> v) {
    return CreateVector(v.begin(), v.size());
  }

  template <typename T>
  Offset<Vector<Offset<T>>> CreateVector(const Offset<T>* v, size_t len) {
    StartVector<Offset<T>>(len);
    for (auto i = len; i > 0;) {
      PushElement(v[--i]);
    }
    return Offset<Vector<Offset<T>>>(EndVector(len));
  }

  /// @brief Serialize a `std::vector` into a FlatBuffer `vector`.
  /// @tparam T The data type of the `std::vector` elements.
  /// @param v A const reference to the `std::vector` to serialize into the
  /// buffer as a `vector`.
  /// @return Returns a typed `Offset` into the serialized data indicating
  /// where the vector is stored.
  template <typename T, typename Alloc = std::allocator<T>>
  Offset<Vector<T>> CreateVector(const std::vector<T, Alloc>& v) {
    return CreateVector(data(v), v.size());
  }

  template <template <typename...> class VectorT = Vector64,
            int&... ExplicitArgumentBarrier, typename T>
  Offset64<VectorT<T>> CreateVector64(const std::vector<T>& v) {
    return CreateVector<T, Offset64, VectorT>(data(v), v.size());
  }

  // vector<bool> may be implemented using a bit-set, so we can't access it as
  // an array. Instead, read elements manually.
  // Background: https://isocpp.org/blog/2012/11/on-vectorbool
  Offset<Vector<uint8_t>> CreateVector(const std::vector<bool>& v) {
    StartVector<uint8_t>(v.size());
    for (auto i = v.size(); i > 0;) {
      PushElement(static_cast<uint8_t>(v[--i]));
    }
    return Offset<Vector<uint8_t>>(EndVector(v.size()));
  }

  Offset64<Vector64<uint8_t>> CreateVector64(const std::vector<bool>& v) {
    StartVector<uint8_t, Offset64, Vector64<uint8_t>::size_type>(v.size());
    for (auto i = v.size(); i > 0;) {
      PushElement(static_cast<uint8_t>(v[--i]));
    }
    return Offset64<Vector64<uint8_t>>(
        EndVector<Vector64<uint8_t>::size_type,
                  Offset64<Vector64<uint8_t>>::offset_type>(v.size()));
  }

  /// @brief Serialize values returned by a function into a FlatBuffer `vector`.
  /// This is a convenience function that takes care of iteration for you.
  /// @tparam T The data type of the `std::vector` elements.
  /// @param f A function that takes the current iteration 0..vector_size-1 and
  /// returns any type that you can construct a FlatBuffers vector out of.
  /// @return Returns a typed `Offset` into the serialized data indicating
  /// where the vector is stored.
  template <typename T>
  Offset<Vector<T>> CreateVector(size_t vector_size,
                                 const std::function<T(size_t i)>& f) {
    FLATBUFFERS_ASSERT(FLATBUFFERS_GENERAL_HEAP_ALLOC_OK);
    std::vector<T> elems(vector_size);
    for (size_t i = 0; i < vector_size; i++) elems[i] = f(i);
    return CreateVector(elems);
  }

  /// @brief Serialize values returned by a function into a FlatBuffer `vector`.
  /// This is a convenience function that takes care of iteration for you. This
  /// uses a vector stored on the heap to store the intermediate results of the
  /// iteration.
  /// @tparam T The data type of the `std::vector` elements.
  /// @param f A function that takes the current iteration 0..vector_size-1,
  /// and the state parameter returning any type that you can construct a
  /// FlatBuffers vector out of.
  /// @param state State passed to f.
  /// @return Returns a typed `Offset` into the serialized data indicating
  /// where the vector is stored.
  template <typename T, typename F, typename S>
  Offset<Vector<T>> CreateVector(size_t vector_size, F f, S* state) {
    FLATBUFFERS_ASSERT(FLATBUFFERS_GENERAL_HEAP_ALLOC_OK);
    std::vector<T> elems(vector_size);
    for (size_t i = 0; i < vector_size; i++) elems[i] = f(i, state);
    return CreateVector(elems);
  }

  /// @brief Serialize a `std::vector<StringType>` into a FlatBuffer `vector`.
  /// whereas StringType is any type that is accepted by the CreateString()
  /// overloads.
  /// This is a convenience function for a common case.
  /// @param v A const reference to the `std::vector` to serialize into the
  /// buffer as a `vector`.
  /// @return Returns a typed `Offset` into the serialized data indicating
  /// where the vector is stored.
  template <typename StringType = std::string,
            typename Alloc = std::allocator<StringType>>
  Offset<Vector<Offset<String>>> CreateVectorOfStrings(
      const std::vector<StringType, Alloc>& v) {
    return CreateVectorOfStrings(v.cbegin(), v.cend());
  }

  /// @brief Serialize a collection of Strings into a FlatBuffer `vector`.
  /// This is a convenience function for a common case.
  /// @param begin The beginning iterator of the collection
  /// @param end The ending iterator of the collection
  /// @return Returns a typed `Offset` into the serialized data indicating
  /// where the vector is stored.
  template <class It>
  Offset<Vector<Offset<String>>> CreateVectorOfStrings(It begin, It end) {
    auto distance = std::distance(begin, end);
    FLATBUFFERS_ASSERT(distance >= 0);
    auto size = static_cast<size_t>(distance);
    auto scratch_buffer_usage = size * sizeof(Offset<String>);
    // If there is not enough space to store the offsets, there definitely won't
    // be enough space to store all the strings. So ensuring space for the
    // scratch region is OK, for if it fails, it would have failed later.
    buf_.ensure_space(scratch_buffer_usage);
    for (auto it = begin; it != end; ++it) {
      buf_.scratch_push_small(CreateString(*it));
    }
    StartVector<Offset<String>>(size);
    for (size_t i = 1; i <= size; i++) {
      // Note we re-evaluate the buf location each iteration to account for any
      // underlying buffer resizing that may occur.
      PushElement(*reinterpret_cast<Offset<String>*>(
          buf_.scratch_end() - i * sizeof(Offset<String>)));
    }
    buf_.scratch_pop(scratch_buffer_usage);
    return Offset<Vector<Offset<String>>>(EndVector(size));
  }

  /// @brief Serialize an array of structs into a FlatBuffer `vector`.
  /// @tparam T The data type of the struct array elements.
  /// @param[in] v A pointer to the array of type `T` to serialize into the
  /// buffer as a `vector`.
  /// @param[in] len The number of elements to serialize.
  /// @return Returns a typed `Offset` into the serialized data indicating
  /// where the vector is stored.
  template <typename T, template <typename...> class OffsetT = Offset,
            template <typename...> class VectorT = Vector>
  OffsetT<VectorT<const T*>> CreateVectorOfStructs(const T* v, size_t len) {
    // The type of the length field in the vector.
    typedef typename VectorT<T>::size_type LenT;
    typedef typename OffsetT<VectorT<const T*>>::offset_type offset_type;

    StartVector<OffsetT, LenT>(len, sizeof(T), AlignOf<T>());
    if (len > 0) {
      PushBytes(reinterpret_cast<const uint8_t*>(v), sizeof(T) * len);
    }
    return OffsetT<VectorT<const T*>>(EndVector<LenT, offset_type>(len));
  }

  /// @brief Serialize an array of structs into a FlatBuffer `vector`.
  /// @tparam T The data type of the struct array elements.
  /// @param[in] filler A function that takes the current iteration
  /// 0..vector_size-1 and a pointer to the struct that must be filled.
  /// @return Returns a typed `Offset` into the serialized data indicating
  /// where the vector is stored.
  /// This is mostly useful when flatbuffers are generated with mutation
  /// accessors.
  template <typename T>
  Offset<Vector<const T*>> CreateVectorOfStructs(
      size_t vector_size, const std::function<void(size_t i, T*)>& filler) {
    T* structs = StartVectorOfStructs<T>(vector_size);
    for (size_t i = 0; i < vector_size; i++) {
      filler(i, structs);
      structs++;
    }
    return EndVectorOfStructs<T>(vector_size);
  }

  /// @brief Serialize an array of structs into a FlatBuffer `vector`.
  /// @tparam T The data type of the struct array elements.
  /// @param[in] f A function that takes the current iteration 0..vector_size-1,
  /// a pointer to the struct that must be filled and the state argument.
  /// @param[in] state Arbitrary state to pass to f.
  /// @return Returns a typed `Offset` into the serialized data indicating
  /// where the vector is stored.
  /// This is mostly useful when flatbuffers are generated with mutation
  /// accessors.
  template <typename T, typename F, typename S>
  Offset<Vector<const T*>> CreateVectorOfStructs(size_t vector_size, F f,
                                                 S* state) {
    T* structs = StartVectorOfStructs<T>(vector_size);
    for (size_t i = 0; i < vector_size; i++) {
      f(i, structs, state);
      structs++;
    }
    return EndVectorOfStructs<T>(vector_size);
  }

  /// @brief Serialize a `std::vector` of structs into a FlatBuffer `vector`.
  /// @tparam T The data type of the `std::vector` struct elements.
  /// @param[in] v A const reference to the `std::vector` of structs to
  /// serialize into the buffer as a `vector`.
  /// @return Returns a typed `Offset` into the serialized data indicating
  /// where the vector is stored.
  template <typename T, template <typename...> class OffsetT = Offset,
            template <typename...> class VectorT = Vector,
            typename Alloc = std::allocator<T>>
  OffsetT<VectorT<const T*>> CreateVectorOfStructs(
      const std::vector<T, Alloc>& v) {
    return CreateVectorOfStructs<T, OffsetT, VectorT>(data(v), v.size());
  }

  template <template <typename...> class VectorT = Vector64, int&...,
            typename T>
  Offset64<VectorT<const T*>> CreateVectorOfStructs64(const std::vector<T>& v) {
    return CreateVectorOfStructs<T, Offset64, VectorT>(data(v), v.size());
  }

  /// @brief Serialize an array of native structs into a FlatBuffer `vector`.
  /// @tparam T The data type of the struct array elements.
  /// @tparam S The data type of the native struct array elements.
  /// @param[in] v A pointer to the array of type `S` to serialize into the
  /// buffer as a `vector`.
  /// @param[in] len The number of elements to serialize.
  /// @param[in] pack_func Pointer to a function to convert the native struct
  /// to the FlatBuffer struct.
  /// @return Returns a typed `Offset` into the serialized data indicating
  /// where the vector is stored.
  template <typename T, typename S>
  Offset<Vector<const T*>> CreateVectorOfNativeStructs(
      const S* v, size_t len, T (*const pack_func)(const S&)) {
    FLATBUFFERS_ASSERT(pack_func);
    auto structs = StartVectorOfStructs<T>(len);
    for (size_t i = 0; i < len; i++) {
      structs[i] = pack_func(v[i]);
    }
    return EndVectorOfStructs<T>(len);
  }

  /// @brief Serialize an array of native structs into a FlatBuffer `vector`.
  /// @tparam T The data type of the struct array elements.
  /// @tparam S The data type of the native struct array elements.
  /// @param[in] v A pointer to the array of type `S` to serialize into the
  /// buffer as a `vector`.
  /// @param[in] len The number of elements to serialize.
  /// @return Returns a typed `Offset` into the serialized data indicating
  /// where the vector is stored.
  template <typename T, typename S>
  Offset<Vector<const T*>> CreateVectorOfNativeStructs(const S* v, size_t len) {
    extern T Pack(const S&);
    return CreateVectorOfNativeStructs(v, len, Pack);
  }

  /// @brief Serialize a `std::vector` of native structs into a FlatBuffer
  /// `vector`.
  /// @tparam T The data type of the `std::vector` struct elements.
  /// @tparam S The data type of the `std::vector` native struct elements.
  /// @param[in] v A const reference to the `std::vector` of structs to
  /// serialize into the buffer as a `vector`.
  /// @param[in] pack_func Pointer to a function to convert the native struct
  /// to the FlatBuffer struct.
  /// @return Returns a typed `Offset` into the serialized data indicating
  /// where the vector is stored.
  template <typename T, typename S, typename Alloc = std::allocator<T>>
  Offset<Vector<const T*>> CreateVectorOfNativeStructs(
      const std::vector<S, Alloc>& v, T (*const pack_func)(const S&)) {
    return CreateVectorOfNativeStructs<T, S>(data(v), v.size(), pack_func);
  }

  /// @brief Serialize a `std::vector` of native structs into a FlatBuffer
  /// `vector`.
  /// @tparam T The data type of the `std::vector` struct elements.
  /// @tparam S The data type of the `std::vector` native struct elements.
  /// @param[in] v A const reference to the `std::vector` of structs to
  /// serialize into the buffer as a `vector`.
  /// @return Returns a typed `Offset` into the serialized data indicating
  /// where the vector is stored.
  template <typename T, typename S, typename Alloc = std::allocator<S>>
  Offset<Vector<const T*>> CreateVectorOfNativeStructs(
      const std::vector<S, Alloc>& v) {
    return CreateVectorOfNativeStructs<T, S>(data(v), v.size());
  }

  /// @cond FLATBUFFERS_INTERNAL
  template <typename T>
  struct StructKeyComparator {
    bool operator()(const T& a, const T& b) const {
      return a.KeyCompareLessThan(&b);
    }
  };
  /// @endcond

  /// @brief Serialize a `std::vector` of structs into a FlatBuffer `vector`
  /// in sorted order.
  /// @tparam T The data type of the `std::vector` struct elements.
  /// @param[in] v A const reference to the `std::vector` of structs to
  /// serialize into the buffer as a `vector`.
  /// @return Returns a typed `Offset` into the serialized data indicating
  /// where the vector is stored.
  template <typename T, typename Alloc = std::allocator<T>>
  Offset<Vector<const T*>> CreateVectorOfSortedStructs(
      std::vector<T, Alloc>* v) {
    return CreateVectorOfSortedStructs(data(*v), v->size());
  }

  /// @brief Serialize a `std::vector` of native structs into a FlatBuffer
  /// `vector` in sorted order.
  /// @tparam T The data type of the `std::vector` struct elements.
  /// @tparam S The data type of the `std::vector` native struct elements.
  /// @param[in] v A const reference to the `std::vector` of structs to
  /// serialize into the buffer as a `vector`.
  /// @return Returns a typed `Offset` into the serialized data indicating
  /// where the vector is stored.
  template <typename T, typename S, typename Alloc = std::allocator<T>>
  Offset<Vector<const T*>> CreateVectorOfSortedNativeStructs(
      std::vector<S, Alloc>* v) {
    return CreateVectorOfSortedNativeStructs<T, S>(data(*v), v->size());
  }

  /// @brief Serialize an array of structs into a FlatBuffer `vector` in sorted
  /// order.
  /// @tparam T The data type of the struct array elements.
  /// @param[in] v A pointer to the array of type `T` to serialize into the
  /// buffer as a `vector`.
  /// @param[in] len The number of elements to serialize.
  /// @return Returns a typed `Offset` into the serialized data indicating
  /// where the vector is stored.
  template <typename T>
  Offset<Vector<const T*>> CreateVectorOfSortedStructs(T* v, size_t len) {
    std::stable_sort(v, v + len, StructKeyComparator<T>());
    return CreateVectorOfStructs(v, len);
  }

  /// @brief Serialize an array of native structs into a FlatBuffer `vector` in
  /// sorted order.
  /// @tparam T The data type of the struct array elements.
  /// @tparam S The data type of the native struct array elements.
  /// @param[in] v A pointer to the array of type `S` to serialize into the
  /// buffer as a `vector`.
  /// @param[in] len The number of elements to serialize.
  /// @return Returns a typed `Offset` into the serialized data indicating
  /// where the vector is stored.
  template <typename T, typename S>
  Offset<Vector<const T*>> CreateVectorOfSortedNativeStructs(S* v, size_t len) {
    extern T Pack(const S&);
    auto structs = StartVectorOfStructs<T>(len);
    for (size_t i = 0; i < len; i++) {
      structs[i] = Pack(v[i]);
    }
    std::stable_sort(structs, structs + len, StructKeyComparator<T>());
    return EndVectorOfStructs<T>(len);
  }

  /// @cond FLATBUFFERS_INTERNAL
  template <typename T>
  struct TableKeyComparator {
    explicit TableKeyComparator(vector_downward<SizeT>& buf) : buf_(buf) {}
    TableKeyComparator(const TableKeyComparator& other) : buf_(other.buf_) {}
    bool operator()(const Offset<T>& a, const Offset<T>& b) const {
      auto table_a = reinterpret_cast<T*>(buf_.data_at(a.o));
      auto table_b = reinterpret_cast<T*>(buf_.data_at(b.o));
      return table_a->KeyCompareLessThan(table_b);
    }
    vector_downward<SizeT>& buf_;

   private:
    FLATBUFFERS_DELETE_FUNC(
        TableKeyComparator& operator=(const TableKeyComparator& other));
  };
  /// @endcond

  /// @brief Serialize an array of `table` offsets as a `vector` in the buffer
  /// in sorted order.
  /// @tparam T The data type that the offset refers to.
  /// @param[in] v An array of type `Offset<T>` that contains the `table`
  /// offsets to store in the buffer in sorted order.
  /// @param[in] len The number of elements to store in the `vector`.
  /// @return Returns a typed `Offset` into the serialized data indicating
  /// where the vector is stored.
  template <typename T>
  Offset<Vector<Offset<T>>> CreateVectorOfSortedTables(Offset<T>* v,
                                                       size_t len) {
    std::stable_sort(v, v + len, TableKeyComparator<T>(buf_));
    return CreateVector(v, len);
  }

  /// @brief Serialize an array of `table` offsets as a `vector` in the buffer
  /// in sorted order.
  /// @tparam T The data type that the offset refers to.
  /// @param[in] v An array of type `Offset<T>` that contains the `table`
  /// offsets to store in the buffer in sorted order.
  /// @return Returns a typed `Offset` into the serialized data indicating
  /// where the vector is stored.
  template <typename T, typename Alloc = std::allocator<T>>
  Offset<Vector<Offset<T>>> CreateVectorOfSortedTables(
      std::vector<Offset<T>, Alloc>* v) {
    return CreateVectorOfSortedTables(data(*v), v->size());
  }

  /// @brief Specialized version of `CreateVector` for non-copying use cases.
  /// Write the data any time later to the returned buffer pointer `buf`.
  /// @param[in] len The number of elements to store in the `vector`.
  /// @param[in] elemsize The size of each element in the `vector`.
  /// @param[out] buf A pointer to a `uint8_t` pointer that can be
  /// written to at a later time to serialize the data into a `vector`
  /// in the buffer.
  uoffset_t CreateUninitializedVector(size_t len, size_t elemsize,
                                      size_t alignment, uint8_t** buf) {
    NotNested();
    StartVector(len, elemsize, alignment);
    buf_.make_space(len * elemsize);
    const uoffset_t vec_start = GetSizeRelative32BitRegion();
    auto vec_end = EndVector(len);
    *buf = buf_.data_at(vec_start);
    return vec_end;
  }

  FLATBUFFERS_ATTRIBUTE([[deprecated("call the version above instead")]])
  uoffset_t CreateUninitializedVector(size_t len, size_t elemsize,
                                      uint8_t** buf) {
    return CreateUninitializedVector(len, elemsize, elemsize, buf);
  }

  /// @brief Specialized version of `CreateVector` for non-copying use cases.
  /// Write the data any time later to the returned buffer pointer `buf`.
  /// @tparam T The data type of the data that will be stored in the buffer
  /// as a `vector`.
  /// @param[in] len The number of elements to store in the `vector`.
  /// @param[out] buf A pointer to a pointer of type `T` that can be
  /// written to at a later time to serialize the data into a `vector`
  /// in the buffer.
  template <typename T>
  Offset<Vector<T>> CreateUninitializedVector(size_t len, T** buf) {
    AssertScalarT<T>();
    return CreateUninitializedVector(len, sizeof(T), AlignOf<T>(),
                                     reinterpret_cast<uint8_t**>(buf));
  }

  template <typename T>
  Offset<Vector<const T*>> CreateUninitializedVectorOfStructs(size_t len,
                                                              T** buf) {
    return CreateUninitializedVector(len, sizeof(T), AlignOf<T>(),
                                     reinterpret_cast<uint8_t**>(buf));
  }

  // @brief Create a vector of scalar type T given as input a vector of scalar
  // type U, useful with e.g. pre "enum class" enums, or any existing scalar
  // data of the wrong type.
  template <typename T, typename U>
  Offset<Vector<T>> CreateVectorScalarCast(const U* v, size_t len) {
    AssertScalarT<T>();
    AssertScalarT<U>();
    StartVector<T>(len);
    for (auto i = len; i > 0;) {
      PushElement(static_cast<T>(v[--i]));
    }
    return Offset<Vector<T>>(EndVector(len));
  }

  /// @brief Write a struct by itself, typically to be part of a union.
  template <typename T>
  Offset<const T*> CreateStruct(const T& structobj) {
    NotNested();
    Align(AlignOf<T>());
    buf_.push_small(structobj);
    return Offset<const T*>(
        CalculateOffset<typename Offset<const T*>::offset_type>());
  }

  /// @brief Finish serializing a buffer by writing the root offset.
  /// @param[in] file_identifier If a `file_identifier` is given, the buffer
  /// will be prefixed with a standard FlatBuffers file header.
  template <typename T>
  void Finish(Offset<T> root, const char* file_identifier = nullptr) {
    Finish(root.o, file_identifier, false);
  }

  /// @brief Finish a buffer with a 32 bit size field pre-fixed (size of the
  /// buffer following the size field). These buffers are NOT compatible
  /// with standard buffers created by Finish, i.e. you can't call GetRoot
  /// on them, you have to use GetSizePrefixedRoot instead.
  /// All >32 bit quantities in this buffer will be aligned when the whole
  /// size pre-fixed buffer is aligned.
  /// These kinds of buffers are useful for creating a stream of FlatBuffers.
  template <typename T>
  void FinishSizePrefixed(Offset<T> root,
                          const char* file_identifier = nullptr) {
    Finish(root.o, file_identifier, true);
  }

  void SwapBufAllocator(FlatBufferBuilderImpl& other) {
    buf_.swap_allocator(other.buf_);
  }

  /// @brief The length of a FlatBuffer file header.
  static const size_t kFileIdentifierLength =
      ::flatbuffers::kFileIdentifierLength;

 protected:
  // You shouldn't really be copying instances of this class.
  FlatBufferBuilderImpl(const FlatBufferBuilderImpl&);
  FlatBufferBuilderImpl& operator=(const FlatBufferBuilderImpl&);

  void Finish(uoffset_t root, const char* file_identifier, bool size_prefix) {
    // A buffer can only be finished once. To reuse a builder use `clear()`.
    FLATBUFFERS_ASSERT(!finished);

    NotNested();
    buf_.clear_scratch();

    const size_t prefix_size = size_prefix ? sizeof(SizeT) : 0;
    // Make sure we track the alignment of the size prefix.
    TrackMinAlign(prefix_size);

    const size_t root_offset_size = sizeof(uoffset_t);
    const size_t file_id_size = file_identifier ? kFileIdentifierLength : 0;

    // This will cause the whole buffer to be aligned.
    PreAlign(prefix_size + root_offset_size + file_id_size, minalign_);

    if (file_identifier) {
      FLATBUFFERS_ASSERT(strlen(file_identifier) == kFileIdentifierLength);
      PushBytes(reinterpret_cast<const uint8_t*>(file_identifier),
                kFileIdentifierLength);
    }
    PushElement(ReferTo(root));  // Location of root.
    if (size_prefix) {
      PushElement(GetSize());
    }
    finished = true;
  }

  struct FieldLoc {
    uoffset_t off;
    voffset_t id;
  };

  vector_downward<SizeT> buf_;

  // Accumulating offsets of table members while it is being built.
  // We store these in the scratch pad of buf_, after the vtable offsets.
  uoffset_t num_field_loc;
  // Track how much of the vtable is in use, so we can output the most compact
  // possible vtable.
  voffset_t max_voffset_;

  // This is the length of the 64-bit region of the buffer. The buffer supports
  // 64-bit offsets by forcing serialization of those elements in the "tail"
  // region of the buffer (i.e. "64-bit region"). To properly keep track of
  // offsets that are referenced from the tail of the buffer to not overflow
  // their size (e.g. Offset is a uint32_t type), the boundary of the 32-/64-bit
  // regions must be tracked.
  //
  // [    Complete FlatBuffer     ]
  // [32-bit region][64-bit region]
  //               ^              ^
  //               |              Tail of the buffer.
  //               |
  //               Tail of the 32-bit region of the buffer.
  //
  // This keeps track of the size of the 64-bit region so that the tail of the
  // 32-bit region can be calculated as `GetSize() - length_of_64_bit_region_`.
  //
  // This will remain 0 if no 64-bit offset types are added to the buffer.
  size_t length_of_64_bit_region_;

  // Ensure objects are not nested.
  bool nested;

  // Ensure the buffer is finished before it is being accessed.
  bool finished;

  size_t minalign_;

  bool force_defaults_;  // Serialize values equal to their defaults anyway.

  bool dedup_vtables_;

  struct StringOffsetCompare {
    explicit StringOffsetCompare(const vector_downward<SizeT>& buf)
        : buf_(&buf) {}
    bool operator()(const Offset<String>& a, const Offset<String>& b) const {
      auto stra = reinterpret_cast<const String*>(buf_->data_at(a.o));
      auto strb = reinterpret_cast<const String*>(buf_->data_at(b.o));
      return StringLessThan(stra->data(), stra->size(), strb->data(),
                            strb->size());
    }
    const vector_downward<SizeT>* buf_;
  };

  // For use with CreateSharedString. Instantiated on first use only.
  typedef std::set<Offset<String>, StringOffsetCompare> StringOffsetMap;
  StringOffsetMap* string_pool;

 private:
  void CanAddOffset64() {
    // If you hit this assertion, you are attempting to add a 64-bit offset to
    // a 32-bit only builder. This is because the builder has overloads that
    // differ only on the offset size returned: e.g.:
    //
    //   FlatBufferBuilder builder;
    //   Offset64<String> string_offset = builder.CreateString<Offset64>();
    //
    // Either use a 64-bit aware builder, or don't try to create an Offset64
    // return type.
    //
    // TODO(derekbailey): we can probably do more enable_if to avoid this
    // looking like its possible to the user.
    static_assert(Is64Aware, "cannot add 64-bit offset to a 32-bit builder");

    // If you hit this assertion, you are attempting to add an 64-bit offset
    // item after already serializing a 32-bit item. All 64-bit offsets have to
    // added to the tail of the buffer before any 32-bit items can be added.
    // Otherwise some items might not be addressable due to the maximum range of
    // the 32-bit offset.
    FLATBUFFERS_ASSERT(GetSize() == length_of_64_bit_region_);
  }

  /// @brief Store a string in the buffer, which can contain any binary data.
  /// @param[in] str A const char pointer to the data to be stored as a string.
  /// @param[in] len The number of bytes that should be stored from `str`.
  /// @return Returns the offset in the buffer where the string starts.
  void CreateStringImpl(const char* str, size_t len) {
    NotNested();
    PreAlign<uoffset_t>(len + 1);  // Always 0-terminated.
    buf_.fill(1);
    PushBytes(reinterpret_cast<const uint8_t*>(str), len);
    PushElement(static_cast<uoffset_t>(len));
  }

  // Allocates space for a vector of structures.
  // Must be completed with EndVectorOfStructs().
  template <typename T, template <typename> class OffsetT = Offset>
  T* StartVectorOfStructs(size_t vector_size) {
    StartVector<OffsetT>(vector_size, sizeof(T), AlignOf<T>());
    return reinterpret_cast<T*>(buf_.make_space(vector_size * sizeof(T)));
  }

  // End the vector of structures in the flatbuffers.
  // Vector should have previously be started with StartVectorOfStructs().
  template <typename T, template <typename> class OffsetT = Offset>
  OffsetT<Vector<const T*>> EndVectorOfStructs(size_t vector_size) {
    return OffsetT<Vector<const T*>>(
        EndVector<typename Vector<const T*>::size_type,
                  typename OffsetT<Vector<const T*>>::offset_type>(
            vector_size));
  }

  template <typename T>
  typename std::enable_if<std::is_same<T, uoffset_t>::value, T>::type
  CalculateOffset() {
    // Default to the end of the 32-bit region. This may or may not be the end
    // of the buffer, depending on if any 64-bit offsets have been added.
    return GetSizeRelative32BitRegion();
  }

  // Specializations to handle the 64-bit CalculateOffset, which is relative to
  // end of the buffer.
  template <typename T>
  typename std::enable_if<std::is_same<T, uoffset64_t>::value, T>::type
  CalculateOffset() {
    // This should never be compiled in when not using a 64-bit builder.
    static_assert(Is64Aware, "invalid 64-bit offset in 32-bit builder");

    // Store how big the 64-bit region of the buffer is, so we can determine
    // where the 32/64 bit boundary is.
    length_of_64_bit_region_ = GetSize();

    return length_of_64_bit_region_;
  }
};
/// @}

// Hack to `FlatBufferBuilder` mean `FlatBufferBuilder<false>` or
// `FlatBufferBuilder<>`, where the template < > syntax is required.
using FlatBufferBuilder = FlatBufferBuilderImpl<false>;
using FlatBufferBuilder64 = FlatBufferBuilderImpl<true>;

// These are external due to GCC not allowing them in the class.
// See: https://stackoverflow.com/q/8061456/868247
template <>
template <>
inline Offset64<String> FlatBufferBuilder64::CreateString(const char* str,
                                                          size_t len) {
  CanAddOffset64();
  CreateStringImpl(str, len);
  return Offset64<String>(
      CalculateOffset<typename Offset64<String>::offset_type>());
}

// Used to distinguish from real Offsets.
template <typename T = void>
struct EmptyOffset {};

// TODO(derekbailey): it would be nice to combine these two methods.
template <>
template <>
inline void FlatBufferBuilder64::StartVector<Offset64, uint32_t>(
    size_t len, size_t elemsize, size_t alignment) {
  CanAddOffset64();
  StartVector<EmptyOffset, uint32_t>(len, elemsize, alignment);
}

template <>
template <>
inline void FlatBufferBuilder64::StartVector<Offset64, uint64_t>(
    size_t len, size_t elemsize, size_t alignment) {
  CanAddOffset64();
  StartVector<EmptyOffset, uint64_t>(len, elemsize, alignment);
}

/// Helpers to get a typed pointer to objects that are currently being built.
/// @warning Creating new objects will lead to reallocations and invalidates
/// the pointer!
template <typename T>
T* GetMutableTemporaryPointer(FlatBufferBuilder& fbb, Offset<T> offset) {
  return reinterpret_cast<T*>(fbb.GetCurrentBufferPointer() + fbb.GetSize() -
                              offset.o);
}

template <typename T>
const T* GetTemporaryPointer(const FlatBufferBuilder& fbb, Offset<T> offset) {
  return reinterpret_cast<const T*>(fbb.GetCurrentBufferPointer() +
                                    fbb.GetSize() - offset.o);
}

}  // namespace flatbuffers

#endif  // FLATBUFFERS_FLATBUFFER_BUILDER_H_
