// Protocol Buffers - Google's data interchange format
// Copyright 2023 Google LLC.  All rights reserved.
//
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file or at
// https://developers.google.com/open-source/licenses/bsd

#ifndef UPB_REFLECTION_DEF_HPP_
#define UPB_REFLECTION_DEF_HPP_

#include <stdint.h>

#include <cstring>
#include <memory>
#include <string>

#include "absl/log/absl_check.h"
#include "absl/strings/string_view.h"
#include "upb/base/descriptor_constants.h"
#include "upb/base/status.hpp"
#include "upb/base/string_view.h"
#include "upb/mem/arena.hpp"
#include "upb/message/value.h"
#include "upb/mini_descriptor/decode.h"
#include "upb/mini_table/enum.h"
#include "upb/mini_table/field.h"
#include "upb/mini_table/message.h"
#include "upb/reflection/def.h"
#include "upb/reflection/descriptor_bootstrap.h"
#include "upb/reflection/internal/def_pool.h"
#include "upb/reflection/internal/enum_def.h"

// Must be last
#include "upb/port/def.inc"

namespace upb {

typedef upb_MessageValue MessageValue;

class EnumDefPtr;
class FileDefPtr;
class MessageDefPtr;
class OneofDefPtr;

// A upb::FieldDefPtr describes a single field in a message.  It is most often
// found as a part of a upb_MessageDef, but can also stand alone to represent
// an extension.
class FieldDefPtr {
 public:
  FieldDefPtr() : ptr_(nullptr) {}
  explicit FieldDefPtr(const upb_FieldDef* ptr) : ptr_(ptr) {}

  const upb_FieldDef* ptr() const { return ptr_; }

  typedef upb_FieldType Type;
  typedef upb_CType CType;
  typedef upb_Label Label;

  FileDefPtr file() const;
  const char* full_name() const { return upb_FieldDef_FullName(ptr_); }

  const upb_MiniTableField* mini_table() const {
    return upb_FieldDef_MiniTable(ptr_);
  }

  std::string MiniDescriptorEncode() const {
    upb::Arena arena;
    upb_StringView md;
    // TODO: Change to absl::ThrowStdBadAlloc once our min absl version is above
    // 202603
    ABSL_CHECK(upb_FieldDef_MiniDescriptorEncode(ptr_, arena.ptr(), &md));
    return std::string(md.data, md.size);
  }

  const google_protobuf_FieldOptions* options() const {
    return upb_FieldDef_Options(ptr_);
  }

  Type type() const { return upb_FieldDef_Type(ptr_); }
  CType ctype() const { return upb_FieldDef_CType(ptr_); }
  Label label() const { return upb_FieldDef_Label(ptr_); }
  const char* name() const { return upb_FieldDef_Name(ptr_); }
  const char* json_name() const { return upb_FieldDef_JsonName(ptr_); }
  uint32_t number() const { return upb_FieldDef_Number(ptr_); }
  bool is_extension() const { return upb_FieldDef_IsExtension(ptr_); }
  bool is_required() const { return upb_FieldDef_IsRequired(ptr_); }
  bool has_presence() const { return upb_FieldDef_HasPresence(ptr_); }

  // For non-string, non-submessage fields, this indicates whether binary
  // protobufs are encoded in packed or non-packed format.
  //
  // Note: this accessor reflects the fact that "packed" has different defaults
  // depending on whether the proto is proto2 or proto3.
  bool packed() const { return upb_FieldDef_IsPacked(ptr_); }

  // An integer that can be used as an index into an array of fields for
  // whatever message this field belongs to.  Guaranteed to be less than
  // f->containing_type()->field_count().  May only be accessed once the def has
  // been finalized.
  // The index ordering here is *dependent* on the order of the fields in the
  // .proto file.
  uint32_t index() const { return upb_FieldDef_Index(ptr_); }

  // Index into msgdef->layout->fields or file->exts.
  // This is the index that the MiniTable uses, and is independent of the order
  // of the fields in the .proto file.
  uint32_t layout_index() const { return upb_FieldDef_LayoutIndex(ptr_); }

