#ifndef THIRD_PARTY_UPB_WASM_ABI_COMPONENT_H_
#define THIRD_PARTY_UPB_WASM_ABI_COMPONENT_H_

#include <cstdint>
#include <utility>

#include "third_party/absl/base/nullability.h"
#include "upb/base/string_view.h"
#include "upb/mem/arena.h"
#include "wasm_abi/embedded_memory.h"
#include "wasm_abi/handle.h"
#include "wasm_abi/handle_constants.h"
#include "wasm_abi/mini_table/container.hpp"
#include "wasm_abi/status_util.h"

namespace upb::wasm {

// A protobuf API for separating a program using protobuf from its
// implementation, targeted at Wasm.
//
// Schemas are provided by a MiniTableComponent.
class Component {
 public:
  // Component uses a unified table over the core UPB types.
  using Resources = HandleTable<upb_Arena*, EmbeddedArray, EmbeddedMap,
                                EmbeddedMessage, upb_StringView>;

  Component(const MiniTableContainer* mt_container, EmbeddedMemory* memory,
            Resources resources = {})
      : mt_container_(mt_container),
        memory_(memory),
        resources_(std::move(resources)) {}

  // Directly access the Component's resources.
  // Resources can be moved out of the Component for later usage, and used to
  // initialize new Component instances.
  Resources& resources() { return resources_; }
  const Resources& resources() const { return resources_; }

  // Resources are not automatically cleaned up on Component shutdown to avoid
  // deletion of injected values. Use `FreeResources` below to force cleanup of
  // all non-null members. This is static for use with Resources retained beyond
  // a particular Component instance's lifetime.
  static void FreeResources(Resources& resources);

  // Helpers for adding or referencing resources from the host.
  template <typename T>
  uint32_t Insert(const T& handle) {
    return resources_.Insert(handle);
  }
  template <typename T>
  T ResolveHandle(MaybeErrorStatus* absl_nonnull status, uint32_t handle) {
    return resources_.ResolveHandle<T>(status, handle);
  }

  //////////////
  // UPB Methods

  // LINT.IfChange

  // TODO: b/513639245 - Implement sandboxed Arena functions if required.

  uint32_t StringView_Constructor(MaybeErrorStatus* absl_nonnull status,
                                  uint32_t data, uint32_t len,
                                  uint32_t arena_handle);

  uint32_t StringView_FromFloat(MaybeErrorStatus* absl_nonnull status,
                                float value, uint32_t arena_handle);

  uint32_t StringView_FromDouble(MaybeErrorStatus* absl_nonnull status,
                                 double value, uint32_t arena_handle);

  uint32_t StringView_FromInt32(MaybeErrorStatus* absl_nonnull status,
                                int32_t value, uint32_t arena_handle);

  uint32_t StringView_FromUInt32(MaybeErrorStatus* absl_nonnull status,
                                 uint32_t value, uint32_t arena_handle);

  uint32_t StringView_FromInt64(MaybeErrorStatus* absl_nonnull status,
                                int64_t value, uint32_t arena_handle);

  uint32_t StringView_FromUInt64(MaybeErrorStatus* absl_nonnull status,
                                 uint64_t value, uint32_t arena_handle);

  uint32_t StringView_Size(MaybeErrorStatus* absl_nonnull status,
                           uint32_t str_handle);

  uint32_t StringView_Alias(MaybeErrorStatus* absl_nonnull status,
                            uint32_t wasm_addr, uint32_t len);

  uint32_t StringView_IsEqual(MaybeErrorStatus* absl_nonnull status,
                              uint32_t h1, uint32_t h2);

  int32_t StringView_Compare(MaybeErrorStatus* absl_nonnull status, uint32_t h1,
                             uint32_t h2);

  uint32_t StringView_ToExternalBuffer(MaybeErrorStatus* absl_nonnull status,
                                       uint32_t str_handle,
                                       uint32_t arena_handle);

  uint32_t Message_Constructor(MaybeErrorStatus* absl_nonnull status,
                               uint32_t mt_index, uint32_t arena_handle);

  void Message_DeepCopy(MaybeErrorStatus* absl_nonnull status,
                        uint32_t dst_msg_handle, uint32_t src_msg_handle,
                        uint32_t arena_handle);

  void Message_ShallowCopy(MaybeErrorStatus* absl_nonnull status,
                           uint32_t dst_msg_handle, uint32_t src_msg_handle,
                           uint32_t arena_handle);

  int32_t Message_GetInt32(MaybeErrorStatus* absl_nonnull status,
                           uint32_t msg_handle, uint32_t field_index,
                           int32_t default_val);

  void Message_SetInt32(MaybeErrorStatus* absl_nonnull status,
                        uint32_t msg_handle, uint32_t field_index,
                        int32_t value);

