/*
 * Copyright 2017 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_FLEXBUFFERS_H_
#define FLATBUFFERS_FLEXBUFFERS_H_

#include <algorithm>
#include <map>
// Used to select STL variant.
#include "flatbuffers/base.h"
// We use the basic binary writing functions from the regular FlatBuffers.
#include "flatbuffers/util.h"

#ifdef _MSC_VER
#  include <intrin.h>
#endif

#if defined(_MSC_VER)
#  pragma warning(push)
#  pragma warning(disable : 4127)  // C4127: conditional expression is constant
#endif

namespace flexbuffers {

class Reference;
class Map;

// These are used in the lower 2 bits of a type field to determine the size of
// the elements (and or size field) of the item pointed to (e.g. vector).
enum BitWidth {
  BIT_WIDTH_8 = 0,
  BIT_WIDTH_16 = 1,
  BIT_WIDTH_32 = 2,
  BIT_WIDTH_64 = 3,
};

// These are used as the upper 6 bits of a type field to indicate the actual
// type.
enum Type {
  FBT_NULL = 0,
  FBT_INT = 1,
  FBT_UINT = 2,
  FBT_FLOAT = 3,
  // Types above stored inline, types below (except FBT_BOOL) store an offset.
  FBT_KEY = 4,
  FBT_STRING = 5,
  FBT_INDIRECT_INT = 6,
  FBT_INDIRECT_UINT = 7,
  FBT_INDIRECT_FLOAT = 8,
  FBT_MAP = 9,
  FBT_VECTOR = 10,      // Untyped.
  FBT_VECTOR_INT = 11,  // Typed any size (stores no type table).
  FBT_VECTOR_UINT = 12,
  FBT_VECTOR_FLOAT = 13,
  FBT_VECTOR_KEY = 14,
  // DEPRECATED, use FBT_VECTOR or FBT_VECTOR_KEY instead.
  // Read test.cpp/FlexBuffersDeprecatedTest() for details on why.
  FBT_VECTOR_STRING_DEPRECATED = 15,
  FBT_VECTOR_INT2 = 16,  // Typed tuple (no type table, no size field).
  FBT_VECTOR_UINT2 = 17,
  FBT_VECTOR_FLOAT2 = 18,
  FBT_VECTOR_INT3 = 19,  // Typed triple (no type table, no size field).
  FBT_VECTOR_UINT3 = 20,
  FBT_VECTOR_FLOAT3 = 21,
  FBT_VECTOR_INT4 = 22,  // Typed quad (no type table, no size field).
  FBT_VECTOR_UINT4 = 23,
  FBT_VECTOR_FLOAT4 = 24,
  FBT_BLOB = 25,
  FBT_BOOL = 26,
  FBT_VECTOR_BOOL =
      36,  // To Allow the same type of conversion of type to vector type

  FBT_MAX_TYPE = 37
};

inline bool IsInline(Type t) { return t <= FBT_FLOAT || t == FBT_BOOL; }

inline bool IsTypedVectorElementType(Type t) {
  return (t >= FBT_INT && t <= FBT_STRING) || t == FBT_BOOL;
}

inline bool IsTypedVector(Type t) {
  return (t >= FBT_VECTOR_INT && t <= FBT_VECTOR_STRING_DEPRECATED) ||
         t == FBT_VECTOR_BOOL;
}

inline bool IsFixedTypedVector(Type t) {
  return t >= FBT_VECTOR_INT2 && t <= FBT_VECTOR_FLOAT4;
}

inline Type ToTypedVector(Type t, size_t fixed_len = 0) {
  FLATBUFFERS_ASSERT(IsTypedVectorElementType(t));
  switch (fixed_len) {
    case 0: return static_cast<Type>(t - FBT_INT + FBT_VECTOR_INT);
    case 2: return static_cast<Type>(t - FBT_INT + FBT_VECTOR_INT2);
    case 3: return static_cast<Type>(t - FBT_INT + FBT_VECTOR_INT3);
    case 4: return static_cast<Type>(t - FBT_INT + FBT_VECTOR_INT4);
    default: FLATBUFFERS_ASSERT(0); return FBT_NULL;
  }
}

inline Type ToTypedVectorElementType(Type t) {
  FLATBUFFERS_ASSERT(IsTypedVector(t));
  return static_cast<Type>(t - FBT_VECTOR_INT + FBT_INT);
}

inline Type ToFixedTypedVectorElementType(Type t, uint8_t *len) {
  FLATBUFFERS_ASSERT(IsFixedTypedVector(t));
  auto fixed_type = t - FBT_VECTOR_INT2;
  *len = static_cast<uint8_t>(fixed_type / 3 +
                              2);  // 3 types each, starting from length 2.
  return static_cast<Type>(fixed_type % 3 + FBT_INT);
}

// TODO: implement proper support for 8/16bit floats, or decide not to
// support them.
typedef int16_t half;
typedef int8_t quarter;

// TODO: can we do this without conditionals using intrinsics or inline asm
// on some platforms? Given branch prediction the method below should be
// decently quick, but it is the most frequently executed function.
// We could do an (unaligned) 64-bit read if we ifdef out the platforms for
// which that doesn't work (or where we'd read into un-owned memory).
template<typename R, typename T1, typename T2, typename T4, typename T8>
R ReadSizedScalar(const uint8_t *data, uint8_t byte_width) {
  return byte_width < 4
             ? (byte_width < 2
                    ? static_cast<R>(flatbuffers::ReadScalar<T1>(data))
                    : static_cast<R>(flatbuffers::ReadScalar<T2>(data)))
             : (byte_width < 8
                    ? static_cast<R>(flatbuffers::ReadScalar<T4>(data))
                    : static_cast<R>(flatbuffers::ReadScalar<T8>(data)));
}

inline int64_t ReadInt64(const uint8_t *data, uint8_t byte_width) {
  return ReadSizedScalar<int64_t, int8_t, int16_t, int32_t, int64_t>(
      data, byte_width);
}

inline uint64_t ReadUInt64(const uint8_t *data, uint8_t byte_width) {
  // This is the "hottest" function (all offset lookups use this), so worth
  // optimizing if possible.
  // TODO: GCC apparently replaces memcpy by a rep movsb, but only if count is a
  // constant, which here it isn't. Test if memcpy is still faster than
  // the conditionals in ReadSizedScalar. Can also use inline asm.

  // clang-format off
  #if defined(_MSC_VER) && defined(_M_X64) && !defined(_M_ARM64EC)
  // This is 64-bit Windows only, __movsb does not work on 32-bit Windows.
    uint64_t u = 0;
    __movsb(reinterpret_cast<uint8_t *>(&u),
            reinterpret_cast<const uint8_t *>(data), byte_width);
    return flatbuffers::EndianScalar(u);
  #else
    return ReadSizedScalar<uint64_t, uint8_t, uint16_t, uint32_t, uint64_t>(
             data, byte_width);
  #endif
  // clang-format on
}

inline double ReadDouble(const uint8_t *data, uint8_t byte_width) {
  return ReadSizedScalar<double, quarter, half, float, double>(data,
                                                               byte_width);
}

inline const uint8_t *Indirect(const uint8_t *offset, uint8_t byte_width) {
  return offset - ReadUInt64(offset, byte_width);
}

template<typename T> const uint8_t *Indirect(const uint8_t *offset) {
  return offset - flatbuffers::ReadScalar<T>(offset);
}

inline BitWidth WidthU(uint64_t u) {
#define FLATBUFFERS_GET_FIELD_BIT_WIDTH(value, width)                   \
  {                                                                     \
    if (!((u) & ~((1ULL << (width)) - 1ULL))) return BIT_WIDTH_##width; \
  }
  FLATBUFFERS_GET_FIELD_BIT_WIDTH(u, 8);
  FLATBUFFERS_GET_FIELD_BIT_WIDTH(u, 16);
  FLATBUFFERS_GET_FIELD_BIT_WIDTH(u, 32);
#undef FLATBUFFERS_GET_FIELD_BIT_WIDTH
  return BIT_WIDTH_64;
}

inline BitWidth WidthI(int64_t i) {
  auto u = static_cast<uint64_t>(i) << 1;
  return WidthU(i >= 0 ? u : ~u);
}

inline BitWidth WidthF(double f) {
  return static_cast<double>(static_cast<float>(f)) == f ? BIT_WIDTH_32
                                                         : BIT_WIDTH_64;
}

// Base class of all types below.
// Points into the data buffer and allows access to one type.
class Object {
 public:
  Object(const uint8_t *data, uint8_t byte_width)
      : data_(data), byte_width_(byte_width) {}

 protected:
  const uint8_t *data_;
  uint8_t byte_width_;
};

// Object that has a size, obtained either from size prefix, or elsewhere.
class Sized : public Object {
 public:
  // Size prefix.
  Sized(const uint8_t *data, uint8_t byte_width)
      : Object(data, byte_width), size_(read_size()) {}
  // Manual size.
  Sized(const uint8_t *data, uint8_t byte_width, size_t sz)
      : Object(data, byte_width), size_(sz) {}
  size_t size() const { return size_; }
  // Access size stored in `byte_width_` bytes before data_ pointer.
  size_t read_size() const {
    return static_cast<size_t>(ReadUInt64(data_ - byte_width_, byte_width_));
  }

 protected:
  size_t size_;
};

class String : public Sized {
 public:
  // Size prefix.
  String(const uint8_t *data, uint8_t byte_width) : Sized(data, byte_width) {}
  // Manual size.
  String(const uint8_t *data, uint8_t byte_width, size_t sz)
      : Sized(data, byte_width, sz) {}

  size_t length() const { return size(); }
  const char *c_str() const { return reinterpret_cast<const char *>(data_); }
  std::string str() const { return std::string(c_str(), size()); }

  static String EmptyString() {
    static const char *empty_string = "";
    return String(reinterpret_cast<const uint8_t *>(empty_string), 1, 0);
  }
  bool IsTheEmptyString() const { return data_ == EmptyString().data_; }
};

class Blob : public Sized {
 public:
  Blob(const uint8_t *data_buf, uint8_t byte_width)
      : Sized(data_buf, byte_width) {}

  static Blob EmptyBlob() {
    static const uint8_t empty_blob[] = { 0 /*len*/ };
    return Blob(empty_blob + 1, 1);
  }
  bool IsTheEmptyBlob() const { return data_ == EmptyBlob().data_; }
  const uint8_t *data() const { return data_; }
};