  // The MessageDef to which this field belongs (for extensions, the extended
  // message).
  MessageDefPtr containing_type() const;

  // For extensions, the message the extension is declared inside, or NULL if
  // none.
  MessageDefPtr extension_scope() const;

  // The OneofDef to which this field belongs, or NULL if this field is not part
  // of a oneof.
  OneofDefPtr containing_oneof() const;
  OneofDefPtr real_containing_oneof() const;

  // Convenient field type tests.
  bool IsEnum() const { return upb_FieldDef_IsEnum(ptr_); }
  bool IsSubMessage() const { return upb_FieldDef_IsSubMessage(ptr_); }
  bool IsString() const { return upb_FieldDef_IsString(ptr_); }
  bool IsSequence() const { return upb_FieldDef_IsRepeated(ptr_); }
  bool IsPrimitive() const { return upb_FieldDef_IsPrimitive(ptr_); }
  bool IsMap() const { return upb_FieldDef_IsMap(ptr_); }

  MessageValue default_value() const { return upb_FieldDef_Default(ptr_); }

  // Returns the enum or submessage def for this field, if any.  The field's
  // type must match (ie. you may only call enum_subdef() for fields where
  // type() == kUpb_CType_Enum).
  EnumDefPtr enum_subdef() const;
  MessageDefPtr message_type() const;

  explicit operator bool() const { return ptr_ != nullptr; }

  friend bool operator==(FieldDefPtr lhs, FieldDefPtr rhs) {
    return lhs.ptr_ == rhs.ptr_;
  }

  friend bool operator!=(FieldDefPtr lhs, FieldDefPtr rhs) {
    return !(lhs == rhs);
  }

 private:
  const upb_FieldDef* ptr_;
};

// Class that represents a oneof.
class OneofDefPtr {
 public:
  OneofDefPtr() : ptr_(nullptr) {}
  explicit OneofDefPtr(const upb_OneofDef* ptr) : ptr_(ptr) {}

  const upb_OneofDef* ptr() const { return ptr_; }
  explicit operator bool() const { return ptr_ != nullptr; }

  const google_protobuf_OneofOptions* options() const {
    return upb_OneofDef_Options(ptr_);
  }

  // Returns the MessageDef that contains this OneofDef.
  MessageDefPtr containing_type() const;

  // Returns the name of this oneof.
  const char* name() const { return upb_OneofDef_Name(ptr_); }
  const char* full_name() const { return upb_OneofDef_FullName(ptr_); }

  // Returns the number of fields in the oneof.
  int field_count() const { return upb_OneofDef_FieldCount(ptr_); }
  FieldDefPtr field(int i) const {
    return FieldDefPtr(upb_OneofDef_Field(ptr_, i));
  }

  // Looks up by name.
  FieldDefPtr FindFieldByName(const char* name, size_t len) const {
    return FieldDefPtr(upb_OneofDef_LookupNameWithSize(ptr_, name, len));
  }
  FieldDefPtr FindFieldByName(const char* name) const {
    return FieldDefPtr(upb_OneofDef_LookupName(ptr_, name));
  }

  template <class T>
  FieldDefPtr FindFieldByName(const T& str) const {
    return FindFieldByName(str.c_str(), str.size());
  }

  // Looks up by tag number.
  FieldDefPtr FindFieldByNumber(uint32_t num) const {
    return FieldDefPtr(upb_OneofDef_LookupNumber(ptr_, num));
  }

 private:
  const upb_OneofDef* ptr_;
};

// Structure that describes a single .proto message type.
class MessageDefPtr {
 public:
  MessageDefPtr() : ptr_(nullptr) {}
  explicit MessageDefPtr(const upb_MessageDef* ptr) : ptr_(ptr) {}

  const google_protobuf_MessageOptions* options() const {
    return upb_MessageDef_Options(ptr_);
  }

  std::string MiniDescriptorEncode() const {
    upb::Arena arena;
    upb_StringView md;
    // TODO: Change to absl::ThrowStdBadAlloc once our min absl version is above
    // 202603
    ABSL_CHECK(upb_MessageDef_MiniDescriptorEncode(ptr_, arena.ptr(), &md));
    return std::string(md.data, md.size);
  }