  uint32_t Message_GetUInt32(MaybeErrorStatus* absl_nonnull status,
                             uint32_t msg_handle, uint32_t field_index,
                             uint32_t default_val);

  void Message_SetUInt32(MaybeErrorStatus* absl_nonnull status,
                         uint32_t msg_handle, uint32_t field_index,
                         uint32_t value);

  int64_t Message_GetInt64(MaybeErrorStatus* absl_nonnull status,
                           uint32_t msg_handle, uint32_t field_index,
                           int64_t default_val);

  void Message_SetInt64(MaybeErrorStatus* absl_nonnull status,
                        uint32_t msg_handle, uint32_t field_index,
                        int64_t value);

  uint64_t Message_GetUInt64(MaybeErrorStatus* absl_nonnull status,
                             uint32_t msg_handle, uint32_t field_index,
                             uint64_t default_val);

  void Message_SetUInt64(MaybeErrorStatus* absl_nonnull status,
                         uint32_t msg_handle, uint32_t field_index,
                         uint64_t value);

  uint32_t Message_HasBaseField(MaybeErrorStatus* absl_nonnull status,
                                uint32_t msg_handle, uint32_t field_index);

  uint32_t Message_HasExtension(MaybeErrorStatus* absl_nonnull status,
                                uint32_t msg_handle, uint32_t ext_index);

  // Retrieves a mutable UPB Array handle. Returns a handle to a null array if
  // the host message or the array field is not set.
  uint32_t Message_GetArray(MaybeErrorStatus* absl_nonnull status,
                            uint32_t msg_handle, uint32_t field_index);

  // A `Message_SetArray` variant that updates the target array field to an
  // empty array the array to be set is null. Needed for Eko compatibility.
  void Message_SetNullableArray(MaybeErrorStatus* absl_nonnull status,
                                uint32_t msg_handle, uint32_t field_index,
                                uint32_t arr_handle, uint32_t arena_handle);

  uint32_t Message_GetBool(MaybeErrorStatus* absl_nonnull status,
                           uint32_t msg_handle, uint32_t field_index,
                           uint32_t default_val);

  void Message_SetBool(MaybeErrorStatus* absl_nonnull status,
                       uint32_t msg_handle, uint32_t field_index,
                       uint32_t value);

  float Message_GetFloat(MaybeErrorStatus* absl_nonnull status,
                         uint32_t msg_handle, uint32_t field_index,
                         float default_val);

  void Message_SetFloat(MaybeErrorStatus* absl_nonnull status,
                        uint32_t msg_handle, uint32_t field_index, float value);

  double Message_GetDouble(MaybeErrorStatus* absl_nonnull status,
                           uint32_t msg_handle, uint32_t field_index,
                           double default_val);

  void Message_SetDouble(MaybeErrorStatus* absl_nonnull status,
                         uint32_t msg_handle, uint32_t field_index,
                         double value);

  uint32_t Message_GetString(MaybeErrorStatus* absl_nonnull status,
                             uint32_t msg_handle, uint32_t field_index,
                             uint32_t default_val_handle);

  void Message_SetString(MaybeErrorStatus* absl_nonnull status,
                         uint32_t msg_handle, uint32_t field_index,
                         uint32_t value_handle);

  uint32_t Message_GetMessage(MaybeErrorStatus* absl_nonnull status,
                              uint32_t msg_handle, uint32_t field_index);

  uint32_t Message_GetMessageOrEmpty(MaybeErrorStatus* absl_nonnull status,
                                     uint32_t msg_handle, uint32_t field_index,
                                     uint32_t arena_handle);

  // A `Message_SetMessage` variant that creates or updates the message field
  // with an empty message if the message to be set is null. Needed for Eko
  // compatibility.
  void Message_SetNullableMessage(MaybeErrorStatus* absl_nonnull status,
                                  uint32_t msg_handle, uint32_t field_index,
                                  uint32_t value_handle, uint32_t arena_handle);

  uint32_t Message_GetOrCreateMutableMessage(
      MaybeErrorStatus* absl_nonnull status, uint32_t msg_handle,
      uint32_t field_index, uint32_t arena_handle);

  uint32_t Message_ApproximateByteSize(MaybeErrorStatus* absl_nonnull status,
                                       uint32_t msg_handle);

  // Retrieves a mutable UPB Map handle. Returns a handle to a null map if the
  // host message or the map field is not set.
  uint32_t Message_GetMap(MaybeErrorStatus* absl_nonnull status,
                          uint32_t msg_handle, uint32_t entry_mt_index,
                          uint32_t field_index);

  void Message_SetNullableMap(MaybeErrorStatus* absl_nonnull status,
                              uint32_t msg_handle, uint32_t field_index,
                              uint32_t map_handle, uint32_t arena_handle);

  void Message_ClearBaseField(MaybeErrorStatus* absl_nonnull status,
                              uint32_t msg_handle, uint32_t field_index);