class Vector : public Sized {
 public:
  Vector(const uint8_t *data, uint8_t byte_width) : Sized(data, byte_width) {}

  Reference operator[](size_t i) const;

  static Vector EmptyVector() {
    static const uint8_t empty_vector[] = { 0 /*len*/ };
    return Vector(empty_vector + 1, 1);
  }
  bool IsTheEmptyVector() const { return data_ == EmptyVector().data_; }
};

class TypedVector : public Sized {
 public:
  TypedVector(const uint8_t *data, uint8_t byte_width, Type element_type)
      : Sized(data, byte_width), type_(element_type) {}

  Reference operator[](size_t i) const;

  static TypedVector EmptyTypedVector() {
    static const uint8_t empty_typed_vector[] = { 0 /*len*/ };
    return TypedVector(empty_typed_vector + 1, 1, FBT_INT);
  }
  bool IsTheEmptyVector() const {
    return data_ == TypedVector::EmptyTypedVector().data_;
  }

  Type ElementType() { return type_; }

  friend Reference;

 private:
  Type type_;

  friend Map;
};

class FixedTypedVector : public Object {
 public:
  FixedTypedVector(const uint8_t *data, uint8_t byte_width, Type element_type,
                   uint8_t len)
      : Object(data, byte_width), type_(element_type), len_(len) {}

  Reference operator[](size_t i) const;

  static FixedTypedVector EmptyFixedTypedVector() {
    static const uint8_t fixed_empty_vector[] = { 0 /* unused */ };
    return FixedTypedVector(fixed_empty_vector, 1, FBT_INT, 0);
  }
  bool IsTheEmptyFixedTypedVector() const {
    return data_ == FixedTypedVector::EmptyFixedTypedVector().data_;
  }

  Type ElementType() const { return type_; }
  uint8_t size() const { return len_; }

 private:
  Type type_;
  uint8_t len_;
};

class Map : public Vector {
 public:
  Map(const uint8_t *data, uint8_t byte_width) : Vector(data, byte_width) {}

  Reference operator[](const char *key) const;
  Reference operator[](const std::string &key) const;

  Vector Values() const { return Vector(data_, byte_width_); }

  TypedVector Keys() const {
    const size_t num_prefixed_fields = 3;
    auto keys_offset = data_ - byte_width_ * num_prefixed_fields;
    return TypedVector(Indirect(keys_offset, byte_width_),
                       static_cast<uint8_t>(
                           ReadUInt64(keys_offset + byte_width_, byte_width_)),
                       FBT_KEY);
  }

  static Map EmptyMap() {
    static const uint8_t empty_map[] = {
      0 /*keys_len*/, 0 /*keys_offset*/, 1 /*keys_width*/, 0 /*len*/
    };
    return Map(empty_map + 4, 1);
  }

  bool IsTheEmptyMap() const { return data_ == EmptyMap().data_; }
};

template<typename T>
void AppendToString(std::string &s, T &&v, bool keys_quoted) {
  s += "[ ";
  for (size_t i = 0; i < v.size(); i++) {
    if (i) s += ", ";
    v[i].ToString(true, keys_quoted, s);
  }
  s += " ]";
}

class Reference {
 public:
  Reference()
      : data_(nullptr), parent_width_(0), byte_width_(0), type_(FBT_NULL) {}

  Reference(const uint8_t *data, uint8_t parent_width, uint8_t byte_width,
            Type type)
      : data_(data),
        parent_width_(parent_width),
        byte_width_(byte_width),
        type_(type) {}

  Reference(const uint8_t *data, uint8_t parent_width, uint8_t packed_type)
      : data_(data),
        parent_width_(parent_width),
        byte_width_(1 << (packed_type & 3)),
        type_(static_cast<Type>(packed_type >> 2)) {
  }

  Type GetType() const { return type_; }

  bool IsNull() const { return type_ == FBT_NULL; }
  bool IsBool() const { return type_ == FBT_BOOL; }
  bool IsInt() const { return type_ == FBT_INT || type_ == FBT_INDIRECT_INT; }
  bool IsUInt() const {
    return type_ == FBT_UINT || type_ == FBT_INDIRECT_UINT;
  }
  bool IsIntOrUint() const { return IsInt() || IsUInt(); }
  bool IsFloat() const {
    return type_ == FBT_FLOAT || type_ == FBT_INDIRECT_FLOAT;
  }
  bool IsNumeric() const { return IsIntOrUint() || IsFloat(); }
  bool IsString() const { return type_ == FBT_STRING; }
  bool IsKey() const { return type_ == FBT_KEY; }
  bool IsVector() const { return type_ == FBT_VECTOR || type_ == FBT_MAP; }
  bool IsUntypedVector() const { return type_ == FBT_VECTOR; }
  bool IsTypedVector() const { return flexbuffers::IsTypedVector(type_); }
  bool IsFixedTypedVector() const {
    return flexbuffers::IsFixedTypedVector(type_);
  }
  bool IsAnyVector() const {
    return (IsTypedVector() || IsFixedTypedVector() || IsVector());
  }
  bool IsMap() const { return type_ == FBT_MAP; }
  bool IsBlob() const { return type_ == FBT_BLOB; }
  bool AsBool() const {
    return (type_ == FBT_BOOL ? ReadUInt64(data_, parent_width_)
                              : AsUInt64()) != 0;
  }

  // Reads any type as a int64_t. Never fails, does most sensible conversion.
  // Truncates floats, strings are attempted to be parsed for a number,
  // vectors/maps return their size. Returns 0 if all else fails.
  int64_t AsInt64() const {
    if (type_ == FBT_INT) {
      // A fast path for the common case.
      return ReadInt64(data_, parent_width_);
    } else
      switch (type_) {
        case FBT_INDIRECT_INT: return ReadInt64(Indirect(), byte_width_);
        case FBT_UINT: return ReadUInt64(data_, parent_width_);
        case FBT_INDIRECT_UINT: return ReadUInt64(Indirect(), byte_width_);
        case FBT_FLOAT:
          return static_cast<int64_t>(ReadDouble(data_, parent_width_));
        case FBT_INDIRECT_FLOAT:
          return static_cast<int64_t>(ReadDouble(Indirect(), byte_width_));
        case FBT_NULL: return 0;
        case FBT_STRING: return flatbuffers::StringToInt(AsString().c_str());
        case FBT_VECTOR: return static_cast<int64_t>(AsVector().size());
        case FBT_BOOL: return ReadInt64(data_, parent_width_);
        default:
          // Convert other things to int.
          return 0;
      }
  }

  // TODO: could specialize these to not use AsInt64() if that saves
  // extension ops in generated code, and use a faster op than ReadInt64.
  int32_t AsInt32() const { return static_cast<int32_t>(AsInt64()); }
  int16_t AsInt16() const { return static_cast<int16_t>(AsInt64()); }
  int8_t AsInt8() const { return static_cast<int8_t>(AsInt64()); }