  const upb_MessageDef* ptr() const { return ptr_; }

  FileDefPtr file() const;

  const char* full_name() const { return upb_MessageDef_FullName(ptr_); }
  const char* name() const { return upb_MessageDef_Name(ptr_); }

  // Returns the MessageDef that contains this MessageDef (or null).
  MessageDefPtr containing_type() const;

  const upb_MiniTable* mini_table() const {
    return upb_MessageDef_MiniTable(ptr_);
  }

  // The number of fields that belong to the MessageDef.
  int field_count() const { return upb_MessageDef_FieldCount(ptr_); }
  FieldDefPtr field(int i) const {
    return FieldDefPtr(upb_MessageDef_Field(ptr_, i));
  }

  // The number of oneofs that belong to the MessageDef.
  int oneof_count() const { return upb_MessageDef_OneofCount(ptr_); }
  int real_oneof_count() const { return upb_MessageDef_RealOneofCount(ptr_); }
  OneofDefPtr oneof(int i) const {
    return OneofDefPtr(upb_MessageDef_Oneof(ptr_, i));
  }

  int enum_type_count() const { return upb_MessageDef_NestedEnumCount(ptr_); }
  EnumDefPtr enum_type(int i) const;

  int nested_message_count() const {
    return upb_MessageDef_NestedMessageCount(ptr_);
  }
  MessageDefPtr nested_message(int i) const {
    return MessageDefPtr(upb_MessageDef_NestedMessage(ptr_, i));
  }

  int nested_extension_count() const {
    return upb_MessageDef_NestedExtensionCount(ptr_);
  }
  FieldDefPtr nested_extension(int i) const {
    return FieldDefPtr(upb_MessageDef_NestedExtension(ptr_, i));
  }

  int extension_range_count() const {
    return upb_MessageDef_ExtensionRangeCount(ptr_);
  }

  // These return null pointers if the field is not found.
  FieldDefPtr FindFieldByNumber(uint32_t number) const {
    return FieldDefPtr(upb_MessageDef_FindFieldByNumber(ptr_, number));
  }
  FieldDefPtr FindFieldByName(const char* name, size_t len) const {
    return FieldDefPtr(upb_MessageDef_FindFieldByNameWithSize(ptr_, name, len));
  }
  FieldDefPtr FindFieldByName(const char* name) const {
    return FieldDefPtr(upb_MessageDef_FindFieldByName(ptr_, name));
  }

  template <class T>
  FieldDefPtr FindFieldByName(const T& str) const {
    return FindFieldByName(str.c_str(), str.size());
  }

  OneofDefPtr FindOneofByName(const char* name, size_t len) const {
    return OneofDefPtr(upb_MessageDef_FindOneofByNameWithSize(ptr_, name, len));
  }

  OneofDefPtr FindOneofByName(const char* name) const {
    return OneofDefPtr(upb_MessageDef_FindOneofByName(ptr_, name));
  }

  template <class T>
  OneofDefPtr FindOneofByName(const T& str) const {
    return FindOneofByName(str.c_str(), str.size());
  }

  // Is this message a map entry?
  bool mapentry() const { return upb_MessageDef_IsMapEntry(ptr_); }

  FieldDefPtr map_key() const {
    if (!mapentry()) return FieldDefPtr();
    return FieldDefPtr(upb_MessageDef_Field(ptr_, 0));
  }

  FieldDefPtr map_value() const {
    if (!mapentry()) return FieldDefPtr();
    return FieldDefPtr(upb_MessageDef_Field(ptr_, 1));
  }

  // Return the type of well known type message. kUpb_WellKnown_Unspecified for
  // non-well-known message.
  upb_WellKnown wellknowntype() const {
    return upb_MessageDef_WellKnownType(ptr_);
  }

  explicit operator bool() const { return ptr_ != nullptr; }

  friend bool operator==(MessageDefPtr lhs, MessageDefPtr rhs) {
    return lhs.ptr_ == rhs.ptr_;
  }

  friend bool operator!=(MessageDefPtr lhs, MessageDefPtr rhs) {
    return !(lhs == rhs);
  }