  // Extension Getters /////////////////////////////////////////////////////////
  uint32_t Message_GetBoolExtension(MaybeErrorStatus* absl_nonnull status,
                                    uint32_t msg_handle, uint32_t ext_index,
                                    uint32_t default_val);

  double Message_GetDoubleExtension(MaybeErrorStatus* absl_nonnull status,
                                    uint32_t msg_handle, uint32_t ext_index,
                                    double default_val);

  float Message_GetFloatExtension(MaybeErrorStatus* absl_nonnull status,
                                  uint32_t msg_handle, uint32_t ext_index,
                                  float default_val);

  int32_t Message_GetInt32Extension(MaybeErrorStatus* absl_nonnull status,
                                    uint32_t msg_handle, uint32_t ext_index,
                                    int32_t default_val);

  int64_t Message_GetInt64Extension(MaybeErrorStatus* absl_nonnull status,
                                    uint32_t msg_handle, uint32_t ext_index,
                                    int64_t default_val);

  uint32_t Message_GetUInt32Extension(MaybeErrorStatus* absl_nonnull status,
                                      uint32_t msg_handle, uint32_t ext_index,
                                      uint32_t default_val);

  uint64_t Message_GetUInt64Extension(MaybeErrorStatus* absl_nonnull status,
                                      uint32_t msg_handle, uint32_t ext_index,
                                      uint64_t default_val);

  uint32_t Message_GetStringExtension(MaybeErrorStatus* absl_nonnull status,
                                      uint32_t msg_handle, uint32_t ext_index,
                                      uint32_t default_val_handle);

  uint32_t Message_GetMessageExtension(MaybeErrorStatus* absl_nonnull status,
                                       uint32_t msg_handle, uint32_t ext_index);

  uint32_t Message_GetMessageExtensionOrEmpty(
      MaybeErrorStatus* absl_nonnull status, uint32_t msg_handle,
      uint32_t ext_index, uint32_t arena_handle);

  uint32_t Message_GetArrayExtension(MaybeErrorStatus* absl_nonnull status,
                                     uint32_t msg_handle, uint32_t ext_index);

  uint32_t Message_GetMutableArrayExtension(
      MaybeErrorStatus* absl_nonnull status, uint32_t msg_handle,
      uint32_t ext_index);

  // Extension Setters /////////////////////////////////////////////////////////

  void Message_SetBoolExtension(MaybeErrorStatus* absl_nonnull status,
                                uint32_t msg_handle, uint32_t ext_index,
                                uint32_t value, uint32_t arena_handle);

  void Message_SetDoubleExtension(MaybeErrorStatus* absl_nonnull status,
                                  uint32_t msg_handle, uint32_t ext_index,
                                  double value, uint32_t arena_handle);

  void Message_SetFloatExtension(MaybeErrorStatus* absl_nonnull status,
                                 uint32_t msg_handle, uint32_t ext_index,
                                 float value, uint32_t arena_handle);

  void Message_SetInt32Extension(MaybeErrorStatus* absl_nonnull status,
                                 uint32_t msg_handle, uint32_t ext_index,
                                 int32_t value, uint32_t arena_handle);

  void Message_SetUInt32Extension(MaybeErrorStatus* absl_nonnull status,
                                  uint32_t msg_handle, uint32_t ext_index,
                                  uint32_t value, uint32_t arena_handle);

  void Message_SetInt64Extension(MaybeErrorStatus* absl_nonnull status,
                                 uint32_t msg_handle, uint32_t ext_index,
                                 int64_t value, uint32_t arena_handle);

  void Message_SetUInt64Extension(MaybeErrorStatus* absl_nonnull status,
                                  uint32_t msg_handle, uint32_t ext_index,
                                  uint64_t value, uint32_t arena_handle);

  void Message_SetStringExtension(MaybeErrorStatus* absl_nonnull status,
                                  uint32_t msg_handle, uint32_t ext_index,
                                  uint32_t value_handle, uint32_t arena_handle);

  // A `Message_SetMessageExtension` variant that clears the message extension
  // if the message to be set is null. Needed for Eko compatibility.
  void Message_SetNullableMessageExtension(
      MaybeErrorStatus* absl_nonnull status, uint32_t msg_handle,
      uint32_t ext_index, uint32_t value_handle, uint32_t arena_handle);

  // A `Message_SetArrayExtension` variant that clears the target array
  // extension if the array to be set is null. Needed for Eko compatibility.
  void Message_SetNullableArrayExtension(MaybeErrorStatus* absl_nonnull status,
                                         uint32_t msg_handle,
                                         uint32_t ext_index,
                                         uint32_t value_handle,
                                         uint32_t arena_handle);

  void Message_ClearExtension(MaybeErrorStatus* absl_nonnull status,
                              uint32_t msg_handle, uint32_t ext_index);