  uint64_t AsUInt64() const {
    if (type_ == FBT_UINT) {
      // A fast path for the common case.
      return ReadUInt64(data_, parent_width_);
    } else
      switch (type_) {
        case FBT_INDIRECT_UINT: return ReadUInt64(Indirect(), byte_width_);
        case FBT_INT: return ReadInt64(data_, parent_width_);
        case FBT_INDIRECT_INT: return ReadInt64(Indirect(), byte_width_);
        case FBT_FLOAT:
          return static_cast<uint64_t>(ReadDouble(data_, parent_width_));
        case FBT_INDIRECT_FLOAT:
          return static_cast<uint64_t>(ReadDouble(Indirect(), byte_width_));
        case FBT_NULL: return 0;
        case FBT_STRING: return flatbuffers::StringToUInt(AsString().c_str());
        case FBT_VECTOR: return static_cast<uint64_t>(AsVector().size());
        case FBT_BOOL: return ReadUInt64(data_, parent_width_);
        default:
          // Convert other things to uint.
          return 0;
      }
  }

  uint32_t AsUInt32() const { return static_cast<uint32_t>(AsUInt64()); }
  uint16_t AsUInt16() const { return static_cast<uint16_t>(AsUInt64()); }
  uint8_t AsUInt8() const { return static_cast<uint8_t>(AsUInt64()); }

  double AsDouble() const {
    if (type_ == FBT_FLOAT) {
      // A fast path for the common case.
      return ReadDouble(data_, parent_width_);
    } else
      switch (type_) {
        case FBT_INDIRECT_FLOAT: return ReadDouble(Indirect(), byte_width_);
        case FBT_INT:
          return static_cast<double>(ReadInt64(data_, parent_width_));
        case FBT_UINT:
          return static_cast<double>(ReadUInt64(data_, parent_width_));
        case FBT_INDIRECT_INT:
          return static_cast<double>(ReadInt64(Indirect(), byte_width_));
        case FBT_INDIRECT_UINT:
          return static_cast<double>(ReadUInt64(Indirect(), byte_width_));
        case FBT_NULL: return 0.0;
        case FBT_STRING: {
          double d;
          flatbuffers::StringToNumber(AsString().c_str(), &d);
          return d;
        }
        case FBT_VECTOR: return static_cast<double>(AsVector().size());
        case FBT_BOOL:
          return static_cast<double>(ReadUInt64(data_, parent_width_));
        default:
          // Convert strings and other things to float.
          return 0;
      }
  }

  float AsFloat() const { return static_cast<float>(AsDouble()); }

  const char *AsKey() const {
    if (type_ == FBT_KEY || type_ == FBT_STRING) {
      return reinterpret_cast<const char *>(Indirect());
    } else {
      return "";
    }
  }

  // This function returns the empty string if you try to read something that
  // is not a string or key.
  String AsString() const {
    if (type_ == FBT_STRING) {
      return String(Indirect(), byte_width_);
    } else if (type_ == FBT_KEY) {
      auto key = Indirect();
      return String(key, byte_width_,
                    strlen(reinterpret_cast<const char *>(key)));
    } else {
      return String::EmptyString();
    }
  }

  // Unlike AsString(), this will convert any type to a std::string.
  std::string ToString() const {
    std::string s;
    ToString(false, false, s);
    return s;
  }

  // Convert any type to a JSON-like string. strings_quoted determines if
  // string values at the top level receive "" quotes (inside other values
  // they always do). keys_quoted determines if keys are quoted, at any level.
  // TODO(wvo): add further options to have indentation/newlines.
  void ToString(bool strings_quoted, bool keys_quoted, std::string &s) const {
    if (type_ == FBT_STRING) {
      String str(Indirect(), byte_width_);
      if (strings_quoted) {
        flatbuffers::EscapeString(str.c_str(), str.length(), &s, true, false);
      } else {
        s.append(str.c_str(), str.length());
      }
    } else if (IsKey()) {
      auto str = AsKey();
      if (keys_quoted) {
        flatbuffers::EscapeString(str, strlen(str), &s, true, false);
      } else {
        s += str;
      }
    } else if (IsInt()) {
      s += flatbuffers::NumToString(AsInt64());
    } else if (IsUInt()) {
      s += flatbuffers::NumToString(AsUInt64());
    } else if (IsFloat()) {
      s += flatbuffers::NumToString(AsDouble());
    } else if (IsNull()) {
      s += "null";
    } else if (IsBool()) {
      s += AsBool() ? "true" : "false";
    } else if (IsMap()) {
      s += "{ ";
      auto m = AsMap();
      auto keys = m.Keys();
      auto vals = m.Values();
      for (size_t i = 0; i < keys.size(); i++) {
        bool kq = keys_quoted;
        if (!kq) {
          // FlexBuffers keys may contain arbitrary characters, only allow
          // unquoted if it looks like an "identifier":
          const char *p = keys[i].AsKey();
          if (!flatbuffers::is_alpha(*p) && *p != '_') {
            kq = true;
          } else {
            while (*++p) {
              if (!flatbuffers::is_alnum(*p) && *p != '_') {
                kq = true;
                break;
              }
            }
          }
        }
        keys[i].ToString(true, kq, s);
        s += ": ";
        vals[i].ToString(true, keys_quoted, s);
        if (i < keys.size() - 1) s += ", ";
      }
      s += " }";
    } else if (IsVector()) {
      AppendToString<Vector>(s, AsVector(), keys_quoted);
    } else if (IsTypedVector()) {
      AppendToString<TypedVector>(s, AsTypedVector(), keys_quoted);
    } else if (IsFixedTypedVector()) {
      AppendToString<FixedTypedVector>(s, AsFixedTypedVector(), keys_quoted);
    } else if (IsBlob()) {
      auto blob = AsBlob();
      flatbuffers::EscapeString(reinterpret_cast<const char *>(blob.data()),
                                blob.size(), &s, true, false);
    } else {
      s += "(?)";
    }
  }

  // This function returns the empty blob if you try to read a not-blob.
  // Strings can be viewed as blobs too.
  Blob AsBlob() const {
    if (type_ == FBT_BLOB || type_ == FBT_STRING) {
      return Blob(Indirect(), byte_width_);
    } else {
      return Blob::EmptyBlob();
    }
  }

  // This function returns the empty vector if you try to read a not-vector.
  // Maps can be viewed as vectors too.
  Vector AsVector() const {
    if (type_ == FBT_VECTOR || type_ == FBT_MAP) {
      return Vector(Indirect(), byte_width_);
    } else {
      return Vector::EmptyVector();
    }
  }

  TypedVector AsTypedVector() const {
    if (IsTypedVector()) {
      auto tv =
          TypedVector(Indirect(), byte_width_, ToTypedVectorElementType(type_));
      if (tv.type_ == FBT_STRING) {
        // These can't be accessed as strings, since we don't know the bit-width
        // of the size field, see the declaration of
        // FBT_VECTOR_STRING_DEPRECATED above for details.
        // We change the type here to be keys, which are a subtype of strings,
        // and will ignore the size field. This will truncate strings with
        // embedded nulls.
        tv.type_ = FBT_KEY;
      }
      return tv;
    } else {
      return TypedVector::EmptyTypedVector();
    }
  }

  FixedTypedVector AsFixedTypedVector() const {
    if (IsFixedTypedVector()) {
      uint8_t len = 0;
      auto vtype = ToFixedTypedVectorElementType(type_, &len);
      return FixedTypedVector(Indirect(), byte_width_, vtype, len);
    } else {
      return FixedTypedVector::EmptyFixedTypedVector();
    }
  }

  Map AsMap() const {
    if (type_ == FBT_MAP) {
      return Map(Indirect(), byte_width_);
    } else {
      return Map::EmptyMap();
    }
  }

  template<typename T> T As() const;

  // Experimental: Mutation functions.
  // These allow scalars in an already created buffer to be updated in-place.
  // Since by default scalars are stored in the smallest possible space,
  // the new value may not fit, in which case these functions return false.
  // To avoid this, you can construct the values you intend to mutate using
  // Builder::ForceMinimumBitWidth.
  bool MutateInt(int64_t i) {
    if (type_ == FBT_INT) {
      return Mutate(data_, i, parent_width_, WidthI(i));
    } else if (type_ == FBT_INDIRECT_INT) {
      return Mutate(Indirect(), i, byte_width_, WidthI(i));
    } else if (type_ == FBT_UINT) {
      auto u = static_cast<uint64_t>(i);
      return Mutate(data_, u, parent_width_, WidthU(u));
    } else if (type_ == FBT_INDIRECT_UINT) {
      auto u = static_cast<uint64_t>(i);
      return Mutate(Indirect(), u, byte_width_, WidthU(u));
    } else {
      return false;
    }
  }

  bool MutateBool(bool b) {
    return type_ == FBT_BOOL && Mutate(data_, b, parent_width_, BIT_WIDTH_8);
  }