 private:
  class FieldIter {
   public:
    explicit FieldIter(const upb_MessageDef* m, int i) : m_(m), i_(i) {}
    void operator++() { i_++; }

    FieldDefPtr operator*() {
      return FieldDefPtr(upb_MessageDef_Field(m_, i_));
    }

    friend bool operator==(FieldIter lhs, FieldIter rhs) {
      return lhs.i_ == rhs.i_;
    }

    friend bool operator!=(FieldIter lhs, FieldIter rhs) {
      return !(lhs == rhs);
    }

   private:
    const upb_MessageDef* m_;
    int i_;
  };

  class FieldAccessor {
   public:
    explicit FieldAccessor(const upb_MessageDef* md) : md_(md) {}
    FieldIter begin() { return FieldIter(md_, 0); }
    FieldIter end() { return FieldIter(md_, upb_MessageDef_FieldCount(md_)); }

   private:
    const upb_MessageDef* md_;
  };

  class OneofIter {
   public:
    explicit OneofIter(const upb_MessageDef* m, int i) : m_(m), i_(i) {}
    void operator++() { i_++; }

    OneofDefPtr operator*() {
      return OneofDefPtr(upb_MessageDef_Oneof(m_, i_));
    }

    friend bool operator==(OneofIter lhs, OneofIter rhs) {
      return lhs.i_ == rhs.i_;
    }

    friend bool operator!=(OneofIter lhs, OneofIter rhs) {
      return !(lhs == rhs);
    }

   private:
    const upb_MessageDef* m_;
    int i_;
  };

  class OneofAccessor {
   public:
    explicit OneofAccessor(const upb_MessageDef* md) : md_(md) {}
    OneofIter begin() { return OneofIter(md_, 0); }
    OneofIter end() { return OneofIter(md_, upb_MessageDef_OneofCount(md_)); }

   private:
    const upb_MessageDef* md_;
  };

 public:
  FieldAccessor fields() const { return FieldAccessor(ptr()); }
  OneofAccessor oneofs() const { return OneofAccessor(ptr()); }

 private:
  const upb_MessageDef* ptr_;
};

class EnumValDefPtr {
 public:
  EnumValDefPtr() : ptr_(nullptr) {}
  explicit EnumValDefPtr(const upb_EnumValueDef* ptr) : ptr_(ptr) {}

  const google_protobuf_EnumValueOptions* options() const {
    return upb_EnumValueDef_Options(ptr_);
  }

  int32_t number() const { return upb_EnumValueDef_Number(ptr_); }
  const char* full_name() const { return upb_EnumValueDef_FullName(ptr_); }
  const char* json_name() const { return upb_EnumValueDef_JsonName(ptr_); }
  const char* name() const { return upb_EnumValueDef_Name(ptr_); }

 private:
  const upb_EnumValueDef* ptr_;
};

class EnumDefPtr {
 public:
  EnumDefPtr() : ptr_(nullptr) {}
  explicit EnumDefPtr(const upb_EnumDef* ptr) : ptr_(ptr) {}

  const google_protobuf_EnumOptions* options() const {
    return upb_EnumDef_Options(ptr_);
  }

  const upb_MiniTableEnum* mini_table() const {
    return _upb_EnumDef_MiniTable(ptr_);
  }

  std::string MiniDescriptorEncode() const {
    upb::Arena arena;
    upb_StringView md;
    // TODO: Change to absl::ThrowStdBadAlloc once our min absl version is above
    // 202603
    ABSL_CHECK(upb_EnumDef_MiniDescriptorEncode(ptr_, arena.ptr(), &md));
    return std::string(md.data, md.size);
  }

  const upb_EnumDef* ptr() const { return ptr_; }
  explicit operator bool() const { return ptr_ != nullptr; }

  FileDefPtr file() const;
  const char* full_name() const { return upb_EnumDef_FullName(ptr_); }
  const char* name() const { return upb_EnumDef_Name(ptr_); }
  bool is_closed() const { return upb_EnumDef_IsClosed(ptr_); }

  // Returns the MessageDef that contains this EnumDef (or null).
  MessageDefPtr containing_type() const;