  uint32_t Array_Constructor(MaybeErrorStatus* absl_nonnull status,
                             int32_t ctype, uint32_t arena_handle);

  uint32_t Array_ConstructorForMessages(MaybeErrorStatus* absl_nonnull status,
                                        uint32_t entry_mt_index,
                                        uint32_t arena_handle);

  uint32_t Array_Size(MaybeErrorStatus* absl_nonnull status,
                      uint32_t arr_handle);

  uint32_t Array_GetBool(MaybeErrorStatus* absl_nonnull status,
                         uint32_t arr_handle, uint32_t index);

  int32_t Array_GetInt32(MaybeErrorStatus* absl_nonnull status,
                         uint32_t arr_handle, uint32_t index);

  uint32_t Array_GetUInt32(MaybeErrorStatus* absl_nonnull status,
                           uint32_t arr_handle, uint32_t index);

  int64_t Array_GetInt64(MaybeErrorStatus* absl_nonnull status,
                         uint32_t arr_handle, uint32_t index);

  uint64_t Array_GetUInt64(MaybeErrorStatus* absl_nonnull status,
                           uint32_t arr_handle, uint32_t index);

  float Array_GetFloat(MaybeErrorStatus* absl_nonnull status,
                       uint32_t arr_handle, uint32_t index);

  double Array_GetDouble(MaybeErrorStatus* absl_nonnull status,
                         uint32_t arr_handle, uint32_t index);

  uint32_t Array_GetMessage(MaybeErrorStatus* absl_nonnull status,
                            uint32_t arr_handle, uint32_t index);

  uint32_t Array_GetString(MaybeErrorStatus* absl_nonnull status,
                           uint32_t arr_handle, uint32_t index);

  void Array_AppendBool(MaybeErrorStatus* absl_nonnull status,
                        uint32_t arr_handle, uint32_t value,
                        uint32_t arena_handle);

  void Array_AppendInt32(MaybeErrorStatus* absl_nonnull status,
                         uint32_t arr_handle, int32_t value,
                         uint32_t arena_handle);

  void Array_AppendUInt32(MaybeErrorStatus* absl_nonnull status,
                          uint32_t arr_handle, uint32_t value,
                          uint32_t arena_handle);

  void Array_AppendFloat(MaybeErrorStatus* absl_nonnull status,
                         uint32_t arr_handle, float value,
                         uint32_t arena_handle);

  void Array_AppendMessage(MaybeErrorStatus* absl_nonnull status,
                           uint32_t arr_handle, uint32_t value_handle,
                           uint32_t arena_handle);

  void Array_AppendString(MaybeErrorStatus* absl_nonnull status,
                          uint32_t arr_handle, uint32_t value_handle,
                          uint32_t arena_handle);

  void Array_AppendInt64(MaybeErrorStatus* absl_nonnull status,
                         uint32_t arr_handle, int64_t value,
                         uint32_t arena_handle);

  void Array_AppendUInt64(MaybeErrorStatus* absl_nonnull status,
                          uint32_t arr_handle, uint64_t value,
                          uint32_t arena_handle);

  void Array_AppendDouble(MaybeErrorStatus* absl_nonnull status,
                          uint32_t arr_handle, double value,
                          uint32_t arena_handle);

  void Array_Append(MaybeErrorStatus* absl_nonnull status, uint32_t arr_handle,
                    uint32_t other_arr_handle, uint32_t arena_handle);

  uint32_t MapInt32_Contains(MaybeErrorStatus* absl_nonnull status,
                             uint32_t map_handle, int32_t key);

  int32_t MapInt32_GetInt32(MaybeErrorStatus* absl_nonnull status,
                            uint32_t map_handle, int32_t key,
                            int32_t default_val);

  uint32_t MapInt32_GetUInt32(MaybeErrorStatus* absl_nonnull status,
                              uint32_t map_handle, int32_t key,
                              uint32_t default_val);

  int64_t MapInt32_GetInt64(MaybeErrorStatus* absl_nonnull status,
                            uint32_t map_handle, int32_t key,
                            int64_t default_val);

  uint64_t MapInt32_GetUInt64(MaybeErrorStatus* absl_nonnull status,
                              uint32_t map_handle, int32_t key,
                              uint64_t default_val);

  float MapInt32_GetFloat(MaybeErrorStatus* absl_nonnull status,
                          uint32_t map_handle, int32_t key, float default_val);

  double MapInt32_GetDouble(MaybeErrorStatus* absl_nonnull status,
                            uint32_t map_handle, int32_t key,
                            double default_val);

  uint32_t MapInt32_GetMessage(MaybeErrorStatus* absl_nonnull status,
                               uint32_t map_handle, int32_t key,
                               uint32_t default_val_handle);

  uint32_t MapInt32_GetString(MaybeErrorStatus* absl_nonnull status,
                              uint32_t map_handle, int32_t key,
                              uint32_t default_val_handle);