  bool MutateUInt(uint64_t u) {
    if (type_ == FBT_UINT) {
      return Mutate(data_, u, parent_width_, WidthU(u));
    } else if (type_ == FBT_INDIRECT_UINT) {
      return Mutate(Indirect(), u, byte_width_, WidthU(u));
    } else if (type_ == FBT_INT) {
      auto i = static_cast<int64_t>(u);
      return Mutate(data_, i, parent_width_, WidthI(i));
    } else if (type_ == FBT_INDIRECT_INT) {
      auto i = static_cast<int64_t>(u);
      return Mutate(Indirect(), i, byte_width_, WidthI(i));
    } else {
      return false;
    }
  }

  bool MutateFloat(float f) {
    if (type_ == FBT_FLOAT) {
      return MutateF(data_, f, parent_width_, BIT_WIDTH_32);
    } else if (type_ == FBT_INDIRECT_FLOAT) {
      return MutateF(Indirect(), f, byte_width_, BIT_WIDTH_32);
    } else {
      return false;
    }
  }

  bool MutateFloat(double d) {
    if (type_ == FBT_FLOAT) {
      return MutateF(data_, d, parent_width_, WidthF(d));
    } else if (type_ == FBT_INDIRECT_FLOAT) {
      return MutateF(Indirect(), d, byte_width_, WidthF(d));
    } else {
      return false;
    }
  }

  bool MutateString(const char *str, size_t len) {
    auto s = AsString();
    if (s.IsTheEmptyString()) return false;
    // This is very strict, could allow shorter strings, but that creates
    // garbage.
    if (s.length() != len) return false;
    memcpy(const_cast<char *>(s.c_str()), str, len);
    return true;
  }
  bool MutateString(const char *str) { return MutateString(str, strlen(str)); }
  bool MutateString(const std::string &str) {
    return MutateString(str.data(), str.length());
  }

 private:
  const uint8_t *Indirect() const {
    return flexbuffers::Indirect(data_, parent_width_);
  }

  template<typename T>
  bool Mutate(const uint8_t *dest, T t, size_t byte_width,
              BitWidth value_width) {
    auto fits = static_cast<size_t>(static_cast<size_t>(1U) << value_width) <=
                byte_width;
    if (fits) {
      t = flatbuffers::EndianScalar(t);
      memcpy(const_cast<uint8_t *>(dest), &t, byte_width);
    }
    return fits;
  }

  template<typename T>
  bool MutateF(const uint8_t *dest, T t, size_t byte_width,
               BitWidth value_width) {
    if (byte_width == sizeof(double))
      return Mutate(dest, static_cast<double>(t), byte_width, value_width);
    if (byte_width == sizeof(float))
      return Mutate(dest, static_cast<float>(t), byte_width, value_width);
    FLATBUFFERS_ASSERT(false);
    return false;
  }

  friend class Verifier;

  const uint8_t *data_;
  uint8_t parent_width_;
  uint8_t byte_width_;
  Type type_;
};

// Template specialization for As().
template<> inline bool Reference::As<bool>() const { return AsBool(); }

template<> inline int8_t Reference::As<int8_t>() const { return AsInt8(); }
template<> inline int16_t Reference::As<int16_t>() const { return AsInt16(); }
template<> inline int32_t Reference::As<int32_t>() const { return AsInt32(); }
template<> inline int64_t Reference::As<int64_t>() const { return AsInt64(); }

template<> inline uint8_t Reference::As<uint8_t>() const { return AsUInt8(); }
template<> inline uint16_t Reference::As<uint16_t>() const {
  return AsUInt16();
}
template<> inline uint32_t Reference::As<uint32_t>() const {
  return AsUInt32();
}
template<> inline uint64_t Reference::As<uint64_t>() const {
  return AsUInt64();
}

template<> inline double Reference::As<double>() const { return AsDouble(); }
template<> inline float Reference::As<float>() const { return AsFloat(); }

template<> inline String Reference::As<String>() const { return AsString(); }
template<> inline std::string Reference::As<std::string>() const {
  return AsString().str();
}

template<> inline Blob Reference::As<Blob>() const { return AsBlob(); }
template<> inline Vector Reference::As<Vector>() const { return AsVector(); }
template<> inline TypedVector Reference::As<TypedVector>() const {
  return AsTypedVector();
}
template<> inline FixedTypedVector Reference::As<FixedTypedVector>() const {
  return AsFixedTypedVector();
}
template<> inline Map Reference::As<Map>() const { return AsMap(); }

inline uint8_t PackedType(BitWidth bit_width, Type type) {
  return static_cast<uint8_t>(bit_width | (type << 2));
}

inline uint8_t NullPackedType() { return PackedType(BIT_WIDTH_8, FBT_NULL); }

// Vector accessors.
// Note: if you try to access outside of bounds, you get a Null value back
// instead. Normally this would be an assert, but since this is "dynamically
// typed" data, you may not want that (someone sends you a 2d vector and you
// wanted 3d).
// The Null converts seamlessly into a default value for any other type.
// TODO(wvo): Could introduce an #ifdef that makes this into an assert?
inline Reference Vector::operator[](size_t i) const {
  auto len = size();
  if (i >= len) return Reference(nullptr, 1, NullPackedType());
  auto packed_type = (data_ + len * byte_width_)[i];
  auto elem = data_ + i * byte_width_;
  return Reference(elem, byte_width_, packed_type);
}

inline Reference TypedVector::operator[](size_t i) const {
  auto len = size();
  if (i >= len) return Reference(nullptr, 1, NullPackedType());
  auto elem = data_ + i * byte_width_;
  return Reference(elem, byte_width_, 1, type_);
}

inline Reference FixedTypedVector::operator[](size_t i) const {
  if (i >= len_) return Reference(nullptr, 1, NullPackedType());
  auto elem = data_ + i * byte_width_;
  return Reference(elem, byte_width_, 1, type_);
}

template<typename T> int KeyCompare(const void *key, const void *elem) {
  auto str_elem = reinterpret_cast<const char *>(
      Indirect<T>(reinterpret_cast<const uint8_t *>(elem)));
  auto skey = reinterpret_cast<const char *>(key);
  return strcmp(skey, str_elem);
}

inline Reference Map::operator[](const char *key) const {
  auto keys = Keys();
  // We can't pass keys.byte_width_ to the comparison function, so we have
  // to pick the right one ahead of time.
  int (*comp)(const void *, const void *) = nullptr;
  switch (keys.byte_width_) {
    case 1: comp = KeyCompare<uint8_t>; break;
    case 2: comp = KeyCompare<uint16_t>; break;
    case 4: comp = KeyCompare<uint32_t>; break;
    case 8: comp = KeyCompare<uint64_t>; break;
    default: FLATBUFFERS_ASSERT(false); return Reference();
  }
  auto res = std::bsearch(key, keys.data_, keys.size(), keys.byte_width_, comp);
  if (!res) return Reference(nullptr, 1, NullPackedType());
  auto i = (reinterpret_cast<uint8_t *>(res) - keys.data_) / keys.byte_width_;
  return (*static_cast<const Vector *>(this))[i];
}

inline Reference Map::operator[](const std::string &key) const {
  return (*this)[key.c_str()];
}

inline Reference GetRoot(const uint8_t *buffer, size_t size) {
  // See Finish() below for the serialization counterpart of this.
  // The root starts at the end of the buffer, so we parse backwards from there.
  auto end = buffer + size;
  auto byte_width = *--end;
  auto packed_type = *--end;
  end -= byte_width;  // The root data item.
  return Reference(end, byte_width, packed_type);
}

inline Reference GetRoot(const std::vector<uint8_t> &buffer) {
  return GetRoot(buffer.data(), buffer.size());
}

// Flags that configure how the Builder behaves.
// The "Share" flags determine if the Builder automatically tries to pool
// this type. Pooling can reduce the size of serialized data if there are
// multiple maps of the same kind, at the expense of slightly slower
// serialization (the cost of lookups) and more memory use (std::set).
// By default this is on for keys, but off for strings.
// Turn keys off if you have e.g. only one map.
// Turn strings on if you expect many non-unique string values.
// Additionally, sharing key vectors can save space if you have maps with
// identical field populations.
enum BuilderFlag {
  BUILDER_FLAG_NONE = 0,
  BUILDER_FLAG_SHARE_KEYS = 1,
  BUILDER_FLAG_SHARE_STRINGS = 2,
  BUILDER_FLAG_SHARE_KEYS_AND_STRINGS = 3,
  BUILDER_FLAG_SHARE_KEY_VECTORS = 4,
  BUILDER_FLAG_SHARE_ALL = 7,
};

class Builder FLATBUFFERS_FINAL_CLASS {
 public:
  Builder(size_t initial_size = 256,
          BuilderFlag flags = BUILDER_FLAG_SHARE_KEYS)
      : buf_(initial_size),
        finished_(false),
        has_duplicate_keys_(false),
        flags_(flags),
        force_min_bit_width_(BIT_WIDTH_8),
        key_pool(KeyOffsetCompare(buf_)),
        string_pool(StringOffsetCompare(buf_)) {
    buf_.clear();
  }

#ifdef FLATBUFFERS_DEFAULT_DECLARATION
  Builder(Builder &&) = default;
  Builder &operator=(Builder &&) = default;
#endif