  // The value that is used as the default when no field default is specified.
  // If not set explicitly, the first value that was added will be used.
  // The default value must be a member of the enum.
  // Requires that value_count() > 0.
  int32_t default_value() const { return upb_EnumDef_Default(ptr_); }

  // Returns the number of values currently defined in the enum.  Note that
  // multiple names can refer to the same number, so this may be greater than
  // the total number of unique numbers.
  int value_count() const { return upb_EnumDef_ValueCount(ptr_); }
  EnumValDefPtr value(int i) const {
    return EnumValDefPtr(upb_EnumDef_Value(ptr_, i));
  }

  EnumValDefPtr FindValueByJsonName(const char* name) const {
    return EnumValDefPtr(upb_EnumDef_FindByJsonName(ptr_, name));
  }

  // Lookups from name to integer, returning true if found.
  EnumValDefPtr FindValueByName(const char* name) const {
    return EnumValDefPtr(upb_EnumDef_FindValueByName(ptr_, name));
  }

  // Finds the name corresponding to the given number, or NULL if none was
  // found.  If more than one name corresponds to this number, returns the
  // first one that was added.
  EnumValDefPtr FindValueByNumber(int32_t num) const {
    return EnumValDefPtr(upb_EnumDef_FindValueByNumber(ptr_, num));
  }

 private:
  const upb_EnumDef* ptr_;
};

// Class that represents a .proto file with some things defined in it.
//
// Many users won't care about FileDefs, but they are necessary if you want to
// read the values of file-level options.
class FileDefPtr {
 public:
  explicit FileDefPtr(const upb_FileDef* ptr) : ptr_(ptr) {}

  const google_protobuf_FileOptions* options() const {
    return upb_FileDef_Options(ptr_);
  }

  const upb_FileDef* ptr() const { return ptr_; }

  // Get/set name of the file (eg. "foo/bar.proto").
  const char* name() const { return upb_FileDef_Name(ptr_); }

  // Package name for definitions inside the file (eg. "foo.bar").
  const char* package() const { return upb_FileDef_Package(ptr_); }

  // Get the list of dependencies from the file.  These are returned in the
  // order that they were added to the FileDefPtr.
  int dependency_count() const { return upb_FileDef_DependencyCount(ptr_); }
  FileDefPtr dependency(int index) const {
    return FileDefPtr(upb_FileDef_Dependency(ptr_, index));
  }

  int public_dependency_count() const {
    return upb_FileDef_PublicDependencyCount(ptr_);
  }
  FileDefPtr public_dependency(int index) const {
    return FileDefPtr(upb_FileDef_PublicDependency(ptr_, index));
  }

  int option_dependency_count() const {
    return upb_FileDef_OptionDependencyCount(ptr_);
  }
  const char* option_dependency(int index) const {
    return upb_FileDef_OptionDependency(ptr_, index);
  }

  int toplevel_enum_count() const {
    return upb_FileDef_TopLevelEnumCount(ptr_);
  }
  EnumDefPtr toplevel_enum(int index) const {
    return EnumDefPtr(upb_FileDef_TopLevelEnum(ptr_, index));
  }

  int toplevel_message_count() const {
    return upb_FileDef_TopLevelMessageCount(ptr_);
  }
  MessageDefPtr toplevel_message(int index) const {
    return MessageDefPtr(upb_FileDef_TopLevelMessage(ptr_, index));
  }

  int toplevel_extension_count() const {
    return upb_FileDef_TopLevelExtensionCount(ptr_);
  }
  FieldDefPtr toplevel_extension(int index) const {
    return FieldDefPtr(upb_FileDef_TopLevelExtension(ptr_, index));
  }

  bool resolves(const char* path) const {
    return upb_FileDef_Resolves(ptr_, path);
  }

  explicit operator bool() const { return ptr_ != nullptr; }

  friend bool operator==(FileDefPtr lhs, FileDefPtr rhs) {
    return lhs.ptr_ == rhs.ptr_;
  }

  friend bool operator!=(FileDefPtr lhs, FileDefPtr rhs) {
    return !(lhs == rhs);
  }