  uint32_t MapInt32_GetBool(MaybeErrorStatus* absl_nonnull status,
                            uint32_t map_handle, int32_t key,
                            uint32_t default_val);

  uint32_t MapUInt32_Contains(MaybeErrorStatus* absl_nonnull status,
                              uint32_t map_handle, uint32_t key);

  uint32_t MapUInt32_GetUInt32(MaybeErrorStatus* absl_nonnull status,
                               uint32_t map_handle, uint32_t key,
                               uint32_t default_val);

  int32_t MapUInt32_GetInt32(MaybeErrorStatus* absl_nonnull status,
                             uint32_t map_handle, uint32_t key,
                             int32_t default_val);

  int64_t MapUInt32_GetInt64(MaybeErrorStatus* absl_nonnull status,
                             uint32_t map_handle, uint32_t key,
                             int64_t default_val);

  uint64_t MapUInt32_GetUInt64(MaybeErrorStatus* absl_nonnull status,
                               uint32_t map_handle, uint32_t key,
                               uint64_t default_val);

  float MapUInt32_GetFloat(MaybeErrorStatus* absl_nonnull status,
                           uint32_t map_handle, uint32_t key,
                           float default_val);

  double MapUInt32_GetDouble(MaybeErrorStatus* absl_nonnull status,
                             uint32_t map_handle, uint32_t key,
                             double default_val);

  int32_t MapUInt32_GetBool(MaybeErrorStatus* absl_nonnull status,
                            uint32_t map_handle, uint32_t key,
                            uint32_t default_val);

  uint32_t MapUInt32_GetMessage(MaybeErrorStatus* absl_nonnull status,
                                uint32_t map_handle, uint32_t key,
                                uint32_t default_val_handle);

  uint32_t MapUInt32_GetString(MaybeErrorStatus* absl_nonnull status,
                               uint32_t map_handle, uint32_t key,
                               uint32_t default_val_handle);

  uint32_t MapInt64_Contains(MaybeErrorStatus* absl_nonnull status,
                             uint32_t map_handle, int64_t key);

  int64_t MapInt64_GetInt64(MaybeErrorStatus* absl_nonnull status,
                            uint32_t map_handle, int64_t key,
                            int64_t default_val);

  int32_t MapInt64_GetInt32(MaybeErrorStatus* absl_nonnull status,
                            uint32_t map_handle, int64_t key,
                            int32_t default_val);

  uint32_t MapInt64_GetUInt32(MaybeErrorStatus* absl_nonnull status,
                              uint32_t map_handle, int64_t key,
                              uint32_t default_val);

  uint64_t MapInt64_GetUInt64(MaybeErrorStatus* absl_nonnull status,
                              uint32_t map_handle, int64_t key,
                              uint64_t default_val);

  float MapInt64_GetFloat(MaybeErrorStatus* absl_nonnull status,
                          uint32_t map_handle, int64_t key, float default_val);

  double MapInt64_GetDouble(MaybeErrorStatus* absl_nonnull status,
                            uint32_t map_handle, int64_t key,
                            double default_val);

  int32_t MapInt64_GetBool(MaybeErrorStatus* absl_nonnull status,
                           uint32_t map_handle, int64_t key,
                           int32_t default_val);

  uint32_t MapInt64_GetMessage(MaybeErrorStatus* absl_nonnull status,
                               uint32_t map_handle, int64_t key,
                               uint32_t default_val_handle);

  uint32_t MapInt64_GetString(MaybeErrorStatus* absl_nonnull status,
                              uint32_t map_handle, int64_t key,
                              uint32_t default_val_handle);

  uint32_t MapUInt64_Contains(MaybeErrorStatus* absl_nonnull status,
                              uint32_t map_handle, uint64_t key);

  uint64_t MapUInt64_GetUInt64(MaybeErrorStatus* absl_nonnull status,
                               uint32_t map_handle, uint64_t key,
                               uint64_t default_val);

  int32_t MapUInt64_GetInt32(MaybeErrorStatus* absl_nonnull status,
                             uint32_t map_handle, uint64_t key,
                             int32_t default_val);

  uint32_t MapUInt64_GetUInt32(MaybeErrorStatus* absl_nonnull status,
                               uint32_t map_handle, uint64_t key,
                               uint32_t default_val);

  int64_t MapUInt64_GetInt64(MaybeErrorStatus* absl_nonnull status,
                             uint32_t map_handle, uint64_t key,
                             int64_t default_val);

  float MapUInt64_GetFloat(MaybeErrorStatus* absl_nonnull status,
                           uint32_t map_handle, uint64_t key,
                           float default_val);

  double MapUInt64_GetDouble(MaybeErrorStatus* absl_nonnull status,
                             uint32_t map_handle, uint64_t key,
                             double default_val);

  int32_t MapUInt64_GetBool(MaybeErrorStatus* absl_nonnull status,
                            uint32_t map_handle, uint64_t key,
                            int32_t default_val);