  /// @brief Get the serialized buffer (after you call `Finish()`).
  /// @return Returns a vector owned by this class.
  const std::vector<uint8_t> &GetBuffer() const {
    Finished();
    return buf_;
  }

  // Size of the buffer. Does not include unfinished values.
  size_t GetSize() const { return buf_.size(); }

  // Reset all state so we can re-use the buffer.
  void Clear() {
    buf_.clear();
    stack_.clear();
    finished_ = false;
    // flags_ remains as-is;
    force_min_bit_width_ = BIT_WIDTH_8;
    key_pool.clear();
    string_pool.clear();
  }

  // All value constructing functions below have two versions: one that
  // takes a key (for placement inside a map) and one that doesn't (for inside
  // vectors and elsewhere).

  void Null() { stack_.push_back(Value()); }
  void Null(const char *key) {
    Key(key);
    Null();
  }

  void Int(int64_t i) { stack_.push_back(Value(i, FBT_INT, WidthI(i))); }
  void Int(const char *key, int64_t i) {
    Key(key);
    Int(i);
  }

  void UInt(uint64_t u) { stack_.push_back(Value(u, FBT_UINT, WidthU(u))); }
  void UInt(const char *key, uint64_t u) {
    Key(key);
    UInt(u);
  }

  void Float(float f) { stack_.push_back(Value(f)); }
  void Float(const char *key, float f) {
    Key(key);
    Float(f);
  }

  void Double(double f) { stack_.push_back(Value(f)); }
  void Double(const char *key, double d) {
    Key(key);
    Double(d);
  }

  void Bool(bool b) { stack_.push_back(Value(b)); }
  void Bool(const char *key, bool b) {
    Key(key);
    Bool(b);
  }

  void IndirectInt(int64_t i) { PushIndirect(i, FBT_INDIRECT_INT, WidthI(i)); }
  void IndirectInt(const char *key, int64_t i) {
    Key(key);
    IndirectInt(i);
  }

  void IndirectUInt(uint64_t u) {
    PushIndirect(u, FBT_INDIRECT_UINT, WidthU(u));
  }
  void IndirectUInt(const char *key, uint64_t u) {
    Key(key);
    IndirectUInt(u);
  }

  void IndirectFloat(float f) {
    PushIndirect(f, FBT_INDIRECT_FLOAT, BIT_WIDTH_32);
  }
  void IndirectFloat(const char *key, float f) {
    Key(key);
    IndirectFloat(f);
  }

  void IndirectDouble(double f) {
    PushIndirect(f, FBT_INDIRECT_FLOAT, WidthF(f));
  }
  void IndirectDouble(const char *key, double d) {
    Key(key);
    IndirectDouble(d);
  }

  size_t Key(const char *str, size_t len) {
    auto sloc = buf_.size();
    WriteBytes(str, len + 1);
    if (flags_ & BUILDER_FLAG_SHARE_KEYS) {
      auto it = key_pool.find(sloc);
      if (it != key_pool.end()) {
        // Already in the buffer. Remove key we just serialized, and use
        // existing offset instead.
        buf_.resize(sloc);
        sloc = *it;
      } else {
        key_pool.insert(sloc);
      }
    }
    stack_.push_back(Value(static_cast<uint64_t>(sloc), FBT_KEY, BIT_WIDTH_8));
    return sloc;
  }

  size_t Key(const char *str) { return Key(str, strlen(str)); }
  size_t Key(const std::string &str) { return Key(str.c_str(), str.size()); }

  size_t String(const char *str, size_t len) {
    auto reset_to = buf_.size();
    auto sloc = CreateBlob(str, len, 1, FBT_STRING);
    if (flags_ & BUILDER_FLAG_SHARE_STRINGS) {
      StringOffset so(sloc, len);
      auto it = string_pool.find(so);
      if (it != string_pool.end()) {
        // Already in the buffer. Remove string we just serialized, and use
        // existing offset instead.
        buf_.resize(reset_to);
        sloc = it->first;
        stack_.back().u_ = sloc;
      } else {
        string_pool.insert(so);
      }
    }
    return sloc;
  }
  size_t String(const char *str) { return String(str, strlen(str)); }
  size_t String(const std::string &str) {
    return String(str.c_str(), str.size());
  }
  void String(const flexbuffers::String &str) {
    String(str.c_str(), str.length());
  }

  void String(const char *key, const char *str) {
    Key(key);
    String(str);
  }
  void String(const char *key, const std::string &str) {
    Key(key);
    String(str);
  }
  void String(const char *key, const flexbuffers::String &str) {
    Key(key);
    String(str);
  }

  size_t Blob(const void *data, size_t len) {
    return CreateBlob(data, len, 0, FBT_BLOB);
  }
  size_t Blob(const std::vector<uint8_t> &v) {
    return CreateBlob(v.data(), v.size(), 0, FBT_BLOB);
  }

  void Blob(const char *key, const void *data, size_t len) {
    Key(key);
    Blob(data, len);
  }
  void Blob(const char *key, const std::vector<uint8_t> &v) {
    Key(key);
    Blob(v);
  }

  // TODO(wvo): support all the FlexBuffer types (like flexbuffers::String),
  // e.g. Vector etc. Also in overloaded versions.
  // Also some FlatBuffers types?

  size_t StartVector() { return stack_.size(); }
  size_t StartVector(const char *key) {
    Key(key);
    return stack_.size();
  }
  size_t StartMap() { return stack_.size(); }
  size_t StartMap(const char *key) {
    Key(key);
    return stack_.size();
  }

  // TODO(wvo): allow this to specify an alignment greater than the natural
  // alignment.
  size_t EndVector(size_t start, bool typed, bool fixed) {
    auto vec = CreateVector(start, stack_.size() - start, 1, typed, fixed);
    // Remove temp elements and return vector.
    stack_.resize(start);
    stack_.push_back(vec);
    return static_cast<size_t>(vec.u_);
  }

  size_t EndMap(size_t start) {
    // We should have interleaved keys and values on the stack.
    // Make sure it is an even number:
    auto len = stack_.size() - start;
    FLATBUFFERS_ASSERT(!(len & 1));
    len /= 2;
    // Make sure keys are all strings:
    for (auto key = start; key < stack_.size(); key += 2) {
      FLATBUFFERS_ASSERT(stack_[key].type_ == FBT_KEY);
    }
    // Now sort values, so later we can do a binary search lookup.
    // We want to sort 2 array elements at a time.
    struct TwoValue {
      Value key;
      Value val;
    };
    // TODO(wvo): strict aliasing?
    // TODO(wvo): allow the caller to indicate the data is already sorted
    // for maximum efficiency? With an assert to check sortedness to make sure
    // we're not breaking binary search.
    // Or, we can track if the map is sorted as keys are added which would be
    // be quite cheap (cheaper than checking it here), so we can skip this
    // step automatically when appliccable, and encourage people to write in
    // sorted fashion.
    // std::sort is typically already a lot faster on sorted data though.
    auto dict = reinterpret_cast<TwoValue *>(stack_.data() + start);
    std::sort(
        dict, dict + len, [&](const TwoValue &a, const TwoValue &b) -> bool {
          auto as = reinterpret_cast<const char *>(buf_.data() + a.key.u_);
          auto bs = reinterpret_cast<const char *>(buf_.data() + b.key.u_);
          auto comp = strcmp(as, bs);
          // We want to disallow duplicate keys, since this results in a
          // map where values cannot be found.
          // But we can't assert here (since we don't want to fail on
          // random JSON input) or have an error mechanism.
          // Instead, we set has_duplicate_keys_ in the builder to
          // signal this.
          // TODO: Have to check for pointer equality, as some sort
          // implementation apparently call this function with the same
          // element?? Why?
          if (!comp && &a != &b) has_duplicate_keys_ = true;
          return comp < 0;
        });
    // First create a vector out of all keys.
    // TODO(wvo): if kBuilderFlagShareKeyVectors is true, see if we can share
    // the first vector.
    auto keys = CreateVector(start, len, 2, true, false);
    auto vec = CreateVector(start + 1, len, 2, false, false, &keys);
    // Remove temp elements and return map.
    stack_.resize(start);
    stack_.push_back(vec);
    return static_cast<size_t>(vec.u_);
  }

  // Call this after EndMap to see if the map had any duplicate keys.
  // Any map with such keys won't be able to retrieve all values.
  bool HasDuplicateKeys() const { return has_duplicate_keys_; }