 private:
  const upb_FileDef* ptr_;
};

// Non-const methods in upb::DefPool are NOT thread-safe.
class DefPool {
 public:
  DefPool() : ptr_(upb_DefPool_New(), upb_DefPool_Free) {}
  explicit DefPool(upb_DefPool* s) : ptr_(s, upb_DefPool_Free) {}

  const upb_DefPool* ptr() const { return ptr_.get(); }
  upb_DefPool* ptr() { return ptr_.get(); }

  // Finds an entry in the symbol table with this exact name.  If not found,
  // returns NULL.
  MessageDefPtr FindMessageByName(absl::string_view sym) const {
    return MessageDefPtr(upb_DefPool_FindMessageByNameWithSize(
        ptr_.get(), sym.data(), sym.size()));
  }

  EnumDefPtr FindEnumByName(absl::string_view sym) const {
    return EnumDefPtr(
        upb_DefPool_FindEnumByNameWithSize(ptr_.get(), sym.data(), sym.size()));
  }

  FileDefPtr FindFileByName(absl::string_view name) const {
    return FileDefPtr(upb_DefPool_FindFileByNameWithSize(
        ptr_.get(), name.data(), name.size()));
  }

  FieldDefPtr FindExtensionByName(absl::string_view name) const {
    return FieldDefPtr(upb_DefPool_FindExtensionByNameWithSize(
        ptr_.get(), name.data(), name.size()));
  }

  void _SetPlatform(upb_MiniTablePlatform platform) {
    _upb_DefPool_SetPlatform(ptr_.get(), platform);
  }

  // TODO: iteration?

  // Adds the given serialized FileDescriptorProto to the pool.
  FileDefPtr AddFile(const google_protobuf_FileDescriptorProto* file_proto,
                     Status* status) {
    return FileDefPtr(
        upb_DefPool_AddFile(ptr_.get(), file_proto, status->ptr()));
  }

 private:
  std::unique_ptr<upb_DefPool, decltype(&upb_DefPool_Free)> ptr_;
};

inline FileDefPtr EnumDefPtr::file() const {
  return FileDefPtr(upb_EnumDef_File(ptr_));
}

inline FileDefPtr FieldDefPtr::file() const {
  return FileDefPtr(upb_FieldDef_File(ptr_));
}

inline FileDefPtr MessageDefPtr::file() const {
  return FileDefPtr(upb_MessageDef_File(ptr_));
}

inline MessageDefPtr MessageDefPtr::containing_type() const {
  return MessageDefPtr(upb_MessageDef_ContainingType(ptr_));
}

inline MessageDefPtr EnumDefPtr::containing_type() const {
  return MessageDefPtr(upb_EnumDef_ContainingType(ptr_));
}

inline EnumDefPtr MessageDefPtr::enum_type(int i) const {
  return EnumDefPtr(upb_MessageDef_NestedEnum(ptr_, i));
}

inline MessageDefPtr FieldDefPtr::message_type() const {
  return MessageDefPtr(upb_FieldDef_MessageSubDef(ptr_));
}

inline MessageDefPtr FieldDefPtr::containing_type() const {
  return MessageDefPtr(upb_FieldDef_ContainingType(ptr_));
}

inline MessageDefPtr FieldDefPtr::extension_scope() const {
  return MessageDefPtr(upb_FieldDef_ExtensionScope(ptr_));
}

inline MessageDefPtr OneofDefPtr::containing_type() const {
  return MessageDefPtr(upb_OneofDef_ContainingType(ptr_));
}

inline OneofDefPtr FieldDefPtr::containing_oneof() const {
  return OneofDefPtr(upb_FieldDef_ContainingOneof(ptr_));
}

inline OneofDefPtr FieldDefPtr::real_containing_oneof() const {
  return OneofDefPtr(upb_FieldDef_RealContainingOneof(ptr_));
}

inline EnumDefPtr FieldDefPtr::enum_subdef() const {
  return EnumDefPtr(upb_FieldDef_EnumSubDef(ptr_));
}

}  // namespace upb

#include "upb/port/undef.inc"

#endif  // UPB_REFLECTION_DEF_HPP_