  uint32_t MapUInt64_GetMessage(MaybeErrorStatus* absl_nonnull status,
                                uint32_t map_handle, uint64_t key,
                                uint32_t default_val_handle);

  uint32_t MapUInt64_GetString(MaybeErrorStatus* absl_nonnull status,
                               uint32_t map_handle, uint64_t key,
                               uint32_t default_val_handle);

  uint32_t MapBool_Contains(MaybeErrorStatus* absl_nonnull status,
                            uint32_t map_handle, int32_t key);

  int32_t MapBool_GetInt32(MaybeErrorStatus* absl_nonnull status,
                           uint32_t map_handle, int32_t key,
                           int32_t default_val);

  uint32_t MapBool_GetUInt32(MaybeErrorStatus* absl_nonnull status,
                             uint32_t map_handle, int32_t key,
                             uint32_t default_val);

  int64_t MapBool_GetInt64(MaybeErrorStatus* absl_nonnull status,
                           uint32_t map_handle, int32_t key,
                           int64_t default_val);

  uint64_t MapBool_GetUInt64(MaybeErrorStatus* absl_nonnull status,
                             uint32_t map_handle, int32_t key,
                             uint64_t default_val);
  float MapBool_GetFloat(MaybeErrorStatus* absl_nonnull status,
                         uint32_t map_handle, int32_t key, float default_val);

  double MapBool_GetDouble(MaybeErrorStatus* absl_nonnull status,
                           uint32_t map_handle, int32_t key,
                           double default_val);

  int32_t MapBool_GetBool(MaybeErrorStatus* absl_nonnull status,
                          uint32_t map_handle, int32_t key,
                          int32_t default_val);

  uint32_t MapBool_GetMessage(MaybeErrorStatus* absl_nonnull status,
                              uint32_t map_handle, int32_t key,
                              uint32_t default_val_handle);

  uint32_t MapBool_GetString(MaybeErrorStatus* absl_nonnull status,
                             uint32_t map_handle, int32_t key,
                             uint32_t default_val_handle);

  uint32_t MapString_Contains(MaybeErrorStatus* absl_nonnull status,
                              uint32_t map_handle, uint32_t key_handle);

  int32_t MapString_GetInt32(MaybeErrorStatus* absl_nonnull status,
                             uint32_t map_handle, uint32_t key_handle,
                             int32_t default_val);

  uint32_t MapString_GetUInt32(MaybeErrorStatus* absl_nonnull status,
                               uint32_t map_handle, uint32_t key_handle,
                               uint32_t default_val);

  int64_t MapString_GetInt64(MaybeErrorStatus* absl_nonnull status,
                             uint32_t map_handle, uint32_t key_handle,
                             int64_t default_val);

  uint64_t MapString_GetUInt64(MaybeErrorStatus* absl_nonnull status,
                               uint32_t map_handle, uint32_t key_handle,
                               uint64_t default_val);

  float MapString_GetFloat(MaybeErrorStatus* absl_nonnull status,
                           uint32_t map_handle, uint32_t key_handle,
                           float default_val);

  double MapString_GetDouble(MaybeErrorStatus* absl_nonnull status,
                             uint32_t map_handle, uint32_t key_handle,
                             double default_val);

  int32_t MapString_GetBool(MaybeErrorStatus* absl_nonnull status,
                            uint32_t map_handle, uint32_t key_handle,
                            int32_t default_val);

  uint32_t MapString_GetMessage(MaybeErrorStatus* absl_nonnull status,
                                uint32_t map_handle, uint32_t key_handle,
                                uint32_t default_val_handle);

  uint32_t MapString_GetString(MaybeErrorStatus* absl_nonnull status,
                               uint32_t map_handle, uint32_t key_handle,
                               uint32_t default_val_handle);

  // DEPRECATED: Always use Map_NewForMessages for creating maps, even
  // if the value type is a primitive type. Otherwise, the map will not have the
  // proper minitable for the entries.
  uint32_t Map_New(MaybeErrorStatus* absl_nonnull status, int32_t key_ctype,
                   int32_t value_ctype, uint32_t arena_handle);

  uint32_t Map_NewForMessages(MaybeErrorStatus* absl_nonnull status,
                              int32_t key_ctype, uint32_t entry_mt_index,
                              uint32_t arena_handle);

  void MapInt32_InsertBool(MaybeErrorStatus* absl_nonnull status,
                           uint32_t map_handle, int32_t key, uint32_t value,
                           uint32_t arena_handle);

  void MapInt32_InsertInt32(MaybeErrorStatus* absl_nonnull status,
                            uint32_t map_handle, int32_t key, int32_t value,
                            uint32_t arena_handle);

  void MapInt32_InsertUInt32(MaybeErrorStatus* absl_nonnull status,
                             uint32_t map_handle, int32_t key, uint32_t value,
                             uint32_t arena_handle);