  template<typename F> size_t Vector(F f) {
    auto start = StartVector();
    f();
    return EndVector(start, false, false);
  }
  template<typename F, typename T> size_t Vector(F f, T &state) {
    auto start = StartVector();
    f(state);
    return EndVector(start, false, false);
  }
  template<typename F> size_t Vector(const char *key, F f) {
    auto start = StartVector(key);
    f();
    return EndVector(start, false, false);
  }
  template<typename F, typename T>
  size_t Vector(const char *key, F f, T &state) {
    auto start = StartVector(key);
    f(state);
    return EndVector(start, false, false);
  }

  template<typename T> void Vector(const T *elems, size_t len) {
    if (flatbuffers::is_scalar<T>::value) {
      // This path should be a lot quicker and use less space.
      ScalarVector(elems, len, false);
    } else {
      auto start = StartVector();
      for (size_t i = 0; i < len; i++) Add(elems[i]);
      EndVector(start, false, false);
    }
  }
  template<typename T>
  void Vector(const char *key, const T *elems, size_t len) {
    Key(key);
    Vector(elems, len);
  }
  template<typename T> void Vector(const std::vector<T> &vec) {
    Vector(vec.data(), vec.size());
  }

  template<typename F> size_t TypedVector(F f) {
    auto start = StartVector();
    f();
    return EndVector(start, true, false);
  }
  template<typename F, typename T> size_t TypedVector(F f, T &state) {
    auto start = StartVector();
    f(state);
    return EndVector(start, true, false);
  }
  template<typename F> size_t TypedVector(const char *key, F f) {
    auto start = StartVector(key);
    f();
    return EndVector(start, true, false);
  }
  template<typename F, typename T>
  size_t TypedVector(const char *key, F f, T &state) {
    auto start = StartVector(key);
    f(state);
    return EndVector(start, true, false);
  }

  template<typename T> size_t FixedTypedVector(const T *elems, size_t len) {
    // We only support a few fixed vector lengths. Anything bigger use a
    // regular typed vector.
    FLATBUFFERS_ASSERT(len >= 2 && len <= 4);
    // And only scalar values.
    static_assert(flatbuffers::is_scalar<T>::value, "Unrelated types");
    return ScalarVector(elems, len, true);
  }

  template<typename T>
  size_t FixedTypedVector(const char *key, const T *elems, size_t len) {
    Key(key);
    return FixedTypedVector(elems, len);
  }

  template<typename F> size_t Map(F f) {
    auto start = StartMap();
    f();
    return EndMap(start);
  }
  template<typename F, typename T> size_t Map(F f, T &state) {
    auto start = StartMap();
    f(state);
    return EndMap(start);
  }
  template<typename F> size_t Map(const char *key, F f) {
    auto start = StartMap(key);
    f();
    return EndMap(start);
  }
  template<typename F, typename T> size_t Map(const char *key, F f, T &state) {
    auto start = StartMap(key);
    f(state);
    return EndMap(start);
  }
  template<typename T> void Map(const std::map<std::string, T> &map) {
    auto start = StartMap();
    for (auto it = map.begin(); it != map.end(); ++it)
      Add(it->first.c_str(), it->second);
    EndMap(start);
  }

  // If you wish to share a value explicitly (a value not shared automatically
  // through one of the BUILDER_FLAG_SHARE_* flags) you can do so with these
  // functions. Or if you wish to turn those flags off for performance reasons
  // and still do some explicit sharing. For example:
  // builder.IndirectDouble(M_PI);
  // auto id = builder.LastValue();  // Remember where we stored it.
  // .. more code goes here ..
  // builder.ReuseValue(id);  // Refers to same double by offset.
  // LastValue works regardless of whether the value has a key or not.
  // Works on any data type.
  struct Value;
  Value LastValue() { return stack_.back(); }
  void ReuseValue(Value v) { stack_.push_back(v); }
  void ReuseValue(const char *key, Value v) {
    Key(key);
    ReuseValue(v);
  }

  // Overloaded Add that tries to call the correct function above.
  void Add(int8_t i) { Int(i); }
  void Add(int16_t i) { Int(i); }
  void Add(int32_t i) { Int(i); }
  void Add(int64_t i) { Int(i); }
  void Add(uint8_t u) { UInt(u); }
  void Add(uint16_t u) { UInt(u); }
  void Add(uint32_t u) { UInt(u); }
  void Add(uint64_t u) { UInt(u); }
  void Add(float f) { Float(f); }
  void Add(double d) { Double(d); }
  void Add(bool b) { Bool(b); }
  void Add(const char *str) { String(str); }
  void Add(const std::string &str) { String(str); }
  void Add(const flexbuffers::String &str) { String(str); }

  template<typename T> void Add(const std::vector<T> &vec) { Vector(vec); }

  template<typename T> void Add(const char *key, const T &t) {
    Key(key);
    Add(t);
  }

  template<typename T> void Add(const std::map<std::string, T> &map) {
    Map(map);
  }

  template<typename T> void operator+=(const T &t) { Add(t); }

  // This function is useful in combination with the Mutate* functions above.
  // It forces elements of vectors and maps to have a minimum size, such that
  // they can later be updated without failing.
  // Call with no arguments to reset.
  void ForceMinimumBitWidth(BitWidth bw = BIT_WIDTH_8) {
    force_min_bit_width_ = bw;
  }

  void Finish() {
    // If you hit this assert, you likely have objects that were never included
    // in a parent. You need to have exactly one root to finish a buffer.
    // Check your Start/End calls are matched, and all objects are inside
    // some other object.
    FLATBUFFERS_ASSERT(stack_.size() == 1);

    // Write root value.
    auto byte_width = Align(stack_[0].ElemWidth(buf_.size(), 0));
    WriteAny(stack_[0], byte_width);
    // Write root type.
    Write(stack_[0].StoredPackedType(), 1);
    // Write root size. Normally determined by parent, but root has no parent :)
    Write(byte_width, 1);

    finished_ = true;
  }