  void MapInt32_InsertFloat(MaybeErrorStatus* absl_nonnull status,
                            uint32_t map_handle, int32_t key, float value,
                            uint32_t arena_handle);

  void MapInt32_InsertMessage(MaybeErrorStatus* absl_nonnull status,
                              uint32_t map_handle, int32_t key,
                              uint32_t value_handle, uint32_t arena_handle);

  void MapInt32_InsertString(MaybeErrorStatus* absl_nonnull status,
                             uint32_t map_handle, int32_t key,
                             uint32_t value_handle, uint32_t arena_handle);

  void MapInt32_InsertInt64(MaybeErrorStatus* absl_nonnull status,
                            uint32_t map_handle, int32_t key, int64_t value,
                            uint32_t arena_handle);

  void MapInt32_InsertUInt64(MaybeErrorStatus* absl_nonnull status,
                             uint32_t map_handle, int32_t key, uint64_t value,
                             uint32_t arena_handle);

  void MapInt32_InsertDouble(MaybeErrorStatus* absl_nonnull status,
                             uint32_t map_handle, int32_t key, double value,
                             uint32_t arena_handle);

  void MapUInt32_InsertBool(MaybeErrorStatus* absl_nonnull status,
                            uint32_t map_handle, uint32_t key, uint32_t value,
                            uint32_t arena_handle);

  void MapUInt32_InsertInt32(MaybeErrorStatus* absl_nonnull status,
                             uint32_t map_handle, uint32_t key, int32_t value,
                             uint32_t arena_handle);

  void MapUInt32_InsertUInt32(MaybeErrorStatus* absl_nonnull status,
                              uint32_t map_handle, uint32_t key, uint32_t value,
                              uint32_t arena_handle);

  void MapUInt32_InsertFloat(MaybeErrorStatus* absl_nonnull status,
                             uint32_t map_handle, uint32_t key, float value,
                             uint32_t arena_handle);

  void MapUInt32_InsertMessage(MaybeErrorStatus* absl_nonnull status,
                               uint32_t map_handle, uint32_t key,
                               uint32_t value_handle, uint32_t arena_handle);

  void MapUInt32_InsertString(MaybeErrorStatus* absl_nonnull status,
                              uint32_t map_handle, uint32_t key,
                              uint32_t value_handle, uint32_t arena_handle);

  void MapUInt32_InsertInt64(MaybeErrorStatus* absl_nonnull status,
                             uint32_t map_handle, uint32_t key, int64_t value,
                             uint32_t arena_handle);

  void MapUInt32_InsertUInt64(MaybeErrorStatus* absl_nonnull status,
                              uint32_t map_handle, uint32_t key, uint64_t value,
                              uint32_t arena_handle);

  void MapUInt32_InsertDouble(MaybeErrorStatus* absl_nonnull status,
                              uint32_t map_handle, uint32_t key, double value,
                              uint32_t arena_handle);

  void MapInt64_InsertBool(MaybeErrorStatus* absl_nonnull status,
                           uint32_t map_handle, int64_t key, uint32_t value,
                           uint32_t arena_handle);

  void MapInt64_InsertInt32(MaybeErrorStatus* absl_nonnull status,
                            uint32_t map_handle, int64_t key, int32_t value,
                            uint32_t arena_handle);

  void MapInt64_InsertUInt32(MaybeErrorStatus* absl_nonnull status,
                             uint32_t map_handle, int64_t key, uint32_t value,
                             uint32_t arena_handle);

  void MapInt64_InsertFloat(MaybeErrorStatus* absl_nonnull status,
                            uint32_t map_handle, int64_t key, float value,
                            uint32_t arena_handle);

  void MapInt64_InsertMessage(MaybeErrorStatus* absl_nonnull status,
                              uint32_t map_handle, int64_t key,
                              uint32_t value_handle, uint32_t arena_handle);

  void MapInt64_InsertString(MaybeErrorStatus* absl_nonnull status,
                             uint32_t map_handle, int64_t key,
                             uint32_t value_handle, uint32_t arena_handle);

  void MapInt64_InsertInt64(MaybeErrorStatus* absl_nonnull status,
                            uint32_t map_handle, int64_t key, int64_t value,
                            uint32_t arena_handle);

  void MapInt64_InsertUInt64(MaybeErrorStatus* absl_nonnull status,
                             uint32_t map_handle, int64_t key, uint64_t value,
                             uint32_t arena_handle);

  void MapInt64_InsertDouble(MaybeErrorStatus* absl_nonnull status,
                             uint32_t map_handle, int64_t key, double value,
                             uint32_t arena_handle);

  void MapUInt64_InsertBool(MaybeErrorStatus* absl_nonnull status,
                            uint32_t map_handle, uint64_t key, uint32_t value,
                            uint32_t arena_handle);