 private:
  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
    // Builder::Finish with your root object.
    FLATBUFFERS_ASSERT(finished_);
  }

  // Align to prepare for writing a scalar with a certain size.
  uint8_t Align(BitWidth alignment) {
    auto byte_width = 1U << alignment;
    buf_.insert(buf_.end(), flatbuffers::PaddingBytes(buf_.size(), byte_width),
                0);
    return static_cast<uint8_t>(byte_width);
  }

  void WriteBytes(const void *val, size_t size) {
    buf_.insert(buf_.end(), reinterpret_cast<const uint8_t *>(val),
                reinterpret_cast<const uint8_t *>(val) + size);
  }

  template<typename T> void Write(T val, size_t byte_width) {
    FLATBUFFERS_ASSERT(sizeof(T) >= byte_width);
    val = flatbuffers::EndianScalar(val);
    WriteBytes(&val, byte_width);
  }

  void WriteDouble(double f, uint8_t byte_width) {
    switch (byte_width) {
      case 8: Write(f, byte_width); break;
      case 4: Write(static_cast<float>(f), byte_width); break;
      // case 2: Write(static_cast<half>(f), byte_width); break;
      // case 1: Write(static_cast<quarter>(f), byte_width); break;
      default: FLATBUFFERS_ASSERT(0);
    }
  }

  void WriteOffset(uint64_t o, uint8_t byte_width) {
    auto reloff = buf_.size() - o;
    FLATBUFFERS_ASSERT(byte_width == 8 || reloff < 1ULL << (byte_width * 8));
    Write(reloff, byte_width);
  }

  template<typename T> void PushIndirect(T val, Type type, BitWidth bit_width) {
    auto byte_width = Align(bit_width);
    auto iloc = buf_.size();
    Write(val, byte_width);
    stack_.push_back(Value(static_cast<uint64_t>(iloc), type, bit_width));
  }

  static BitWidth WidthB(size_t byte_width) {
    switch (byte_width) {
      case 1: return BIT_WIDTH_8;
      case 2: return BIT_WIDTH_16;
      case 4: return BIT_WIDTH_32;
      case 8: return BIT_WIDTH_64;
      default: FLATBUFFERS_ASSERT(false); return BIT_WIDTH_64;
    }
  }

  template<typename T> static Type GetScalarType() {
    static_assert(flatbuffers::is_scalar<T>::value, "Unrelated types");
    return flatbuffers::is_floating_point<T>::value
               ? FBT_FLOAT
               : flatbuffers::is_same<T, bool>::value
                     ? FBT_BOOL
                     : (flatbuffers::is_unsigned<T>::value ? FBT_UINT
                                                           : FBT_INT);
  }

 public:
  // This was really intended to be private, except for LastValue/ReuseValue.
  struct Value {
    union {
      int64_t i_;
      uint64_t u_;
      double f_;
    };

    Type type_;

    // For scalars: of itself, for vector: of its elements, for string: length.
    BitWidth min_bit_width_;

    Value() : i_(0), type_(FBT_NULL), min_bit_width_(BIT_WIDTH_8) {}

    Value(bool b)
        : u_(static_cast<uint64_t>(b)),
          type_(FBT_BOOL),
          min_bit_width_(BIT_WIDTH_8) {}

    Value(int64_t i, Type t, BitWidth bw)
        : i_(i), type_(t), min_bit_width_(bw) {}
    Value(uint64_t u, Type t, BitWidth bw)
        : u_(u), type_(t), min_bit_width_(bw) {}

    Value(float f)
        : f_(static_cast<double>(f)),
          type_(FBT_FLOAT),
          min_bit_width_(BIT_WIDTH_32) {}
    Value(double f) : f_(f), type_(FBT_FLOAT), min_bit_width_(WidthF(f)) {}

    uint8_t StoredPackedType(BitWidth parent_bit_width_ = BIT_WIDTH_8) const {
      return PackedType(StoredWidth(parent_bit_width_), type_);
    }

    BitWidth ElemWidth(size_t buf_size, size_t elem_index) const {
      if (IsInline(type_)) {
        return min_bit_width_;
      } else {
        // We have an absolute offset, but want to store a relative offset
        // elem_index elements beyond the current buffer end. Since whether
        // the relative offset fits in a certain byte_width depends on
        // the size of the elements before it (and their alignment), we have
        // to test for each size in turn.
        for (size_t byte_width = 1;
             byte_width <= sizeof(flatbuffers::largest_scalar_t);
             byte_width *= 2) {
          // Where are we going to write this offset?
          auto offset_loc = buf_size +
                            flatbuffers::PaddingBytes(buf_size, byte_width) +
                            elem_index * byte_width;
          // Compute relative offset.
          auto offset = offset_loc - u_;
          // Does it fit?
          auto bit_width = WidthU(offset);
          if (static_cast<size_t>(static_cast<size_t>(1U) << bit_width) ==
              byte_width)
            return bit_width;
        }
        FLATBUFFERS_ASSERT(false);  // Must match one of the sizes above.
        return BIT_WIDTH_64;
      }
    }

    BitWidth StoredWidth(BitWidth parent_bit_width_ = BIT_WIDTH_8) const {
      if (IsInline(type_)) {
        return (std::max)(min_bit_width_, parent_bit_width_);
      } else {
        return min_bit_width_;
      }
    }
  };

 private:
  void WriteAny(const Value &val, uint8_t byte_width) {
    switch (val.type_) {
      case FBT_NULL:
      case FBT_INT: Write(val.i_, byte_width); break;
      case FBT_BOOL:
      case FBT_UINT: Write(val.u_, byte_width); break;
      case FBT_FLOAT: WriteDouble(val.f_, byte_width); break;
      default: WriteOffset(val.u_, byte_width); break;
    }
  }

  size_t CreateBlob(const void *data, size_t len, size_t trailing, Type type) {
    auto bit_width = WidthU(len);
    auto byte_width = Align(bit_width);
    Write<uint64_t>(len, byte_width);
    auto sloc = buf_.size();
    WriteBytes(data, len + trailing);
    stack_.push_back(Value(static_cast<uint64_t>(sloc), type, bit_width));
    return sloc;
  }

  template<typename T>
  size_t ScalarVector(const T *elems, size_t len, bool fixed) {
    auto vector_type = GetScalarType<T>();
    auto byte_width = sizeof(T);
    auto bit_width = WidthB(byte_width);
    // If you get this assert, you're trying to write a vector with a size
    // field that is bigger than the scalars you're trying to write (e.g. a
    // byte vector > 255 elements). For such types, write a "blob" instead.
    // TODO: instead of asserting, could write vector with larger elements
    // instead, though that would be wasteful.
    FLATBUFFERS_ASSERT(WidthU(len) <= bit_width);
    Align(bit_width);
    if (!fixed) Write<uint64_t>(len, byte_width);
    auto vloc = buf_.size();
    for (size_t i = 0; i < len; i++) Write(elems[i], byte_width);
    stack_.push_back(Value(static_cast<uint64_t>(vloc),
                           ToTypedVector(vector_type, fixed ? len : 0),
                           bit_width));
    return vloc;
  }

  Value CreateVector(size_t start, size_t vec_len, size_t step, bool typed,
                     bool fixed, const Value *keys = nullptr) {
    FLATBUFFERS_ASSERT(
        !fixed ||
        typed);  // typed=false, fixed=true combination is not supported.
    // Figure out smallest bit width we can store this vector with.
    auto bit_width = (std::max)(force_min_bit_width_, WidthU(vec_len));
    auto prefix_elems = 1;
    if (keys) {
      // If this vector is part of a map, we will pre-fix an offset to the keys
      // to this vector.
      bit_width = (std::max)(bit_width, keys->ElemWidth(buf_.size(), 0));
      prefix_elems += 2;
    }
    Type vector_type = FBT_KEY;
    // Check bit widths and types for all elements.
    for (size_t i = start; i < stack_.size(); i += step) {
      auto elem_width =
          stack_[i].ElemWidth(buf_.size(), i - start + prefix_elems);
      bit_width = (std::max)(bit_width, elem_width);
      if (typed) {
        if (i == start) {
          vector_type = stack_[i].type_;
        } else {
          // If you get this assert, you are writing a typed vector with
          // elements that are not all the same type.
          FLATBUFFERS_ASSERT(vector_type == stack_[i].type_);
        }
      }
    }
    // If you get this assert, your typed types are not one of:
    // Int / UInt / Float / Key.
    FLATBUFFERS_ASSERT(!typed || IsTypedVectorElementType(vector_type));
    auto byte_width = Align(bit_width);
    // Write vector. First the keys width/offset if available, and size.
    if (keys) {
      WriteOffset(keys->u_, byte_width);
      Write<uint64_t>(1ULL << keys->min_bit_width_, byte_width);
    }
    if (!fixed) Write<uint64_t>(vec_len, byte_width);
    // Then the actual data.
    auto vloc = buf_.size();
    for (size_t i = start; i < stack_.size(); i += step) {
      WriteAny(stack_[i], byte_width);
    }
    // Then the types.
    if (!typed) {
      for (size_t i = start; i < stack_.size(); i += step) {
        buf_.push_back(stack_[i].StoredPackedType(bit_width));
      }
    }
    return Value(static_cast<uint64_t>(vloc),
                 keys ? FBT_MAP
                      : (typed ? ToTypedVector(vector_type, fixed ? vec_len : 0)
                               : FBT_VECTOR),
                 bit_width);
  }

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

  std::vector<uint8_t> buf_;
  std::vector<Value> stack_;

  bool finished_;
  bool has_duplicate_keys_;

  BuilderFlag flags_;

  BitWidth force_min_bit_width_;

  struct KeyOffsetCompare {
    explicit KeyOffsetCompare(const std::vector<uint8_t> &buf) : buf_(&buf) {}
    bool operator()(size_t a, size_t b) const {
      auto stra = reinterpret_cast<const char *>(buf_->data() + a);
      auto strb = reinterpret_cast<const char *>(buf_->data() + b);
      return strcmp(stra, strb) < 0;
    }
    const std::vector<uint8_t> *buf_;
  };

  typedef std::pair<size_t, size_t> StringOffset;
  struct StringOffsetCompare {
    explicit StringOffsetCompare(const std::vector<uint8_t> &buf)
        : buf_(&buf) {}
    bool operator()(const StringOffset &a, const StringOffset &b) const {
      auto stra = buf_->data() + a.first;
      auto strb = buf_->data() + b.first;
      auto cr = memcmp(stra, strb, (std::min)(a.second, b.second) + 1);
      return cr < 0 || (cr == 0 && a.second < b.second);
    }
    const std::vector<uint8_t> *buf_;
  };

  typedef std::set<size_t, KeyOffsetCompare> KeyOffsetMap;
  typedef std::set<StringOffset, StringOffsetCompare> StringOffsetMap;

  KeyOffsetMap key_pool;
  StringOffsetMap string_pool;

  friend class Verifier;
};

// Helper class to verify the integrity of a FlexBuffer
class Verifier FLATBUFFERS_FINAL_CLASS {
 public:
  Verifier(const uint8_t *buf, size_t buf_len,
           // Supplying this vector likely results in faster verification
           // of larger buffers with many shared keys/strings, but
           // comes at the cost of using additional memory the same size of
           // the buffer being verified, so it is by default off.
           std::vector<uint8_t> *reuse_tracker = nullptr,
           bool _check_alignment = true, size_t max_depth = 64)
      : buf_(buf),
        size_(buf_len),
        depth_(0),
        max_depth_(max_depth),
        num_vectors_(0),
        max_vectors_(buf_len),
        check_alignment_(_check_alignment),
        reuse_tracker_(reuse_tracker) {
    FLATBUFFERS_ASSERT(size_ < FLATBUFFERS_MAX_BUFFER_SIZE);
    if (reuse_tracker_) {
      reuse_tracker_->clear();
      reuse_tracker_->resize(size_, PackedType(BIT_WIDTH_8, FBT_NULL));
    }
  }