  void MapUInt64_InsertInt32(MaybeErrorStatus* absl_nonnull status,
                             uint32_t map_handle, uint64_t key, int32_t value,
                             uint32_t arena_handle);

  void MapUInt64_InsertUInt32(MaybeErrorStatus* absl_nonnull status,
                              uint32_t map_handle, uint64_t key, uint32_t value,
                              uint32_t arena_handle);

  void MapUInt64_InsertFloat(MaybeErrorStatus* absl_nonnull status,
                             uint32_t map_handle, uint64_t key, float value,
                             uint32_t arena_handle);

  void MapUInt64_InsertMessage(MaybeErrorStatus* absl_nonnull status,
                               uint32_t map_handle, uint64_t key,
                               uint32_t value_handle, uint32_t arena_handle);

  void MapUInt64_InsertString(MaybeErrorStatus* absl_nonnull status,
                              uint32_t map_handle, uint64_t key,
                              uint32_t value_handle, uint32_t arena_handle);

  void MapUInt64_InsertInt64(MaybeErrorStatus* absl_nonnull status,
                             uint32_t map_handle, uint64_t key, int64_t value,
                             uint32_t arena_handle);

  void MapUInt64_InsertUInt64(MaybeErrorStatus* absl_nonnull status,
                              uint32_t map_handle, uint64_t key, uint64_t value,
                              uint32_t arena_handle);

  void MapUInt64_InsertDouble(MaybeErrorStatus* absl_nonnull status,
                              uint32_t map_handle, uint64_t key, double value,
                              uint32_t arena_handle);

  void MapString_InsertBool(MaybeErrorStatus* absl_nonnull status,
                            uint32_t map_handle, uint32_t key_handle,
                            uint32_t value, uint32_t arena_handle);

  void MapString_InsertInt32(MaybeErrorStatus* absl_nonnull status,
                             uint32_t map_handle, uint32_t key_handle,
                             int32_t value, uint32_t arena_handle);

  void MapString_InsertUInt32(MaybeErrorStatus* absl_nonnull status,
                              uint32_t map_handle, uint32_t key_handle,
                              uint32_t value, uint32_t arena_handle);

  void MapString_InsertFloat(MaybeErrorStatus* absl_nonnull status,
                             uint32_t map_handle, uint32_t key_handle,
                             float value, uint32_t arena_handle);

  void MapString_InsertMessage(MaybeErrorStatus* absl_nonnull status,
                               uint32_t map_handle, uint32_t key_handle,
                               uint32_t value_handle, uint32_t arena_handle);

  void MapString_InsertString(MaybeErrorStatus* absl_nonnull status,
                              uint32_t map_handle, uint32_t key_handle,
                              uint32_t value_handle, uint32_t arena_handle);

  void MapString_InsertInt64(MaybeErrorStatus* absl_nonnull status,
                             uint32_t map_handle, uint32_t key_handle,
                             int64_t value, uint32_t arena_handle);

  void MapString_InsertUInt64(MaybeErrorStatus* absl_nonnull status,
                              uint32_t map_handle, uint32_t key_handle,
                              uint64_t value, uint32_t arena_handle);

  void MapString_InsertDouble(MaybeErrorStatus* absl_nonnull status,
                              uint32_t map_handle, uint32_t key_handle,
                              double value, uint32_t arena_handle);

  uint32_t Map_Size(MaybeErrorStatus* absl_nonnull status, uint32_t map_handle);

  void Decode(MaybeErrorStatus* absl_nonnull status, uint32_t data,
              uint32_t msg_handle, uint32_t mt, uint32_t options,
              uint32_t arena_handle);

  uint32_t Encode(MaybeErrorStatus* absl_nonnull status, uint32_t msg_handle,
                  uint32_t mt_handle, uint32_t options, uint32_t arena_handle);

  uint32_t ByteSize(MaybeErrorStatus* absl_nonnull status, uint32_t msg_handle);

  // LINT.ThenChange(//depot/google3/third_party/upb/wasm_abi/test/upb_component_operators.h)

 private:
  // Accessor for the HandleTable field of Resources. Each supported type has
  // a specialization to access the corresponding HandleTable field.
  template <typename T>
  struct HandleTableAccessor {};

  template <typename T>
  uint32_t StringView_FromPrimitiveValue(MaybeErrorStatus* absl_nonnull status,
                                         T value, uint32_t arena_handle);

  inline const void* ResolveMemoryOffset(MaybeErrorStatus* absl_nonnull status,
                                         uint32_t offset, uint32_t size) {
    return memory_->ResolveMemoryOffset(status, offset, size);
  }

  const MiniTableContainer* mt_container_;
  EmbeddedMemory* memory_;
  Resources resources_;
};

}  // namespace upb::wasm

#endif  // THIRD_PARTY_UPB_WASM_ABI_COMPONENT_H_