 private:
  // Central location where any verification failures register.
  bool Check(bool ok) const {
    // clang-format off
    #ifdef FLATBUFFERS_DEBUG_VERIFICATION_FAILURE
      FLATBUFFERS_ASSERT(ok);
    #endif
    // clang-format on
    return ok;
  }

  // Verify any range within the buffer.
  bool VerifyFrom(size_t elem, size_t elem_len) const {
    return Check(elem_len < size_ && elem <= size_ - elem_len);
  }
  bool VerifyBefore(size_t elem, size_t elem_len) const {
    return Check(elem_len <= elem);
  }

  bool VerifyFromPointer(const uint8_t *p, size_t len) {
    auto o = static_cast<size_t>(p - buf_);
    return VerifyFrom(o, len);
  }
  bool VerifyBeforePointer(const uint8_t *p, size_t len) {
    auto o = static_cast<size_t>(p - buf_);
    return VerifyBefore(o, len);
  }

  bool VerifyByteWidth(size_t width) {
    return Check(width == 1 || width == 2 || width == 4 || width == 8);
  }

  bool VerifyType(int type) { return Check(type >= 0 && type < FBT_MAX_TYPE); }

  bool VerifyOffset(uint64_t off, const uint8_t *p) {
    return Check(off <= static_cast<uint64_t>(size_)) &&
           off <= static_cast<uint64_t>(p - buf_);
  }

  bool VerifyAlignment(const uint8_t *p, size_t size) const {
    auto o = static_cast<size_t>(p - buf_);
    return Check((o & (size - 1)) == 0 || !check_alignment_);
  }

// Macro, since we want to escape from parent function & use lazy args.
#define FLEX_CHECK_VERIFIED(P, PACKED_TYPE)                     \
  if (reuse_tracker_) {                                         \
    auto packed_type = PACKED_TYPE;                             \
    auto existing = (*reuse_tracker_)[P - buf_];                \
    if (existing == packed_type) return true;                   \
    /* Fail verification if already set with different type! */ \
    if (!Check(existing == 0)) return false;                    \
    (*reuse_tracker_)[P - buf_] = packed_type;                  \
  }

  bool VerifyVector(Reference r, const uint8_t *p, Type elem_type) {
    // Any kind of nesting goes thru this function, so guard against that
    // here, both with simple nesting checks, and the reuse tracker if on.
    depth_++;
    num_vectors_++;
    if (!Check(depth_ <= max_depth_ && num_vectors_ <= max_vectors_))
      return false;
    auto size_byte_width = r.byte_width_;
    if (!VerifyBeforePointer(p, size_byte_width)) return false;
    FLEX_CHECK_VERIFIED(p - size_byte_width,
                        PackedType(Builder::WidthB(size_byte_width), r.type_));
    auto sized = Sized(p, size_byte_width);
    auto num_elems = sized.size();
    auto elem_byte_width = r.type_ == FBT_STRING || r.type_ == FBT_BLOB
                               ? uint8_t(1)
                               : r.byte_width_;
    auto max_elems = SIZE_MAX / elem_byte_width;
    if (!Check(num_elems < max_elems))
      return false;  // Protect against byte_size overflowing.
    auto byte_size = num_elems * elem_byte_width;
    if (!VerifyFromPointer(p, byte_size)) return false;
    if (elem_type == FBT_NULL) {
      // Verify type bytes after the vector.
      if (!VerifyFromPointer(p + byte_size, num_elems)) return false;
      auto v = Vector(p, size_byte_width);
      for (size_t i = 0; i < num_elems; i++)
        if (!VerifyRef(v[i])) return false;
    } else if (elem_type == FBT_KEY) {
      auto v = TypedVector(p, elem_byte_width, FBT_KEY);
      for (size_t i = 0; i < num_elems; i++)
        if (!VerifyRef(v[i])) return false;
    } else {
      FLATBUFFERS_ASSERT(IsInline(elem_type));
    }
    depth_--;
    return true;
  }

  bool VerifyKeys(const uint8_t *p, uint8_t byte_width) {
    // The vector part of the map has already been verified.
    const size_t num_prefixed_fields = 3;
    if (!VerifyBeforePointer(p, byte_width * num_prefixed_fields)) return false;
    p -= byte_width * num_prefixed_fields;
    auto off = ReadUInt64(p, byte_width);
    if (!VerifyOffset(off, p)) return false;
    auto key_byte_with =
        static_cast<uint8_t>(ReadUInt64(p + byte_width, byte_width));
    if (!VerifyByteWidth(key_byte_with)) return false;
    return VerifyVector(Reference(p, byte_width, key_byte_with, FBT_VECTOR_KEY),
                        p - off, FBT_KEY);
  }

  bool VerifyKey(const uint8_t *p) {
    FLEX_CHECK_VERIFIED(p, PackedType(BIT_WIDTH_8, FBT_KEY));
    while (p < buf_ + size_)
      if (*p++) return true;
    return false;
  }

#undef FLEX_CHECK_VERIFIED

  bool VerifyTerminator(const String &s) {
    return VerifyFromPointer(reinterpret_cast<const uint8_t *>(s.c_str()),
                             s.size() + 1);
  }

  bool VerifyRef(Reference r) {
    // r.parent_width_ and r.data_ already verified.
    if (!VerifyByteWidth(r.byte_width_) || !VerifyType(r.type_)) {
      return false;
    }
    if (IsInline(r.type_)) {
      // Inline scalars, don't require further verification.
      return true;
    }
    // All remaining types are an offset.
    auto off = ReadUInt64(r.data_, r.parent_width_);
    if (!VerifyOffset(off, r.data_)) return false;
    auto p = r.Indirect();
    if (!VerifyAlignment(p, r.byte_width_)) return false;
    switch (r.type_) {
      case FBT_INDIRECT_INT:
      case FBT_INDIRECT_UINT:
      case FBT_INDIRECT_FLOAT: return VerifyFromPointer(p, r.byte_width_);
      case FBT_KEY: return VerifyKey(p);
      case FBT_MAP:
        return VerifyVector(r, p, FBT_NULL) && VerifyKeys(p, r.byte_width_);
      case FBT_VECTOR: return VerifyVector(r, p, FBT_NULL);
      case FBT_VECTOR_INT: return VerifyVector(r, p, FBT_INT);
      case FBT_VECTOR_BOOL:
      case FBT_VECTOR_UINT: return VerifyVector(r, p, FBT_UINT);
      case FBT_VECTOR_FLOAT: return VerifyVector(r, p, FBT_FLOAT);
      case FBT_VECTOR_KEY: return VerifyVector(r, p, FBT_KEY);
      case FBT_VECTOR_STRING_DEPRECATED:
        // Use of FBT_KEY here intentional, see elsewhere.
        return VerifyVector(r, p, FBT_KEY);
      case FBT_BLOB: return VerifyVector(r, p, FBT_UINT);
      case FBT_STRING:
        return VerifyVector(r, p, FBT_UINT) &&
               VerifyTerminator(String(p, r.byte_width_));
      case FBT_VECTOR_INT2:
      case FBT_VECTOR_UINT2:
      case FBT_VECTOR_FLOAT2:
      case FBT_VECTOR_INT3:
      case FBT_VECTOR_UINT3:
      case FBT_VECTOR_FLOAT3:
      case FBT_VECTOR_INT4:
      case FBT_VECTOR_UINT4:
      case FBT_VECTOR_FLOAT4: {
        uint8_t len = 0;
        auto vtype = ToFixedTypedVectorElementType(r.type_, &len);
        if (!VerifyType(vtype)) return false;
        return VerifyFromPointer(p, r.byte_width_ * len);
      }
      default: return false;
    }
  }

 public:
  bool VerifyBuffer() {
    if (!Check(size_ >= 3)) return false;
    auto end = buf_ + size_;
    auto byte_width = *--end;
    auto packed_type = *--end;
    return VerifyByteWidth(byte_width) && Check(end - buf_ >= byte_width) &&
           VerifyRef(Reference(end - byte_width, byte_width, packed_type));
  }

 private:
  const uint8_t *buf_;
  size_t size_;
  size_t depth_;
  const size_t max_depth_;
  size_t num_vectors_;
  const size_t max_vectors_;
  bool check_alignment_;
  std::vector<uint8_t> *reuse_tracker_;
};

// Utility function that constructs the Verifier for you, see above for
// parameters.
inline bool VerifyBuffer(const uint8_t *buf, size_t buf_len,
                         std::vector<uint8_t> *reuse_tracker = nullptr) {
  Verifier verifier(buf, buf_len, reuse_tracker);
  return verifier.VerifyBuffer();
}

}  // namespace flexbuffers

#if defined(_MSC_VER)
#  pragma warning(pop)
#endif

#endif  // FLATBUFFERS_FLEXBUFFERS_H_
