// Copyright 2013 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// Autogenerated from Pigeon (v7.0.5), do not edit directly.
// See also: https://pub.dev/packages/pigeon

#undef _HAS_EXCEPTIONS

#include "core_tests.gen.h"

#include <flutter/basic_message_channel.h>
#include <flutter/binary_messenger.h>
#include <flutter/encodable_value.h>
#include <flutter/standard_message_codec.h>

#include <map>
#include <optional>
#include <string>

namespace core_tests_pigeontest {
using flutter::BasicMessageChannel;
using flutter::CustomEncodableValue;
using flutter::EncodableList;
using flutter::EncodableMap;
using flutter::EncodableValue;

// AllTypes

bool AllTypes::a_bool() const { return a_bool_; }
void AllTypes::set_a_bool(bool value_arg) { a_bool_ = value_arg; }

int64_t AllTypes::an_int() const { return an_int_; }
void AllTypes::set_an_int(int64_t value_arg) { an_int_ = value_arg; }

double AllTypes::a_double() const { return a_double_; }
void AllTypes::set_a_double(double value_arg) { a_double_ = value_arg; }

const std::vector<uint8_t>& AllTypes::a_byte_array() const {
  return a_byte_array_;
}
void AllTypes::set_a_byte_array(const std::vector<uint8_t>& value_arg) {
  a_byte_array_ = value_arg;
}

const std::vector<int32_t>& AllTypes::a4_byte_array() const {
  return a4_byte_array_;
}
void AllTypes::set_a4_byte_array(const std::vector<int32_t>& value_arg) {
  a4_byte_array_ = value_arg;
}

const std::vector<int64_t>& AllTypes::a8_byte_array() const {
  return a8_byte_array_;
}
void AllTypes::set_a8_byte_array(const std::vector<int64_t>& value_arg) {
  a8_byte_array_ = value_arg;
}

const std::vector<double>& AllTypes::a_float_array() const {
  return a_float_array_;
}
void AllTypes::set_a_float_array(const std::vector<double>& value_arg) {
  a_float_array_ = value_arg;
}

const EncodableList& AllTypes::a_list() const { return a_list_; }
void AllTypes::set_a_list(const EncodableList& value_arg) {
  a_list_ = value_arg;
}

const EncodableMap& AllTypes::a_map() const { return a_map_; }
void AllTypes::set_a_map(const EncodableMap& value_arg) { a_map_ = value_arg; }

const AnEnum& AllTypes::an_enum() const { return an_enum_; }
void AllTypes::set_an_enum(const AnEnum& value_arg) { an_enum_ = value_arg; }

const std::string& AllTypes::a_string() const { return a_string_; }
void AllTypes::set_a_string(std::string_view value_arg) {
  a_string_ = value_arg;
}

EncodableList AllTypes::ToEncodableList() const {
  EncodableList list;
  list.reserve(11);
  list.push_back(EncodableValue(a_bool_));
  list.push_back(EncodableValue(an_int_));
  list.push_back(EncodableValue(a_double_));
  list.push_back(EncodableValue(a_byte_array_));
  list.push_back(EncodableValue(a4_byte_array_));
  list.push_back(EncodableValue(a8_byte_array_));
  list.push_back(EncodableValue(a_float_array_));
  list.push_back(EncodableValue(a_list_));
  list.push_back(EncodableValue(a_map_));
  list.push_back(EncodableValue((int)an_enum_));
  list.push_back(EncodableValue(a_string_));
  return list;
}

AllTypes::AllTypes() {}

AllTypes::AllTypes(const EncodableList& list) {
  auto& encodable_a_bool = list[0];
  if (const bool* pointer_a_bool = std::get_if<bool>(&encodable_a_bool)) {
    a_bool_ = *pointer_a_bool;
  }
  auto& encodable_an_int = list[1];
  if (const int32_t* pointer_an_int = std::get_if<int32_t>(&encodable_an_int))
    an_int_ = *pointer_an_int;
  else if (const int64_t* pointer_an_int_64 =
               std::get_if<int64_t>(&encodable_an_int))
    an_int_ = *pointer_an_int_64;
  auto& encodable_a_double = list[2];
  if (const double* pointer_a_double =
          std::get_if<double>(&encodable_a_double)) {
    a_double_ = *pointer_a_double;
  }
  auto& encodable_a_byte_array = list[3];
  if (const std::vector<uint8_t>* pointer_a_byte_array =
          std::get_if<std::vector<uint8_t>>(&encodable_a_byte_array)) {
    a_byte_array_ = *pointer_a_byte_array;
  }
  auto& encodable_a4_byte_array = list[4];
  if (const std::vector<int32_t>* pointer_a4_byte_array =
          std::get_if<std::vector<int32_t>>(&encodable_a4_byte_array)) {
    a4_byte_array_ = *pointer_a4_byte_array;
  }
  auto& encodable_a8_byte_array = list[5];
  if (const std::vector<int64_t>* pointer_a8_byte_array =
          std::get_if<std::vector<int64_t>>(&encodable_a8_byte_array)) {
    a8_byte_array_ = *pointer_a8_byte_array;
  }
  auto& encodable_a_float_array = list[6];
  if (const std::vector<double>* pointer_a_float_array =
          std::get_if<std::vector<double>>(&encodable_a_float_array)) {
    a_float_array_ = *pointer_a_float_array;
  }
  auto& encodable_a_list = list[7];
  if (const EncodableList* pointer_a_list =
          std::get_if<EncodableList>(&encodable_a_list)) {
    a_list_ = *pointer_a_list;
  }
  auto& encodable_a_map = list[8];
  if (const EncodableMap* pointer_a_map =
          std::get_if<EncodableMap>(&encodable_a_map)) {
    a_map_ = *pointer_a_map;
  }
  auto& encodable_an_enum = list[9];
  if (const int32_t* pointer_an_enum = std::get_if<int32_t>(&encodable_an_enum))
    an_enum_ = (AnEnum)*pointer_an_enum;
  auto& encodable_a_string = list[10];
  if (const std::string* pointer_a_string =
          std::get_if<std::string>(&encodable_a_string)) {
    a_string_ = *pointer_a_string;
  }
}

// AllNullableTypes

const bool* AllNullableTypes::a_nullable_bool() const {
  return a_nullable_bool_ ? &(*a_nullable_bool_) : nullptr;
}
void AllNullableTypes::set_a_nullable_bool(const bool* value_arg) {
  a_nullable_bool_ = value_arg ? std::optional<bool>(*value_arg) : std::nullopt;
}
void AllNullableTypes::set_a_nullable_bool(bool value_arg) {
  a_nullable_bool_ = value_arg;
}

const int64_t* AllNullableTypes::a_nullable_int() const {
  return a_nullable_int_ ? &(*a_nullable_int_) : nullptr;
}
void AllNullableTypes::set_a_nullable_int(const int64_t* value_arg) {
  a_nullable_int_ =
      value_arg ? std::optional<int64_t>(*value_arg) : std::nullopt;
}
void AllNullableTypes::set_a_nullable_int(int64_t value_arg) {
  a_nullable_int_ = value_arg;
}

const double* AllNullableTypes::a_nullable_double() const {
  return a_nullable_double_ ? &(*a_nullable_double_) : nullptr;
}
void AllNullableTypes::set_a_nullable_double(const double* value_arg) {
  a_nullable_double_ =
      value_arg ? std::optional<double>(*value_arg) : std::nullopt;
}
void AllNullableTypes::set_a_nullable_double(double value_arg) {
  a_nullable_double_ = value_arg;
}

const std::vector<uint8_t>* AllNullableTypes::a_nullable_byte_array() const {
  return a_nullable_byte_array_ ? &(*a_nullable_byte_array_) : nullptr;
}
void AllNullableTypes::set_a_nullable_byte_array(
    const std::vector<uint8_t>* value_arg) {
  a_nullable_byte_array_ = value_arg
                               ? std::optional<std::vector<uint8_t>>(*value_arg)
                               : std::nullopt;
}
void AllNullableTypes::set_a_nullable_byte_array(
    const std::vector<uint8_t>& value_arg) {
  a_nullable_byte_array_ = value_arg;
}

const std::vector<int32_t>* AllNullableTypes::a_nullable4_byte_array() const {
  return a_nullable4_byte_array_ ? &(*a_nullable4_byte_array_) : nullptr;
}
void AllNullableTypes::set_a_nullable4_byte_array(
    const std::vector<int32_t>* value_arg) {
  a_nullable4_byte_array_ =
      value_arg ? std::optional<std::vector<int32_t>>(*value_arg)
                : std::nullopt;
}
void AllNullableTypes::set_a_nullable4_byte_array(
    const std::vector<int32_t>& value_arg) {
  a_nullable4_byte_array_ = value_arg;
}

const std::vector<int64_t>* AllNullableTypes::a_nullable8_byte_array() const {
  return a_nullable8_byte_array_ ? &(*a_nullable8_byte_array_) : nullptr;
}
void AllNullableTypes::set_a_nullable8_byte_array(
    const std::vector<int64_t>* value_arg) {
  a_nullable8_byte_array_ =
      value_arg ? std::optional<std::vector<int64_t>>(*value_arg)
                : std::nullopt;
}
void AllNullableTypes::set_a_nullable8_byte_array(
    const std::vector<int64_t>& value_arg) {
  a_nullable8_byte_array_ = value_arg;
}

const std::vector<double>* AllNullableTypes::a_nullable_float_array() const {
  return a_nullable_float_array_ ? &(*a_nullable_float_array_) : nullptr;
}
void AllNullableTypes::set_a_nullable_float_array(
    const std::vector<double>* value_arg) {
  a_nullable_float_array_ =
      value_arg ? std::optional<std::vector<double>>(*value_arg) : std::nullopt;
}
void AllNullableTypes::set_a_nullable_float_array(
    const std::vector<double>& value_arg) {
  a_nullable_float_array_ = value_arg;
}

const EncodableList* AllNullableTypes::a_nullable_list() const {
  return a_nullable_list_ ? &(*a_nullable_list_) : nullptr;
}
void AllNullableTypes::set_a_nullable_list(const EncodableList* value_arg) {
  a_nullable_list_ =
      value_arg ? std::optional<EncodableList>(*value_arg) : std::nullopt;
}
void AllNullableTypes::set_a_nullable_list(const EncodableList& value_arg) {
  a_nullable_list_ = value_arg;
}

const EncodableMap* AllNullableTypes::a_nullable_map() const {
  return a_nullable_map_ ? &(*a_nullable_map_) : nullptr;
}
void AllNullableTypes::set_a_nullable_map(const EncodableMap* value_arg) {
  a_nullable_map_ =
      value_arg ? std::optional<EncodableMap>(*value_arg) : std::nullopt;
}
void AllNullableTypes::set_a_nullable_map(const EncodableMap& value_arg) {
  a_nullable_map_ = value_arg;
}

const EncodableList* AllNullableTypes::nullable_nested_list() const {
  return nullable_nested_list_ ? &(*nullable_nested_list_) : nullptr;
}
void AllNullableTypes::set_nullable_nested_list(
    const EncodableList* value_arg) {
  nullable_nested_list_ =
      value_arg ? std::optional<EncodableList>(*value_arg) : std::nullopt;
}
void AllNullableTypes::set_nullable_nested_list(
    const EncodableList& value_arg) {
  nullable_nested_list_ = value_arg;
}

const EncodableMap* AllNullableTypes::nullable_map_with_annotations() const {
  return nullable_map_with_annotations_ ? &(*nullable_map_with_annotations_)
                                        : nullptr;
}
void AllNullableTypes::set_nullable_map_with_annotations(
    const EncodableMap* value_arg) {
  nullable_map_with_annotations_ =
      value_arg ? std::optional<EncodableMap>(*value_arg) : std::nullopt;
}
void AllNullableTypes::set_nullable_map_with_annotations(
    const EncodableMap& value_arg) {
  nullable_map_with_annotations_ = value_arg;
}

const EncodableMap* AllNullableTypes::nullable_map_with_object() const {
  return nullable_map_with_object_ ? &(*nullable_map_with_object_) : nullptr;
}
void AllNullableTypes::set_nullable_map_with_object(
    const EncodableMap* value_arg) {
  nullable_map_with_object_ =
      value_arg ? std::optional<EncodableMap>(*value_arg) : std::nullopt;
}
void AllNullableTypes::set_nullable_map_with_object(
    const EncodableMap& value_arg) {
  nullable_map_with_object_ = value_arg;
}

const AnEnum* AllNullableTypes::a_nullable_enum() const {
  return a_nullable_enum_ ? &(*a_nullable_enum_) : nullptr;
}
void AllNullableTypes::set_a_nullable_enum(const AnEnum* value_arg) {
  a_nullable_enum_ =
      value_arg ? std::optional<AnEnum>(*value_arg) : std::nullopt;
}
void AllNullableTypes::set_a_nullable_enum(const AnEnum& value_arg) {
  a_nullable_enum_ = value_arg;
}

const std::string* AllNullableTypes::a_nullable_string() const {
  return a_nullable_string_ ? &(*a_nullable_string_) : nullptr;
}
void AllNullableTypes::set_a_nullable_string(
    const std::string_view* value_arg) {
  a_nullable_string_ =
      value_arg ? std::optional<std::string>(*value_arg) : std::nullopt;
}
void AllNullableTypes::set_a_nullable_string(std::string_view value_arg) {
  a_nullable_string_ = value_arg;
}

EncodableList AllNullableTypes::ToEncodableList() const {
  EncodableList list;
  list.reserve(14);
  list.push_back(a_nullable_bool_ ? EncodableValue(*a_nullable_bool_)
                                  : EncodableValue());
  list.push_back(a_nullable_int_ ? EncodableValue(*a_nullable_int_)
                                 : EncodableValue());
  list.push_back(a_nullable_double_ ? EncodableValue(*a_nullable_double_)
                                    : EncodableValue());
  list.push_back(a_nullable_byte_array_
                     ? EncodableValue(*a_nullable_byte_array_)
                     : EncodableValue());
  list.push_back(a_nullable4_byte_array_
                     ? EncodableValue(*a_nullable4_byte_array_)
                     : EncodableValue());
  list.push_back(a_nullable8_byte_array_
                     ? EncodableValue(*a_nullable8_byte_array_)
                     : EncodableValue());
  list.push_back(a_nullable_float_array_
                     ? EncodableValue(*a_nullable_float_array_)
                     : EncodableValue());
  list.push_back(a_nullable_list_ ? EncodableValue(*a_nullable_list_)
                                  : EncodableValue());
  list.push_back(a_nullable_map_ ? EncodableValue(*a_nullable_map_)
                                 : EncodableValue());
  list.push_back(nullable_nested_list_ ? EncodableValue(*nullable_nested_list_)
                                       : EncodableValue());
  list.push_back(nullable_map_with_annotations_
                     ? EncodableValue(*nullable_map_with_annotations_)
                     : EncodableValue());
  list.push_back(nullable_map_with_object_
                     ? EncodableValue(*nullable_map_with_object_)
                     : EncodableValue());
  list.push_back(a_nullable_enum_ ? EncodableValue((int)(*a_nullable_enum_))
                                  : EncodableValue());
  list.push_back(a_nullable_string_ ? EncodableValue(*a_nullable_string_)
                                    : EncodableValue());
  return list;
}

AllNullableTypes::AllNullableTypes() {}

AllNullableTypes::AllNullableTypes(const EncodableList& list) {
  auto& encodable_a_nullable_bool = list[0];
  if (const bool* pointer_a_nullable_bool =
          std::get_if<bool>(&encodable_a_nullable_bool)) {
    a_nullable_bool_ = *pointer_a_nullable_bool;
  }
  auto& encodable_a_nullable_int = list[1];
  if (const int32_t* pointer_a_nullable_int =
          std::get_if<int32_t>(&encodable_a_nullable_int))
    a_nullable_int_ = *pointer_a_nullable_int;
  else if (const int64_t* pointer_a_nullable_int_64 =
               std::get_if<int64_t>(&encodable_a_nullable_int))
    a_nullable_int_ = *pointer_a_nullable_int_64;
  auto& encodable_a_nullable_double = list[2];
  if (const double* pointer_a_nullable_double =
          std::get_if<double>(&encodable_a_nullable_double)) {
    a_nullable_double_ = *pointer_a_nullable_double;
  }
  auto& encodable_a_nullable_byte_array = list[3];
  if (const std::vector<uint8_t>* pointer_a_nullable_byte_array =
          std::get_if<std::vector<uint8_t>>(&encodable_a_nullable_byte_array)) {
    a_nullable_byte_array_ = *pointer_a_nullable_byte_array;
  }
  auto& encodable_a_nullable4_byte_array = list[4];
  if (const std::vector<int32_t>* pointer_a_nullable4_byte_array =
          std::get_if<std::vector<int32_t>>(
              &encodable_a_nullable4_byte_array)) {
    a_nullable4_byte_array_ = *pointer_a_nullable4_byte_array;
  }
  auto& encodable_a_nullable8_byte_array = list[5];
  if (const std::vector<int64_t>* pointer_a_nullable8_byte_array =
          std::get_if<std::vector<int64_t>>(
              &encodable_a_nullable8_byte_array)) {
    a_nullable8_byte_array_ = *pointer_a_nullable8_byte_array;
  }
  auto& encodable_a_nullable_float_array = list[6];
  if (const std::vector<double>* pointer_a_nullable_float_array =
          std::get_if<std::vector<double>>(&encodable_a_nullable_float_array)) {
    a_nullable_float_array_ = *pointer_a_nullable_float_array;
  }
  auto& encodable_a_nullable_list = list[7];
  if (const EncodableList* pointer_a_nullable_list =
          std::get_if<EncodableList>(&encodable_a_nullable_list)) {
    a_nullable_list_ = *pointer_a_nullable_list;
  }
  auto& encodable_a_nullable_map = list[8];
  if (const EncodableMap* pointer_a_nullable_map =
          std::get_if<EncodableMap>(&encodable_a_nullable_map)) {
    a_nullable_map_ = *pointer_a_nullable_map;
  }
  auto& encodable_nullable_nested_list = list[9];
  if (const EncodableList* pointer_nullable_nested_list =
          std::get_if<EncodableList>(&encodable_nullable_nested_list)) {
    nullable_nested_list_ = *pointer_nullable_nested_list;
  }
  auto& encodable_nullable_map_with_annotations = list[10];
  if (const EncodableMap* pointer_nullable_map_with_annotations =
          std::get_if<EncodableMap>(&encodable_nullable_map_with_annotations)) {
    nullable_map_with_annotations_ = *pointer_nullable_map_with_annotations;
  }
  auto& encodable_nullable_map_with_object = list[11];
  if (const EncodableMap* pointer_nullable_map_with_object =
          std::get_if<EncodableMap>(&encodable_nullable_map_with_object)) {
    nullable_map_with_object_ = *pointer_nullable_map_with_object;
  }
  auto& encodable_a_nullable_enum = list[12];
  if (const int32_t* pointer_a_nullable_enum =
          std::get_if<int32_t>(&encodable_a_nullable_enum))
    a_nullable_enum_ = (AnEnum)*pointer_a_nullable_enum;
  auto& encodable_a_nullable_string = list[13];
  if (const std::string* pointer_a_nullable_string =
          std::get_if<std::string>(&encodable_a_nullable_string)) {
    a_nullable_string_ = *pointer_a_nullable_string;
  }
}

// AllNullableTypesWrapper

const AllNullableTypes& AllNullableTypesWrapper::values() const {
  return values_;
}
void AllNullableTypesWrapper::set_values(const AllNullableTypes& value_arg) {
  values_ = value_arg;
}

EncodableList AllNullableTypesWrapper::ToEncodableList() const {
  EncodableList list;
  list.reserve(1);
  list.push_back(EncodableValue(values_.ToEncodableList()));
  return list;
}

AllNullableTypesWrapper::AllNullableTypesWrapper() {}

AllNullableTypesWrapper::AllNullableTypesWrapper(const EncodableList& list) {
  auto& encodable_values = list[0];
  if (const EncodableList* pointer_values =
          std::get_if<EncodableList>(&encodable_values)) {
    values_ = AllNullableTypes(*pointer_values);
  }
}

HostIntegrationCoreApiCodecSerializer::HostIntegrationCoreApiCodecSerializer() {
}
EncodableValue HostIntegrationCoreApiCodecSerializer::ReadValueOfType(
    uint8_t type, flutter::ByteStreamReader* stream) const {
  switch (type) {
    case 128:
      return CustomEncodableValue(
          AllNullableTypes(std::get<EncodableList>(ReadValue(stream))));
    case 129:
      return CustomEncodableValue(
          AllNullableTypesWrapper(std::get<EncodableList>(ReadValue(stream))));
    case 130:
      return CustomEncodableValue(
          AllTypes(std::get<EncodableList>(ReadValue(stream))));
    default:
      return flutter::StandardCodecSerializer::ReadValueOfType(type, stream);
  }
}

void HostIntegrationCoreApiCodecSerializer::WriteValue(
    const EncodableValue& value, flutter::ByteStreamWriter* stream) const {
  if (const CustomEncodableValue* custom_value =
          std::get_if<CustomEncodableValue>(&value)) {
    if (custom_value->type() == typeid(AllNullableTypes)) {
      stream->WriteByte(128);
      WriteValue(
          EncodableValue(
              std::any_cast<AllNullableTypes>(*custom_value).ToEncodableList()),
          stream);
      return;
    }
    if (custom_value->type() == typeid(AllNullableTypesWrapper)) {
      stream->WriteByte(129);
      WriteValue(
          EncodableValue(std::any_cast<AllNullableTypesWrapper>(*custom_value)
                             .ToEncodableList()),
          stream);
      return;
    }
    if (custom_value->type() == typeid(AllTypes)) {
      stream->WriteByte(130);
      WriteValue(EncodableValue(
                     std::any_cast<AllTypes>(*custom_value).ToEncodableList()),
                 stream);
      return;
    }
  }
  flutter::StandardCodecSerializer::WriteValue(value, stream);
}

/// The codec used by HostIntegrationCoreApi.
const flutter::StandardMessageCodec& HostIntegrationCoreApi::GetCodec() {
  return flutter::StandardMessageCodec::GetInstance(
      &HostIntegrationCoreApiCodecSerializer::GetInstance());
}

// Sets up an instance of `HostIntegrationCoreApi` to handle messages through
// the `binary_messenger`.
void HostIntegrationCoreApi::SetUp(flutter::BinaryMessenger* binary_messenger,
                                   HostIntegrationCoreApi* api) {
  {
    auto channel = std::make_unique<BasicMessageChannel<>>(
        binary_messenger, "dev.flutter.pigeon.HostIntegrationCoreApi.noop",
        &GetCodec());
    if (api != nullptr) {
      channel->SetMessageHandler(
          [api](const EncodableValue& message,
                const flutter::MessageReply<EncodableValue>& reply) {
            try {
              std::optional<FlutterError> output = api->Noop();
              if (output.has_value()) {
                reply(WrapError(output.value()));
                return;
              }
              EncodableList wrapped;
              wrapped.push_back(EncodableValue());
              reply(EncodableValue(std::move(wrapped)));
            } catch (const std::exception& exception) {
              reply(WrapError(exception.what()));
            }
          });
    } else {
      channel->SetMessageHandler(nullptr);
    }
  }
  {
    auto channel = std::make_unique<BasicMessageChannel<>>(
        binary_messenger,
        "dev.flutter.pigeon.HostIntegrationCoreApi.echoAllTypes", &GetCodec());
    if (api != nullptr) {
      channel->SetMessageHandler(
          [api](const EncodableValue& message,
                const flutter::MessageReply<EncodableValue>& reply) {
            try {
              const auto& args = std::get<EncodableList>(message);
              const auto& encodable_everything_arg = args.at(0);
              if (encodable_everything_arg.IsNull()) {
                reply(WrapError("everything_arg unexpectedly null."));
                return;
              }
              const auto& everything_arg = std::any_cast<const AllTypes&>(
                  std::get<CustomEncodableValue>(encodable_everything_arg));
              ErrorOr<AllTypes> output = api->EchoAllTypes(everything_arg);
              if (output.has_error()) {
                reply(WrapError(output.error()));
                return;
              }
              EncodableList wrapped;
              wrapped.push_back(
                  CustomEncodableValue(std::move(output).TakeValue()));
              reply(EncodableValue(std::move(wrapped)));
            } catch (const std::exception& exception) {
              reply(WrapError(exception.what()));
            }
          });
    } else {
      channel->SetMessageHandler(nullptr);
    }
  }
  {
    auto channel = std::make_unique<BasicMessageChannel<>>(
        binary_messenger,
        "dev.flutter.pigeon.HostIntegrationCoreApi.echoAllNullableTypes",
        &GetCodec());
    if (api != nullptr) {
      channel->SetMessageHandler(
          [api](const EncodableValue& message,
                const flutter::MessageReply<EncodableValue>& reply) {
            try {
              const auto& args = std::get<EncodableList>(message);
              const auto& encodable_everything_arg = args.at(0);
              const auto* everything_arg =
                  &(std::any_cast<const AllNullableTypes&>(
                      std::get<CustomEncodableValue>(
                          encodable_everything_arg)));
              ErrorOr<std::optional<AllNullableTypes>> output =
                  api->EchoAllNullableTypes(everything_arg);
              if (output.has_error()) {
                reply(WrapError(output.error()));
                return;
              }
              EncodableList wrapped;
              auto output_optional = std::move(output).TakeValue();
              if (output_optional) {
                wrapped.push_back(
                    CustomEncodableValue(std::move(output_optional).value()));
              } else {
                wrapped.push_back(EncodableValue());
              }
              reply(EncodableValue(std::move(wrapped)));
            } catch (const std::exception& exception) {
              reply(WrapError(exception.what()));
            }
          });
    } else {
      channel->SetMessageHandler(nullptr);
    }
  }
  {
    auto channel = std::make_unique<BasicMessageChannel<>>(
        binary_messenger,
        "dev.flutter.pigeon.HostIntegrationCoreApi.throwError", &GetCodec());
    if (api != nullptr) {
      channel->SetMessageHandler(
          [api](const EncodableValue& message,
                const flutter::MessageReply<EncodableValue>& reply) {
            try {
              std::optional<FlutterError> output = api->ThrowError();
              if (output.has_value()) {
                reply(WrapError(output.value()));
                return;
              }
              EncodableList wrapped;
              wrapped.push_back(EncodableValue());
              reply(EncodableValue(std::move(wrapped)));
            } catch (const std::exception& exception) {
              reply(WrapError(exception.what()));
            }
          });
    } else {
      channel->SetMessageHandler(nullptr);
    }
  }
  {
    auto channel = std::make_unique<BasicMessageChannel<>>(
        binary_messenger, "dev.flutter.pigeon.HostIntegrationCoreApi.echoInt",
        &GetCodec());
    if (api != nullptr) {
      channel->SetMessageHandler(
          [api](const EncodableValue& message,
                const flutter::MessageReply<EncodableValue>& reply) {
            try {
              const auto& args = std::get<EncodableList>(message);
              const auto& encodable_an_int_arg = args.at(0);
              if (encodable_an_int_arg.IsNull()) {
                reply(WrapError("an_int_arg unexpectedly null."));
                return;
              }
              const int64_t an_int_arg = encodable_an_int_arg.LongValue();
              ErrorOr<int64_t> output = api->EchoInt(an_int_arg);
              if (output.has_error()) {
                reply(WrapError(output.error()));
                return;
              }
              EncodableList wrapped;
              wrapped.push_back(EncodableValue(std::move(output).TakeValue()));
              reply(EncodableValue(std::move(wrapped)));
            } catch (const std::exception& exception) {
              reply(WrapError(exception.what()));
            }
          });
    } else {
      channel->SetMessageHandler(nullptr);
    }
  }
  {
    auto channel = std::make_unique<BasicMessageChannel<>>(
        binary_messenger,
        "dev.flutter.pigeon.HostIntegrationCoreApi.echoDouble", &GetCodec());
    if (api != nullptr) {
      channel->SetMessageHandler(
          [api](const EncodableValue& message,
                const flutter::MessageReply<EncodableValue>& reply) {
            try {
              const auto& args = std::get<EncodableList>(message);
              const auto& encodable_a_double_arg = args.at(0);
              if (encodable_a_double_arg.IsNull()) {
                reply(WrapError("a_double_arg unexpectedly null."));
                return;
              }
              const auto& a_double_arg =
                  std::get<double>(encodable_a_double_arg);
              ErrorOr<double> output = api->EchoDouble(a_double_arg);
              if (output.has_error()) {
                reply(WrapError(output.error()));
                return;
              }
              EncodableList wrapped;
              wrapped.push_back(EncodableValue(std::move(output).TakeValue()));
              reply(EncodableValue(std::move(wrapped)));
            } catch (const std::exception& exception) {
              reply(WrapError(exception.what()));
            }
          });
    } else {
      channel->SetMessageHandler(nullptr);
    }
  }
  {
    auto channel = std::make_unique<BasicMessageChannel<>>(
        binary_messenger, "dev.flutter.pigeon.HostIntegrationCoreApi.echoBool",
        &GetCodec());
    if (api != nullptr) {
      channel->SetMessageHandler(
          [api](const EncodableValue& message,
                const flutter::MessageReply<EncodableValue>& reply) {
            try {
              const auto& args = std::get<EncodableList>(message);
              const auto& encodable_a_bool_arg = args.at(0);
              if (encodable_a_bool_arg.IsNull()) {
                reply(WrapError("a_bool_arg unexpectedly null."));
                return;
              }
              const auto& a_bool_arg = std::get<bool>(encodable_a_bool_arg);
              ErrorOr<bool> output = api->EchoBool(a_bool_arg);
              if (output.has_error()) {
                reply(WrapError(output.error()));
                return;
              }
              EncodableList wrapped;
              wrapped.push_back(EncodableValue(std::move(output).TakeValue()));
              reply(EncodableValue(std::move(wrapped)));
            } catch (const std::exception& exception) {
              reply(WrapError(exception.what()));
            }
          });
    } else {
      channel->SetMessageHandler(nullptr);
    }
  }
  {
    auto channel = std::make_unique<BasicMessageChannel<>>(
        binary_messenger,
        "dev.flutter.pigeon.HostIntegrationCoreApi.echoString", &GetCodec());
    if (api != nullptr) {
      channel->SetMessageHandler(
          [api](const EncodableValue& message,
                const flutter::MessageReply<EncodableValue>& reply) {
            try {
              const auto& args = std::get<EncodableList>(message);
              const auto& encodable_a_string_arg = args.at(0);
              if (encodable_a_string_arg.IsNull()) {
                reply(WrapError("a_string_arg unexpectedly null."));
                return;
              }
              const auto& a_string_arg =
                  std::get<std::string>(encodable_a_string_arg);
              ErrorOr<std::string> output = api->EchoString(a_string_arg);
              if (output.has_error()) {
                reply(WrapError(output.error()));
                return;
              }
              EncodableList wrapped;
              wrapped.push_back(EncodableValue(std::move(output).TakeValue()));
              reply(EncodableValue(std::move(wrapped)));
            } catch (const std::exception& exception) {
              reply(WrapError(exception.what()));
            }
          });
    } else {
      channel->SetMessageHandler(nullptr);
    }
  }
  {
    auto channel = std::make_unique<BasicMessageChannel<>>(
        binary_messenger,
        "dev.flutter.pigeon.HostIntegrationCoreApi.echoUint8List", &GetCodec());
    if (api != nullptr) {
      channel->SetMessageHandler(
          [api](const EncodableValue& message,
                const flutter::MessageReply<EncodableValue>& reply) {
            try {
              const auto& args = std::get<EncodableList>(message);
              const auto& encodable_a_uint8_list_arg = args.at(0);
              if (encodable_a_uint8_list_arg.IsNull()) {
                reply(WrapError("a_uint8_list_arg unexpectedly null."));
                return;
              }
              const auto& a_uint8_list_arg =
                  std::get<std::vector<uint8_t>>(encodable_a_uint8_list_arg);
              ErrorOr<std::vector<uint8_t>> output =
                  api->EchoUint8List(a_uint8_list_arg);
              if (output.has_error()) {
                reply(WrapError(output.error()));
                return;
              }
              EncodableList wrapped;
              wrapped.push_back(EncodableValue(std::move(output).TakeValue()));
              reply(EncodableValue(std::move(wrapped)));
            } catch (const std::exception& exception) {
              reply(WrapError(exception.what()));
            }
          });
    } else {
      channel->SetMessageHandler(nullptr);
    }
  }
  {
    auto channel = std::make_unique<BasicMessageChannel<>>(
        binary_messenger,
        "dev.flutter.pigeon.HostIntegrationCoreApi.echoObject", &GetCodec());
    if (api != nullptr) {
      channel->SetMessageHandler(
          [api](const EncodableValue& message,
                const flutter::MessageReply<EncodableValue>& reply) {
            try {
              const auto& args = std::get<EncodableList>(message);
              const auto& encodable_an_object_arg = args.at(0);
              if (encodable_an_object_arg.IsNull()) {
                reply(WrapError("an_object_arg unexpectedly null."));
                return;
              }
              const auto& an_object_arg = encodable_an_object_arg;
              ErrorOr<EncodableValue> output = api->EchoObject(an_object_arg);
              if (output.has_error()) {
                reply(WrapError(output.error()));
                return;
              }
              EncodableList wrapped;
              wrapped.push_back(EncodableValue(std::move(output).TakeValue()));
              reply(EncodableValue(std::move(wrapped)));
            } catch (const std::exception& exception) {
              reply(WrapError(exception.what()));
            }
          });
    } else {
      channel->SetMessageHandler(nullptr);
    }
  }
  {
    auto channel = std::make_unique<BasicMessageChannel<>>(
        binary_messenger,
        "dev.flutter.pigeon.HostIntegrationCoreApi.extractNestedNullableString",
        &GetCodec());
    if (api != nullptr) {
      channel->SetMessageHandler(
          [api](const EncodableValue& message,
                const flutter::MessageReply<EncodableValue>& reply) {
            try {
              const auto& args = std::get<EncodableList>(message);
              const auto& encodable_wrapper_arg = args.at(0);
              if (encodable_wrapper_arg.IsNull()) {
                reply(WrapError("wrapper_arg unexpectedly null."));
                return;
              }
              const auto& wrapper_arg =
                  std::any_cast<const AllNullableTypesWrapper&>(
                      std::get<CustomEncodableValue>(encodable_wrapper_arg));
              ErrorOr<std::optional<std::string>> output =
                  api->ExtractNestedNullableString(wrapper_arg);
              if (output.has_error()) {
                reply(WrapError(output.error()));
                return;
              }
              EncodableList wrapped;
              auto output_optional = std::move(output).TakeValue();
              if (output_optional) {
                wrapped.push_back(
                    EncodableValue(std::move(output_optional).value()));
              } else {
                wrapped.push_back(EncodableValue());
              }
              reply(EncodableValue(std::move(wrapped)));
            } catch (const std::exception& exception) {
              reply(WrapError(exception.what()));
            }
          });
    } else {
      channel->SetMessageHandler(nullptr);
    }
  }
  {
    auto channel = std::make_unique<BasicMessageChannel<>>(
        binary_messenger,
        "dev.flutter.pigeon.HostIntegrationCoreApi.createNestedNullableString",
        &GetCodec());
    if (api != nullptr) {
      channel->SetMessageHandler(
          [api](const EncodableValue& message,
                const flutter::MessageReply<EncodableValue>& reply) {
            try {
              const auto& args = std::get<EncodableList>(message);
              const auto& encodable_nullable_string_arg = args.at(0);
              const auto* nullable_string_arg =
                  std::get_if<std::string>(&encodable_nullable_string_arg);
              ErrorOr<AllNullableTypesWrapper> output =
                  api->CreateNestedNullableString(nullable_string_arg);
              if (output.has_error()) {
                reply(WrapError(output.error()));
                return;
              }
              EncodableList wrapped;
              wrapped.push_back(
                  CustomEncodableValue(std::move(output).TakeValue()));
              reply(EncodableValue(std::move(wrapped)));
            } catch (const std::exception& exception) {
              reply(WrapError(exception.what()));
            }
          });
    } else {
      channel->SetMessageHandler(nullptr);
    }
  }
  {
    auto channel = std::make_unique<BasicMessageChannel<>>(
        binary_messenger,
        "dev.flutter.pigeon.HostIntegrationCoreApi.sendMultipleNullableTypes",
        &GetCodec());
    if (api != nullptr) {
      channel->SetMessageHandler(
          [api](const EncodableValue& message,
                const flutter::MessageReply<EncodableValue>& reply) {
            try {
              const auto& args = std::get<EncodableList>(message);
              const auto& encodable_a_nullable_bool_arg = args.at(0);
              const auto* a_nullable_bool_arg =
                  std::get_if<bool>(&encodable_a_nullable_bool_arg);
              const auto& encodable_a_nullable_int_arg = args.at(1);
              const int64_t a_nullable_int_arg_value =
                  encodable_a_nullable_int_arg.IsNull()
                      ? 0
                      : encodable_a_nullable_int_arg.LongValue();
              const auto* a_nullable_int_arg =
                  encodable_a_nullable_int_arg.IsNull()
                      ? nullptr
                      : &a_nullable_int_arg_value;
              const auto& encodable_a_nullable_string_arg = args.at(2);
              const auto* a_nullable_string_arg =
                  std::get_if<std::string>(&encodable_a_nullable_string_arg);
              ErrorOr<AllNullableTypes> output = api->SendMultipleNullableTypes(
                  a_nullable_bool_arg, a_nullable_int_arg,
                  a_nullable_string_arg);
              if (output.has_error()) {
                reply(WrapError(output.error()));
                return;
              }
              EncodableList wrapped;
              wrapped.push_back(
                  CustomEncodableValue(std::move(output).TakeValue()));
              reply(EncodableValue(std::move(wrapped)));
            } catch (const std::exception& exception) {
              reply(WrapError(exception.what()));
            }
          });
    } else {
      channel->SetMessageHandler(nullptr);
    }
  }
  {
    auto channel = std::make_unique<BasicMessageChannel<>>(
        binary_messenger,
        "dev.flutter.pigeon.HostIntegrationCoreApi.echoNullableInt",
        &GetCodec());
    if (api != nullptr) {
      channel->SetMessageHandler(
          [api](const EncodableValue& message,
                const flutter::MessageReply<EncodableValue>& reply) {
            try {
              const auto& args = std::get<EncodableList>(message);
              const auto& encodable_a_nullable_int_arg = args.at(0);
              const int64_t a_nullable_int_arg_value =
                  encodable_a_nullable_int_arg.IsNull()
                      ? 0
                      : encodable_a_nullable_int_arg.LongValue();
              const auto* a_nullable_int_arg =
                  encodable_a_nullable_int_arg.IsNull()
                      ? nullptr
                      : &a_nullable_int_arg_value;
              ErrorOr<std::optional<int64_t>> output =
                  api->EchoNullableInt(a_nullable_int_arg);
              if (output.has_error()) {
                reply(WrapError(output.error()));
                return;
              }
              EncodableList wrapped;
              auto output_optional = std::move(output).TakeValue();
              if (output_optional) {
                wrapped.push_back(
                    EncodableValue(std::move(output_optional).value()));
              } else {
                wrapped.push_back(EncodableValue());
              }
              reply(EncodableValue(std::move(wrapped)));
            } catch (const std::exception& exception) {
              reply(WrapError(exception.what()));
            }
          });
    } else {
      channel->SetMessageHandler(nullptr);
    }
  }
  {
    auto channel = std::make_unique<BasicMessageChannel<>>(
        binary_messenger,
        "dev.flutter.pigeon.HostIntegrationCoreApi.echoNullableDouble",
        &GetCodec());
    if (api != nullptr) {
      channel->SetMessageHandler(
          [api](const EncodableValue& message,
                const flutter::MessageReply<EncodableValue>& reply) {
            try {
              const auto& args = std::get<EncodableList>(message);
              const auto& encodable_a_nullable_double_arg = args.at(0);
              const auto* a_nullable_double_arg =
                  std::get_if<double>(&encodable_a_nullable_double_arg);
              ErrorOr<std::optional<double>> output =
                  api->EchoNullableDouble(a_nullable_double_arg);
              if (output.has_error()) {
                reply(WrapError(output.error()));
                return;
              }
              EncodableList wrapped;
              auto output_optional = std::move(output).TakeValue();
              if (output_optional) {
                wrapped.push_back(
                    EncodableValue(std::move(output_optional).value()));
              } else {
                wrapped.push_back(EncodableValue());
              }
              reply(EncodableValue(std::move(wrapped)));
            } catch (const std::exception& exception) {
              reply(WrapError(exception.what()));
            }
          });
    } else {
      channel->SetMessageHandler(nullptr);
    }
  }
  {
    auto channel = std::make_unique<BasicMessageChannel<>>(
        binary_messenger,
        "dev.flutter.pigeon.HostIntegrationCoreApi.echoNullableBool",
        &GetCodec());
    if (api != nullptr) {
      channel->SetMessageHandler(
          [api](const EncodableValue& message,
                const flutter::MessageReply<EncodableValue>& reply) {
            try {
              const auto& args = std::get<EncodableList>(message);
              const auto& encodable_a_nullable_bool_arg = args.at(0);
              const auto* a_nullable_bool_arg =
                  std::get_if<bool>(&encodable_a_nullable_bool_arg);
              ErrorOr<std::optional<bool>> output =
                  api->EchoNullableBool(a_nullable_bool_arg);
              if (output.has_error()) {
                reply(WrapError(output.error()));
                return;
              }
              EncodableList wrapped;
              auto output_optional = std::move(output).TakeValue();
              if (output_optional) {
                wrapped.push_back(
                    EncodableValue(std::move(output_optional).value()));
              } else {
                wrapped.push_back(EncodableValue());
              }
              reply(EncodableValue(std::move(wrapped)));
            } catch (const std::exception& exception) {
              reply(WrapError(exception.what()));
            }
          });
    } else {
      channel->SetMessageHandler(nullptr);
    }
  }
  {
    auto channel = std::make_unique<BasicMessageChannel<>>(
        binary_messenger,
        "dev.flutter.pigeon.HostIntegrationCoreApi.echoNullableString",
        &GetCodec());
    if (api != nullptr) {
      channel->SetMessageHandler(
          [api](const EncodableValue& message,
                const flutter::MessageReply<EncodableValue>& reply) {
            try {
              const auto& args = std::get<EncodableList>(message);
              const auto& encodable_a_nullable_string_arg = args.at(0);
              const auto* a_nullable_string_arg =
                  std::get_if<std::string>(&encodable_a_nullable_string_arg);
              ErrorOr<std::optional<std::string>> output =
                  api->EchoNullableString(a_nullable_string_arg);
              if (output.has_error()) {
                reply(WrapError(output.error()));
                return;
              }
              EncodableList wrapped;
              auto output_optional = std::move(output).TakeValue();
              if (output_optional) {
                wrapped.push_back(
                    EncodableValue(std::move(output_optional).value()));
              } else {
                wrapped.push_back(EncodableValue());
              }
              reply(EncodableValue(std::move(wrapped)));
            } catch (const std::exception& exception) {
              reply(WrapError(exception.what()));
            }
          });
    } else {
      channel->SetMessageHandler(nullptr);
    }
  }
  {
    auto channel = std::make_unique<BasicMessageChannel<>>(
        binary_messenger,
        "dev.flutter.pigeon.HostIntegrationCoreApi.echoNullableUint8List",
        &GetCodec());
    if (api != nullptr) {
      channel->SetMessageHandler(
          [api](const EncodableValue& message,
                const flutter::MessageReply<EncodableValue>& reply) {
            try {
              const auto& args = std::get<EncodableList>(message);
              const auto& encodable_a_nullable_uint8_list_arg = args.at(0);
              const auto* a_nullable_uint8_list_arg =
                  std::get_if<std::vector<uint8_t>>(
                      &encodable_a_nullable_uint8_list_arg);
              ErrorOr<std::optional<std::vector<uint8_t>>> output =
                  api->EchoNullableUint8List(a_nullable_uint8_list_arg);
              if (output.has_error()) {
                reply(WrapError(output.error()));
                return;
              }
              EncodableList wrapped;
              auto output_optional = std::move(output).TakeValue();
              if (output_optional) {
                wrapped.push_back(
                    EncodableValue(std::move(output_optional).value()));
              } else {
                wrapped.push_back(EncodableValue());
              }
              reply(EncodableValue(std::move(wrapped)));
            } catch (const std::exception& exception) {
              reply(WrapError(exception.what()));
            }
          });
    } else {
      channel->SetMessageHandler(nullptr);
    }
  }
  {
    auto channel = std::make_unique<BasicMessageChannel<>>(
        binary_messenger,
        "dev.flutter.pigeon.HostIntegrationCoreApi.echoNullableObject",
        &GetCodec());
    if (api != nullptr) {
      channel->SetMessageHandler(
          [api](const EncodableValue& message,
                const flutter::MessageReply<EncodableValue>& reply) {
            try {
              const auto& args = std::get<EncodableList>(message);
              const auto& encodable_a_nullable_object_arg = args.at(0);
              const auto* a_nullable_object_arg =
                  &encodable_a_nullable_object_arg;
              ErrorOr<std::optional<EncodableValue>> output =
                  api->EchoNullableObject(a_nullable_object_arg);
              if (output.has_error()) {
                reply(WrapError(output.error()));
                return;
              }
              EncodableList wrapped;
              auto output_optional = std::move(output).TakeValue();
              if (output_optional) {
                wrapped.push_back(
                    EncodableValue(std::move(output_optional).value()));
              } else {
                wrapped.push_back(EncodableValue());
              }
              reply(EncodableValue(std::move(wrapped)));
            } catch (const std::exception& exception) {
              reply(WrapError(exception.what()));
            }
          });
    } else {
      channel->SetMessageHandler(nullptr);
    }
  }
  {
    auto channel = std::make_unique<BasicMessageChannel<>>(
        binary_messenger, "dev.flutter.pigeon.HostIntegrationCoreApi.noopAsync",
        &GetCodec());
    if (api != nullptr) {
      channel->SetMessageHandler(
          [api](const EncodableValue& message,
                const flutter::MessageReply<EncodableValue>& reply) {
            try {
              api->NoopAsync([reply](std::optional<FlutterError>&& output) {
                if (output.has_value()) {
                  reply(WrapError(output.value()));
                  return;
                }
                EncodableList wrapped;
                wrapped.push_back(EncodableValue());
                reply(EncodableValue(std::move(wrapped)));
              });
            } catch (const std::exception& exception) {
              reply(WrapError(exception.what()));
            }
          });
    } else {
      channel->SetMessageHandler(nullptr);
    }
  }
  {
    auto channel = std::make_unique<BasicMessageChannel<>>(
        binary_messenger,
        "dev.flutter.pigeon.HostIntegrationCoreApi.echoAsyncString",
        &GetCodec());
    if (api != nullptr) {
      channel->SetMessageHandler(
          [api](const EncodableValue& message,
                const flutter::MessageReply<EncodableValue>& reply) {
            try {
              const auto& args = std::get<EncodableList>(message);
              const auto& encodable_a_string_arg = args.at(0);
              if (encodable_a_string_arg.IsNull()) {
                reply(WrapError("a_string_arg unexpectedly null."));
                return;
              }
              const auto& a_string_arg =
                  std::get<std::string>(encodable_a_string_arg);
              api->EchoAsyncString(
                  a_string_arg, [reply](ErrorOr<std::string>&& output) {
                    if (output.has_error()) {
                      reply(WrapError(output.error()));
                      return;
                    }
                    EncodableList wrapped;
                    wrapped.push_back(
                        EncodableValue(std::move(output).TakeValue()));
                    reply(EncodableValue(std::move(wrapped)));
                  });
            } catch (const std::exception& exception) {
              reply(WrapError(exception.what()));
            }
          });
    } else {
      channel->SetMessageHandler(nullptr);
    }
  }
  {
    auto channel = std::make_unique<BasicMessageChannel<>>(
        binary_messenger,
        "dev.flutter.pigeon.HostIntegrationCoreApi.callFlutterNoop",
        &GetCodec());
    if (api != nullptr) {
      channel->SetMessageHandler(
          [api](const EncodableValue& message,
                const flutter::MessageReply<EncodableValue>& reply) {
            try {
              api->CallFlutterNoop(
                  [reply](std::optional<FlutterError>&& output) {
                    if (output.has_value()) {
                      reply(WrapError(output.value()));
                      return;
                    }
                    EncodableList wrapped;
                    wrapped.push_back(EncodableValue());
                    reply(EncodableValue(std::move(wrapped)));
                  });
            } catch (const std::exception& exception) {
              reply(WrapError(exception.what()));
            }
          });
    } else {
      channel->SetMessageHandler(nullptr);
    }
  }
  {
    auto channel = std::make_unique<BasicMessageChannel<>>(
        binary_messenger,
        "dev.flutter.pigeon.HostIntegrationCoreApi.callFlutterEchoAllTypes",
        &GetCodec());
    if (api != nullptr) {
      channel->SetMessageHandler(
          [api](const EncodableValue& message,
                const flutter::MessageReply<EncodableValue>& reply) {
            try {
              const auto& args = std::get<EncodableList>(message);
              const auto& encodable_everything_arg = args.at(0);
              if (encodable_everything_arg.IsNull()) {
                reply(WrapError("everything_arg unexpectedly null."));
                return;
              }
              const auto& everything_arg = std::any_cast<const AllTypes&>(
                  std::get<CustomEncodableValue>(encodable_everything_arg));
              api->CallFlutterEchoAllTypes(
                  everything_arg, [reply](ErrorOr<AllTypes>&& output) {
                    if (output.has_error()) {
                      reply(WrapError(output.error()));
                      return;
                    }
                    EncodableList wrapped;
                    wrapped.push_back(
                        CustomEncodableValue(std::move(output).TakeValue()));
                    reply(EncodableValue(std::move(wrapped)));
                  });
            } catch (const std::exception& exception) {
              reply(WrapError(exception.what()));
            }
          });
    } else {
      channel->SetMessageHandler(nullptr);
    }
  }
  {
    auto channel = std::make_unique<BasicMessageChannel<>>(
        binary_messenger,
        "dev.flutter.pigeon.HostIntegrationCoreApi."
        "callFlutterSendMultipleNullableTypes",
        &GetCodec());
    if (api != nullptr) {
      channel->SetMessageHandler(
          [api](const EncodableValue& message,
                const flutter::MessageReply<EncodableValue>& reply) {
            try {
              const auto& args = std::get<EncodableList>(message);
              const auto& encodable_a_nullable_bool_arg = args.at(0);
              const auto* a_nullable_bool_arg =
                  std::get_if<bool>(&encodable_a_nullable_bool_arg);
              const auto& encodable_a_nullable_int_arg = args.at(1);
              const int64_t a_nullable_int_arg_value =
                  encodable_a_nullable_int_arg.IsNull()
                      ? 0
                      : encodable_a_nullable_int_arg.LongValue();
              const auto* a_nullable_int_arg =
                  encodable_a_nullable_int_arg.IsNull()
                      ? nullptr
                      : &a_nullable_int_arg_value;
              const auto& encodable_a_nullable_string_arg = args.at(2);
              const auto* a_nullable_string_arg =
                  std::get_if<std::string>(&encodable_a_nullable_string_arg);
              api->CallFlutterSendMultipleNullableTypes(
                  a_nullable_bool_arg, a_nullable_int_arg,
                  a_nullable_string_arg,
                  [reply](ErrorOr<AllNullableTypes>&& output) {
                    if (output.has_error()) {
                      reply(WrapError(output.error()));
                      return;
                    }
                    EncodableList wrapped;
                    wrapped.push_back(
                        CustomEncodableValue(std::move(output).TakeValue()));
                    reply(EncodableValue(std::move(wrapped)));
                  });
            } catch (const std::exception& exception) {
              reply(WrapError(exception.what()));
            }
          });
    } else {
      channel->SetMessageHandler(nullptr);
    }
  }
  {
    auto channel = std::make_unique<BasicMessageChannel<>>(
        binary_messenger,
        "dev.flutter.pigeon.HostIntegrationCoreApi.callFlutterEchoBool",
        &GetCodec());
    if (api != nullptr) {
      channel->SetMessageHandler(
          [api](const EncodableValue& message,
                const flutter::MessageReply<EncodableValue>& reply) {
            try {
              const auto& args = std::get<EncodableList>(message);
              const auto& encodable_a_bool_arg = args.at(0);
              if (encodable_a_bool_arg.IsNull()) {
                reply(WrapError("a_bool_arg unexpectedly null."));
                return;
              }
              const auto& a_bool_arg = std::get<bool>(encodable_a_bool_arg);
              api->CallFlutterEchoBool(
                  a_bool_arg, [reply](ErrorOr<bool>&& output) {
                    if (output.has_error()) {
                      reply(WrapError(output.error()));
                      return;
                    }
                    EncodableList wrapped;
                    wrapped.push_back(
                        EncodableValue(std::move(output).TakeValue()));
                    reply(EncodableValue(std::move(wrapped)));
                  });
            } catch (const std::exception& exception) {
              reply(WrapError(exception.what()));
            }
          });
    } else {
      channel->SetMessageHandler(nullptr);
    }
  }
  {
    auto channel = std::make_unique<BasicMessageChannel<>>(
        binary_messenger,
        "dev.flutter.pigeon.HostIntegrationCoreApi.callFlutterEchoInt",
        &GetCodec());
    if (api != nullptr) {
      channel->SetMessageHandler(
          [api](const EncodableValue& message,
                const flutter::MessageReply<EncodableValue>& reply) {
            try {
              const auto& args = std::get<EncodableList>(message);
              const auto& encodable_an_int_arg = args.at(0);
              if (encodable_an_int_arg.IsNull()) {
                reply(WrapError("an_int_arg unexpectedly null."));
                return;
              }
              const int64_t an_int_arg = encodable_an_int_arg.LongValue();
              api->CallFlutterEchoInt(
                  an_int_arg, [reply](ErrorOr<int64_t>&& output) {
                    if (output.has_error()) {
                      reply(WrapError(output.error()));
                      return;
                    }
                    EncodableList wrapped;
                    wrapped.push_back(
                        EncodableValue(std::move(output).TakeValue()));
                    reply(EncodableValue(std::move(wrapped)));
                  });
            } catch (const std::exception& exception) {
              reply(WrapError(exception.what()));
            }
          });
    } else {
      channel->SetMessageHandler(nullptr);
    }
  }
  {
    auto channel = std::make_unique<BasicMessageChannel<>>(
        binary_messenger,
        "dev.flutter.pigeon.HostIntegrationCoreApi.callFlutterEchoDouble",
        &GetCodec());
    if (api != nullptr) {
      channel->SetMessageHandler(
          [api](const EncodableValue& message,
                const flutter::MessageReply<EncodableValue>& reply) {
            try {
              const auto& args = std::get<EncodableList>(message);
              const auto& encodable_a_double_arg = args.at(0);
              if (encodable_a_double_arg.IsNull()) {
                reply(WrapError("a_double_arg unexpectedly null."));
                return;
              }
              const auto& a_double_arg =
                  std::get<double>(encodable_a_double_arg);
              api->CallFlutterEchoDouble(
                  a_double_arg, [reply](ErrorOr<double>&& output) {
                    if (output.has_error()) {
                      reply(WrapError(output.error()));
                      return;
                    }
                    EncodableList wrapped;
                    wrapped.push_back(
                        EncodableValue(std::move(output).TakeValue()));
                    reply(EncodableValue(std::move(wrapped)));
                  });
            } catch (const std::exception& exception) {
              reply(WrapError(exception.what()));
            }
          });
    } else {
      channel->SetMessageHandler(nullptr);
    }
  }
  {
    auto channel = std::make_unique<BasicMessageChannel<>>(
        binary_messenger,
        "dev.flutter.pigeon.HostIntegrationCoreApi.callFlutterEchoString",
        &GetCodec());
    if (api != nullptr) {
      channel->SetMessageHandler(
          [api](const EncodableValue& message,
                const flutter::MessageReply<EncodableValue>& reply) {
            try {
              const auto& args = std::get<EncodableList>(message);
              const auto& encodable_a_string_arg = args.at(0);
              if (encodable_a_string_arg.IsNull()) {
                reply(WrapError("a_string_arg unexpectedly null."));
                return;
              }
              const auto& a_string_arg =
                  std::get<std::string>(encodable_a_string_arg);
              api->CallFlutterEchoString(
                  a_string_arg, [reply](ErrorOr<std::string>&& output) {
                    if (output.has_error()) {
                      reply(WrapError(output.error()));
                      return;
                    }
                    EncodableList wrapped;
                    wrapped.push_back(
                        EncodableValue(std::move(output).TakeValue()));
                    reply(EncodableValue(std::move(wrapped)));
                  });
            } catch (const std::exception& exception) {
              reply(WrapError(exception.what()));
            }
          });
    } else {
      channel->SetMessageHandler(nullptr);
    }
  }
  {
    auto channel = std::make_unique<BasicMessageChannel<>>(
        binary_messenger,
        "dev.flutter.pigeon.HostIntegrationCoreApi.callFlutterEchoUint8List",
        &GetCodec());
    if (api != nullptr) {
      channel->SetMessageHandler(
          [api](const EncodableValue& message,
                const flutter::MessageReply<EncodableValue>& reply) {
            try {
              const auto& args = std::get<EncodableList>(message);
              const auto& encodable_a_list_arg = args.at(0);
              if (encodable_a_list_arg.IsNull()) {
                reply(WrapError("a_list_arg unexpectedly null."));
                return;
              }
              const auto& a_list_arg =
                  std::get<std::vector<uint8_t>>(encodable_a_list_arg);
              api->CallFlutterEchoUint8List(
                  a_list_arg, [reply](ErrorOr<std::vector<uint8_t>>&& output) {
                    if (output.has_error()) {
                      reply(WrapError(output.error()));
                      return;
                    }
                    EncodableList wrapped;
                    wrapped.push_back(
                        EncodableValue(std::move(output).TakeValue()));
                    reply(EncodableValue(std::move(wrapped)));
                  });
            } catch (const std::exception& exception) {
              reply(WrapError(exception.what()));
            }
          });
    } else {
      channel->SetMessageHandler(nullptr);
    }
  }
  {
    auto channel = std::make_unique<BasicMessageChannel<>>(
        binary_messenger,
        "dev.flutter.pigeon.HostIntegrationCoreApi.callFlutterEchoList",
        &GetCodec());
    if (api != nullptr) {
      channel->SetMessageHandler(
          [api](const EncodableValue& message,
                const flutter::MessageReply<EncodableValue>& reply) {
            try {
              const auto& args = std::get<EncodableList>(message);
              const auto& encodable_a_list_arg = args.at(0);
              if (encodable_a_list_arg.IsNull()) {
                reply(WrapError("a_list_arg unexpectedly null."));
                return;
              }
              const auto& a_list_arg =
                  std::get<EncodableList>(encodable_a_list_arg);
              api->CallFlutterEchoList(
                  a_list_arg, [reply](ErrorOr<EncodableList>&& output) {
                    if (output.has_error()) {
                      reply(WrapError(output.error()));
                      return;
                    }
                    EncodableList wrapped;
                    wrapped.push_back(
                        EncodableValue(std::move(output).TakeValue()));
                    reply(EncodableValue(std::move(wrapped)));
                  });
            } catch (const std::exception& exception) {
              reply(WrapError(exception.what()));
            }
          });
    } else {
      channel->SetMessageHandler(nullptr);
    }
  }
  {
    auto channel = std::make_unique<BasicMessageChannel<>>(
        binary_messenger,
        "dev.flutter.pigeon.HostIntegrationCoreApi.callFlutterEchoMap",
        &GetCodec());
    if (api != nullptr) {
      channel->SetMessageHandler(
          [api](const EncodableValue& message,
                const flutter::MessageReply<EncodableValue>& reply) {
            try {
              const auto& args = std::get<EncodableList>(message);
              const auto& encodable_a_map_arg = args.at(0);
              if (encodable_a_map_arg.IsNull()) {
                reply(WrapError("a_map_arg unexpectedly null."));
                return;
              }
              const auto& a_map_arg =
                  std::get<EncodableMap>(encodable_a_map_arg);
              api->CallFlutterEchoMap(
                  a_map_arg, [reply](ErrorOr<EncodableMap>&& output) {
                    if (output.has_error()) {
                      reply(WrapError(output.error()));
                      return;
                    }
                    EncodableList wrapped;
                    wrapped.push_back(
                        EncodableValue(std::move(output).TakeValue()));
                    reply(EncodableValue(std::move(wrapped)));
                  });
            } catch (const std::exception& exception) {
              reply(WrapError(exception.what()));
            }
          });
    } else {
      channel->SetMessageHandler(nullptr);
    }
  }
  {
    auto channel = std::make_unique<BasicMessageChannel<>>(
        binary_messenger,
        "dev.flutter.pigeon.HostIntegrationCoreApi.callFlutterEchoNullableBool",
        &GetCodec());
    if (api != nullptr) {
      channel->SetMessageHandler(
          [api](const EncodableValue& message,
                const flutter::MessageReply<EncodableValue>& reply) {
            try {
              const auto& args = std::get<EncodableList>(message);
              const auto& encodable_a_bool_arg = args.at(0);
              const auto* a_bool_arg = std::get_if<bool>(&encodable_a_bool_arg);
              api->CallFlutterEchoNullableBool(
                  a_bool_arg, [reply](ErrorOr<std::optional<bool>>&& output) {
                    if (output.has_error()) {
                      reply(WrapError(output.error()));
                      return;
                    }
                    EncodableList wrapped;
                    auto output_optional = std::move(output).TakeValue();
                    if (output_optional) {
                      wrapped.push_back(
                          EncodableValue(std::move(output_optional).value()));
                    } else {
                      wrapped.push_back(EncodableValue());
                    }
                    reply(EncodableValue(std::move(wrapped)));
                  });
            } catch (const std::exception& exception) {
              reply(WrapError(exception.what()));
            }
          });
    } else {
      channel->SetMessageHandler(nullptr);
    }
  }
  {
    auto channel = std::make_unique<BasicMessageChannel<>>(
        binary_messenger,
        "dev.flutter.pigeon.HostIntegrationCoreApi.callFlutterEchoNullableInt",
        &GetCodec());
    if (api != nullptr) {
      channel->SetMessageHandler(
          [api](const EncodableValue& message,
                const flutter::MessageReply<EncodableValue>& reply) {
            try {
              const auto& args = std::get<EncodableList>(message);
              const auto& encodable_an_int_arg = args.at(0);
              const int64_t an_int_arg_value =
                  encodable_an_int_arg.IsNull()
                      ? 0
                      : encodable_an_int_arg.LongValue();
              const auto* an_int_arg =
                  encodable_an_int_arg.IsNull() ? nullptr : &an_int_arg_value;
              api->CallFlutterEchoNullableInt(
                  an_int_arg,
                  [reply](ErrorOr<std::optional<int64_t>>&& output) {
                    if (output.has_error()) {
                      reply(WrapError(output.error()));
                      return;
                    }
                    EncodableList wrapped;
                    auto output_optional = std::move(output).TakeValue();
                    if (output_optional) {
                      wrapped.push_back(
                          EncodableValue(std::move(output_optional).value()));
                    } else {
                      wrapped.push_back(EncodableValue());
                    }
                    reply(EncodableValue(std::move(wrapped)));
                  });
            } catch (const std::exception& exception) {
              reply(WrapError(exception.what()));
            }
          });
    } else {
      channel->SetMessageHandler(nullptr);
    }
  }
  {
    auto channel = std::make_unique<BasicMessageChannel<>>(
        binary_messenger,
        "dev.flutter.pigeon.HostIntegrationCoreApi."
        "callFlutterEchoNullableDouble",
        &GetCodec());
    if (api != nullptr) {
      channel->SetMessageHandler(
          [api](const EncodableValue& message,
                const flutter::MessageReply<EncodableValue>& reply) {
            try {
              const auto& args = std::get<EncodableList>(message);
              const auto& encodable_a_double_arg = args.at(0);
              const auto* a_double_arg =
                  std::get_if<double>(&encodable_a_double_arg);
              api->CallFlutterEchoNullableDouble(
                  a_double_arg,
                  [reply](ErrorOr<std::optional<double>>&& output) {
                    if (output.has_error()) {
                      reply(WrapError(output.error()));
                      return;
                    }
                    EncodableList wrapped;
                    auto output_optional = std::move(output).TakeValue();
                    if (output_optional) {
                      wrapped.push_back(
                          EncodableValue(std::move(output_optional).value()));
                    } else {
                      wrapped.push_back(EncodableValue());
                    }
                    reply(EncodableValue(std::move(wrapped)));
                  });
            } catch (const std::exception& exception) {
              reply(WrapError(exception.what()));
            }
          });
    } else {
      channel->SetMessageHandler(nullptr);
    }
  }
  {
    auto channel = std::make_unique<BasicMessageChannel<>>(
        binary_messenger,
        "dev.flutter.pigeon.HostIntegrationCoreApi."
        "callFlutterEchoNullableString",
        &GetCodec());
    if (api != nullptr) {
      channel->SetMessageHandler(
          [api](const EncodableValue& message,
                const flutter::MessageReply<EncodableValue>& reply) {
            try {
              const auto& args = std::get<EncodableList>(message);
              const auto& encodable_a_string_arg = args.at(0);
              const auto* a_string_arg =
                  std::get_if<std::string>(&encodable_a_string_arg);
              api->CallFlutterEchoNullableString(
                  a_string_arg,
                  [reply](ErrorOr<std::optional<std::string>>&& output) {
                    if (output.has_error()) {
                      reply(WrapError(output.error()));
                      return;
                    }
                    EncodableList wrapped;
                    auto output_optional = std::move(output).TakeValue();
                    if (output_optional) {
                      wrapped.push_back(
                          EncodableValue(std::move(output_optional).value()));
                    } else {
                      wrapped.push_back(EncodableValue());
                    }
                    reply(EncodableValue(std::move(wrapped)));
                  });
            } catch (const std::exception& exception) {
              reply(WrapError(exception.what()));
            }
          });
    } else {
      channel->SetMessageHandler(nullptr);
    }
  }
  {
    auto channel = std::make_unique<BasicMessageChannel<>>(
        binary_messenger,
        "dev.flutter.pigeon.HostIntegrationCoreApi."
        "callFlutterEchoNullableUint8List",
        &GetCodec());
    if (api != nullptr) {
      channel->SetMessageHandler(
          [api](const EncodableValue& message,
                const flutter::MessageReply<EncodableValue>& reply) {
            try {
              const auto& args = std::get<EncodableList>(message);
              const auto& encodable_a_list_arg = args.at(0);
              const auto* a_list_arg =
                  std::get_if<std::vector<uint8_t>>(&encodable_a_list_arg);
              api->CallFlutterEchoNullableUint8List(
                  a_list_arg,
                  [reply](
                      ErrorOr<std::optional<std::vector<uint8_t>>>&& output) {
                    if (output.has_error()) {
                      reply(WrapError(output.error()));
                      return;
                    }
                    EncodableList wrapped;
                    auto output_optional = std::move(output).TakeValue();
                    if (output_optional) {
                      wrapped.push_back(
                          EncodableValue(std::move(output_optional).value()));
                    } else {
                      wrapped.push_back(EncodableValue());
                    }
                    reply(EncodableValue(std::move(wrapped)));
                  });
            } catch (const std::exception& exception) {
              reply(WrapError(exception.what()));
            }
          });
    } else {
      channel->SetMessageHandler(nullptr);
    }
  }
  {
    auto channel = std::make_unique<BasicMessageChannel<>>(
        binary_messenger,
        "dev.flutter.pigeon.HostIntegrationCoreApi.callFlutterEchoNullableList",
        &GetCodec());
    if (api != nullptr) {
      channel->SetMessageHandler(
          [api](const EncodableValue& message,
                const flutter::MessageReply<EncodableValue>& reply) {
            try {
              const auto& args = std::get<EncodableList>(message);
              const auto& encodable_a_list_arg = args.at(0);
              const auto* a_list_arg =
                  std::get_if<EncodableList>(&encodable_a_list_arg);
              api->CallFlutterEchoNullableList(
                  a_list_arg,
                  [reply](ErrorOr<std::optional<EncodableList>>&& output) {
                    if (output.has_error()) {
                      reply(WrapError(output.error()));
                      return;
                    }
                    EncodableList wrapped;
                    auto output_optional = std::move(output).TakeValue();
                    if (output_optional) {
                      wrapped.push_back(
                          EncodableValue(std::move(output_optional).value()));
                    } else {
                      wrapped.push_back(EncodableValue());
                    }
                    reply(EncodableValue(std::move(wrapped)));
                  });
            } catch (const std::exception& exception) {
              reply(WrapError(exception.what()));
            }
          });
    } else {
      channel->SetMessageHandler(nullptr);
    }
  }
  {
    auto channel = std::make_unique<BasicMessageChannel<>>(
        binary_messenger,
        "dev.flutter.pigeon.HostIntegrationCoreApi.callFlutterEchoNullableMap",
        &GetCodec());
    if (api != nullptr) {
      channel->SetMessageHandler(
          [api](const EncodableValue& message,
                const flutter::MessageReply<EncodableValue>& reply) {
            try {
              const auto& args = std::get<EncodableList>(message);
              const auto& encodable_a_map_arg = args.at(0);
              const auto* a_map_arg =
                  std::get_if<EncodableMap>(&encodable_a_map_arg);
              api->CallFlutterEchoNullableMap(
                  a_map_arg,
                  [reply](ErrorOr<std::optional<EncodableMap>>&& output) {
                    if (output.has_error()) {
                      reply(WrapError(output.error()));
                      return;
                    }
                    EncodableList wrapped;
                    auto output_optional = std::move(output).TakeValue();
                    if (output_optional) {
                      wrapped.push_back(
                          EncodableValue(std::move(output_optional).value()));
                    } else {
                      wrapped.push_back(EncodableValue());
                    }
                    reply(EncodableValue(std::move(wrapped)));
                  });
            } catch (const std::exception& exception) {
              reply(WrapError(exception.what()));
            }
          });
    } else {
      channel->SetMessageHandler(nullptr);
    }
  }
}

EncodableValue HostIntegrationCoreApi::WrapError(
    std::string_view error_message) {
  return EncodableValue(
      EncodableList{EncodableValue(std::string(error_message)),
                    EncodableValue("Error"), EncodableValue()});
}
EncodableValue HostIntegrationCoreApi::WrapError(const FlutterError& error) {
  return EncodableValue(EncodableList{EncodableValue(error.message()),
                                      EncodableValue(error.code()),
                                      error.details()});
}

FlutterIntegrationCoreApiCodecSerializer::
    FlutterIntegrationCoreApiCodecSerializer() {}
EncodableValue FlutterIntegrationCoreApiCodecSerializer::ReadValueOfType(
    uint8_t type, flutter::ByteStreamReader* stream) const {
  switch (type) {
    case 128:
      return CustomEncodableValue(
          AllNullableTypes(std::get<EncodableList>(ReadValue(stream))));
    case 129:
      return CustomEncodableValue(
          AllNullableTypesWrapper(std::get<EncodableList>(ReadValue(stream))));
    case 130:
      return CustomEncodableValue(
          AllTypes(std::get<EncodableList>(ReadValue(stream))));
    default:
      return flutter::StandardCodecSerializer::ReadValueOfType(type, stream);
  }
}

void FlutterIntegrationCoreApiCodecSerializer::WriteValue(
    const EncodableValue& value, flutter::ByteStreamWriter* stream) const {
  if (const CustomEncodableValue* custom_value =
          std::get_if<CustomEncodableValue>(&value)) {
    if (custom_value->type() == typeid(AllNullableTypes)) {
      stream->WriteByte(128);
      WriteValue(
          EncodableValue(
              std::any_cast<AllNullableTypes>(*custom_value).ToEncodableList()),
          stream);
      return;
    }
    if (custom_value->type() == typeid(AllNullableTypesWrapper)) {
      stream->WriteByte(129);
      WriteValue(
          EncodableValue(std::any_cast<AllNullableTypesWrapper>(*custom_value)
                             .ToEncodableList()),
          stream);
      return;
    }
    if (custom_value->type() == typeid(AllTypes)) {
      stream->WriteByte(130);
      WriteValue(EncodableValue(
                     std::any_cast<AllTypes>(*custom_value).ToEncodableList()),
                 stream);
      return;
    }
  }
  flutter::StandardCodecSerializer::WriteValue(value, stream);
}

// Generated class from Pigeon that represents Flutter messages that can be
// called from C++.
FlutterIntegrationCoreApi::FlutterIntegrationCoreApi(
    flutter::BinaryMessenger* binary_messenger) {
  this->binary_messenger_ = binary_messenger;
}

const flutter::StandardMessageCodec& FlutterIntegrationCoreApi::GetCodec() {
  return flutter::StandardMessageCodec::GetInstance(
      &FlutterIntegrationCoreApiCodecSerializer::GetInstance());
}

void FlutterIntegrationCoreApi::Noop(
    std::function<void(void)>&& on_success,
    std::function<void(const FlutterError&)>&& on_error) {
  auto channel = std::make_unique<BasicMessageChannel<>>(
      binary_messenger_, "dev.flutter.pigeon.FlutterIntegrationCoreApi.noop",
      &GetCodec());
  EncodableValue encoded_api_arguments = EncodableValue();
  channel->Send(
      encoded_api_arguments,
      [on_success = std::move(on_success), on_error = std::move(on_error)](
          const uint8_t* reply, size_t reply_size) { on_success(); });
}
void FlutterIntegrationCoreApi::EchoAllTypes(
    const AllTypes& everything_arg,
    std::function<void(const AllTypes&)>&& on_success,
    std::function<void(const FlutterError&)>&& on_error) {
  auto channel = std::make_unique<BasicMessageChannel<>>(
      binary_messenger_,
      "dev.flutter.pigeon.FlutterIntegrationCoreApi.echoAllTypes", &GetCodec());
  EncodableValue encoded_api_arguments = EncodableValue(EncodableList{
      EncodableValue(everything_arg.ToEncodableList()),
  });
  channel->Send(
      encoded_api_arguments,
      [on_success = std::move(on_success), on_error = std::move(on_error)](
          const uint8_t* reply, size_t reply_size) {
        std::unique_ptr<EncodableValue> response =
            GetCodec().DecodeMessage(reply, reply_size);
        const auto& encodable_return_value = *response;
        const auto& return_value = std::any_cast<const AllTypes&>(
            std::get<CustomEncodableValue>(encodable_return_value));
        on_success(return_value);
      });
}
void FlutterIntegrationCoreApi::EchoAllNullableTypes(
    const AllNullableTypes& everything_arg,
    std::function<void(const AllNullableTypes&)>&& on_success,
    std::function<void(const FlutterError&)>&& on_error) {
  auto channel = std::make_unique<BasicMessageChannel<>>(
      binary_messenger_,
      "dev.flutter.pigeon.FlutterIntegrationCoreApi.echoAllNullableTypes",
      &GetCodec());
  EncodableValue encoded_api_arguments = EncodableValue(EncodableList{
      EncodableValue(everything_arg.ToEncodableList()),
  });
  channel->Send(
      encoded_api_arguments,
      [on_success = std::move(on_success), on_error = std::move(on_error)](
          const uint8_t* reply, size_t reply_size) {
        std::unique_ptr<EncodableValue> response =
            GetCodec().DecodeMessage(reply, reply_size);
        const auto& encodable_return_value = *response;
        const auto& return_value = std::any_cast<const AllNullableTypes&>(
            std::get<CustomEncodableValue>(encodable_return_value));
        on_success(return_value);
      });
}
void FlutterIntegrationCoreApi::SendMultipleNullableTypes(
    const bool* a_nullable_bool_arg, const int64_t* a_nullable_int_arg,
    const std::string* a_nullable_string_arg,
    std::function<void(const AllNullableTypes&)>&& on_success,
    std::function<void(const FlutterError&)>&& on_error) {
  auto channel = std::make_unique<BasicMessageChannel<>>(
      binary_messenger_,
      "dev.flutter.pigeon.FlutterIntegrationCoreApi.sendMultipleNullableTypes",
      &GetCodec());
  EncodableValue encoded_api_arguments = EncodableValue(EncodableList{
      a_nullable_bool_arg ? EncodableValue(*a_nullable_bool_arg)
                          : EncodableValue(),
      a_nullable_int_arg ? EncodableValue(*a_nullable_int_arg)
                         : EncodableValue(),
      a_nullable_string_arg ? EncodableValue(*a_nullable_string_arg)
                            : EncodableValue(),
  });
  channel->Send(
      encoded_api_arguments,
      [on_success = std::move(on_success), on_error = std::move(on_error)](
          const uint8_t* reply, size_t reply_size) {
        std::unique_ptr<EncodableValue> response =
            GetCodec().DecodeMessage(reply, reply_size);
        const auto& encodable_return_value = *response;
        const auto& return_value = std::any_cast<const AllNullableTypes&>(
            std::get<CustomEncodableValue>(encodable_return_value));
        on_success(return_value);
      });
}
void FlutterIntegrationCoreApi::EchoBool(
    bool a_bool_arg, std::function<void(bool)>&& on_success,
    std::function<void(const FlutterError&)>&& on_error) {
  auto channel = std::make_unique<BasicMessageChannel<>>(
      binary_messenger_,
      "dev.flutter.pigeon.FlutterIntegrationCoreApi.echoBool", &GetCodec());
  EncodableValue encoded_api_arguments = EncodableValue(EncodableList{
      EncodableValue(a_bool_arg),
  });
  channel->Send(
      encoded_api_arguments,
      [on_success = std::move(on_success), on_error = std::move(on_error)](
          const uint8_t* reply, size_t reply_size) {
        std::unique_ptr<EncodableValue> response =
            GetCodec().DecodeMessage(reply, reply_size);
        const auto& encodable_return_value = *response;
        const auto& return_value = std::get<bool>(encodable_return_value);
        on_success(return_value);
      });
}
void FlutterIntegrationCoreApi::EchoInt(
    int64_t an_int_arg, std::function<void(int64_t)>&& on_success,
    std::function<void(const FlutterError&)>&& on_error) {
  auto channel = std::make_unique<BasicMessageChannel<>>(
      binary_messenger_, "dev.flutter.pigeon.FlutterIntegrationCoreApi.echoInt",
      &GetCodec());
  EncodableValue encoded_api_arguments = EncodableValue(EncodableList{
      EncodableValue(an_int_arg),
  });
  channel->Send(
      encoded_api_arguments,
      [on_success = std::move(on_success), on_error = std::move(on_error)](
          const uint8_t* reply, size_t reply_size) {
        std::unique_ptr<EncodableValue> response =
            GetCodec().DecodeMessage(reply, reply_size);
        const auto& encodable_return_value = *response;
        const int64_t return_value = encodable_return_value.LongValue();
        on_success(return_value);
      });
}
void FlutterIntegrationCoreApi::EchoDouble(
    double a_double_arg, std::function<void(double)>&& on_success,
    std::function<void(const FlutterError&)>&& on_error) {
  auto channel = std::make_unique<BasicMessageChannel<>>(
      binary_messenger_,
      "dev.flutter.pigeon.FlutterIntegrationCoreApi.echoDouble", &GetCodec());
  EncodableValue encoded_api_arguments = EncodableValue(EncodableList{
      EncodableValue(a_double_arg),
  });
  channel->Send(
      encoded_api_arguments,
      [on_success = std::move(on_success), on_error = std::move(on_error)](
          const uint8_t* reply, size_t reply_size) {
        std::unique_ptr<EncodableValue> response =
            GetCodec().DecodeMessage(reply, reply_size);
        const auto& encodable_return_value = *response;
        const auto& return_value = std::get<double>(encodable_return_value);
        on_success(return_value);
      });
}
void FlutterIntegrationCoreApi::EchoString(
    const std::string& a_string_arg,
    std::function<void(const std::string&)>&& on_success,
    std::function<void(const FlutterError&)>&& on_error) {
  auto channel = std::make_unique<BasicMessageChannel<>>(
      binary_messenger_,
      "dev.flutter.pigeon.FlutterIntegrationCoreApi.echoString", &GetCodec());
  EncodableValue encoded_api_arguments = EncodableValue(EncodableList{
      EncodableValue(a_string_arg),
  });
  channel->Send(
      encoded_api_arguments,
      [on_success = std::move(on_success), on_error = std::move(on_error)](
          const uint8_t* reply, size_t reply_size) {
        std::unique_ptr<EncodableValue> response =
            GetCodec().DecodeMessage(reply, reply_size);
        const auto& encodable_return_value = *response;
        const auto& return_value =
            std::get<std::string>(encodable_return_value);
        on_success(return_value);
      });
}
void FlutterIntegrationCoreApi::EchoUint8List(
    const std::vector<uint8_t>& a_list_arg,
    std::function<void(const std::vector<uint8_t>&)>&& on_success,
    std::function<void(const FlutterError&)>&& on_error) {
  auto channel = std::make_unique<BasicMessageChannel<>>(
      binary_messenger_,
      "dev.flutter.pigeon.FlutterIntegrationCoreApi.echoUint8List",
      &GetCodec());
  EncodableValue encoded_api_arguments = EncodableValue(EncodableList{
      EncodableValue(a_list_arg),
  });
  channel->Send(
      encoded_api_arguments,
      [on_success = std::move(on_success), on_error = std::move(on_error)](
          const uint8_t* reply, size_t reply_size) {
        std::unique_ptr<EncodableValue> response =
            GetCodec().DecodeMessage(reply, reply_size);
        const auto& encodable_return_value = *response;
        const auto& return_value =
            std::get<std::vector<uint8_t>>(encodable_return_value);
        on_success(return_value);
      });
}
void FlutterIntegrationCoreApi::EchoList(
    const EncodableList& a_list_arg,
    std::function<void(const EncodableList&)>&& on_success,
    std::function<void(const FlutterError&)>&& on_error) {
  auto channel = std::make_unique<BasicMessageChannel<>>(
      binary_messenger_,
      "dev.flutter.pigeon.FlutterIntegrationCoreApi.echoList", &GetCodec());
  EncodableValue encoded_api_arguments = EncodableValue(EncodableList{
      EncodableValue(a_list_arg),
  });
  channel->Send(
      encoded_api_arguments,
      [on_success = std::move(on_success), on_error = std::move(on_error)](
          const uint8_t* reply, size_t reply_size) {
        std::unique_ptr<EncodableValue> response =
            GetCodec().DecodeMessage(reply, reply_size);
        const auto& encodable_return_value = *response;
        const auto& return_value =
            std::get<EncodableList>(encodable_return_value);
        on_success(return_value);
      });
}
void FlutterIntegrationCoreApi::EchoMap(
    const EncodableMap& a_map_arg,
    std::function<void(const EncodableMap&)>&& on_success,
    std::function<void(const FlutterError&)>&& on_error) {
  auto channel = std::make_unique<BasicMessageChannel<>>(
      binary_messenger_, "dev.flutter.pigeon.FlutterIntegrationCoreApi.echoMap",
      &GetCodec());
  EncodableValue encoded_api_arguments = EncodableValue(EncodableList{
      EncodableValue(a_map_arg),
  });
  channel->Send(
      encoded_api_arguments,
      [on_success = std::move(on_success), on_error = std::move(on_error)](
          const uint8_t* reply, size_t reply_size) {
        std::unique_ptr<EncodableValue> response =
            GetCodec().DecodeMessage(reply, reply_size);
        const auto& encodable_return_value = *response;
        const auto& return_value =
            std::get<EncodableMap>(encodable_return_value);
        on_success(return_value);
      });
}
void FlutterIntegrationCoreApi::EchoNullableBool(
    const bool* a_bool_arg, std::function<void(const bool*)>&& on_success,
    std::function<void(const FlutterError&)>&& on_error) {
  auto channel = std::make_unique<BasicMessageChannel<>>(
      binary_messenger_,
      "dev.flutter.pigeon.FlutterIntegrationCoreApi.echoNullableBool",
      &GetCodec());
  EncodableValue encoded_api_arguments = EncodableValue(EncodableList{
      a_bool_arg ? EncodableValue(*a_bool_arg) : EncodableValue(),
  });
  channel->Send(
      encoded_api_arguments,
      [on_success = std::move(on_success), on_error = std::move(on_error)](
          const uint8_t* reply, size_t reply_size) {
        std::unique_ptr<EncodableValue> response =
            GetCodec().DecodeMessage(reply, reply_size);
        const auto& encodable_return_value = *response;
        const auto* return_value = std::get_if<bool>(&encodable_return_value);
        on_success(return_value);
      });
}
void FlutterIntegrationCoreApi::EchoNullableInt(
    const int64_t* an_int_arg, std::function<void(const int64_t*)>&& on_success,
    std::function<void(const FlutterError&)>&& on_error) {
  auto channel = std::make_unique<BasicMessageChannel<>>(
      binary_messenger_,
      "dev.flutter.pigeon.FlutterIntegrationCoreApi.echoNullableInt",
      &GetCodec());
  EncodableValue encoded_api_arguments = EncodableValue(EncodableList{
      an_int_arg ? EncodableValue(*an_int_arg) : EncodableValue(),
  });
  channel->Send(
      encoded_api_arguments,
      [on_success = std::move(on_success), on_error = std::move(on_error)](
          const uint8_t* reply, size_t reply_size) {
        std::unique_ptr<EncodableValue> response =
            GetCodec().DecodeMessage(reply, reply_size);
        const auto& encodable_return_value = *response;
        const int64_t return_value_value =
            encodable_return_value.IsNull()
                ? 0
                : encodable_return_value.LongValue();
        const auto* return_value =
            encodable_return_value.IsNull() ? nullptr : &return_value_value;
        on_success(return_value);
      });
}
void FlutterIntegrationCoreApi::EchoNullableDouble(
    const double* a_double_arg, std::function<void(const double*)>&& on_success,
    std::function<void(const FlutterError&)>&& on_error) {
  auto channel = std::make_unique<BasicMessageChannel<>>(
      binary_messenger_,
      "dev.flutter.pigeon.FlutterIntegrationCoreApi.echoNullableDouble",
      &GetCodec());
  EncodableValue encoded_api_arguments = EncodableValue(EncodableList{
      a_double_arg ? EncodableValue(*a_double_arg) : EncodableValue(),
  });
  channel->Send(
      encoded_api_arguments,
      [on_success = std::move(on_success), on_error = std::move(on_error)](
          const uint8_t* reply, size_t reply_size) {
        std::unique_ptr<EncodableValue> response =
            GetCodec().DecodeMessage(reply, reply_size);
        const auto& encodable_return_value = *response;
        const auto* return_value = std::get_if<double>(&encodable_return_value);
        on_success(return_value);
      });
}
void FlutterIntegrationCoreApi::EchoNullableString(
    const std::string* a_string_arg,
    std::function<void(const std::string*)>&& on_success,
    std::function<void(const FlutterError&)>&& on_error) {
  auto channel = std::make_unique<BasicMessageChannel<>>(
      binary_messenger_,
      "dev.flutter.pigeon.FlutterIntegrationCoreApi.echoNullableString",
      &GetCodec());
  EncodableValue encoded_api_arguments = EncodableValue(EncodableList{
      a_string_arg ? EncodableValue(*a_string_arg) : EncodableValue(),
  });
  channel->Send(
      encoded_api_arguments,
      [on_success = std::move(on_success), on_error = std::move(on_error)](
          const uint8_t* reply, size_t reply_size) {
        std::unique_ptr<EncodableValue> response =
            GetCodec().DecodeMessage(reply, reply_size);
        const auto& encodable_return_value = *response;
        const auto* return_value =
            std::get_if<std::string>(&encodable_return_value);
        on_success(return_value);
      });
}
void FlutterIntegrationCoreApi::EchoNullableUint8List(
    const std::vector<uint8_t>* a_list_arg,
    std::function<void(const std::vector<uint8_t>*)>&& on_success,
    std::function<void(const FlutterError&)>&& on_error) {
  auto channel = std::make_unique<BasicMessageChannel<>>(
      binary_messenger_,
      "dev.flutter.pigeon.FlutterIntegrationCoreApi.echoNullableUint8List",
      &GetCodec());
  EncodableValue encoded_api_arguments = EncodableValue(EncodableList{
      a_list_arg ? EncodableValue(*a_list_arg) : EncodableValue(),
  });
  channel->Send(
      encoded_api_arguments,
      [on_success = std::move(on_success), on_error = std::move(on_error)](
          const uint8_t* reply, size_t reply_size) {
        std::unique_ptr<EncodableValue> response =
            GetCodec().DecodeMessage(reply, reply_size);
        const auto& encodable_return_value = *response;
        const auto* return_value =
            std::get_if<std::vector<uint8_t>>(&encodable_return_value);
        on_success(return_value);
      });
}
void FlutterIntegrationCoreApi::EchoNullableList(
    const EncodableList* a_list_arg,
    std::function<void(const EncodableList*)>&& on_success,
    std::function<void(const FlutterError&)>&& on_error) {
  auto channel = std::make_unique<BasicMessageChannel<>>(
      binary_messenger_,
      "dev.flutter.pigeon.FlutterIntegrationCoreApi.echoNullableList",
      &GetCodec());
  EncodableValue encoded_api_arguments = EncodableValue(EncodableList{
      a_list_arg ? EncodableValue(*a_list_arg) : EncodableValue(),
  });
  channel->Send(
      encoded_api_arguments,
      [on_success = std::move(on_success), on_error = std::move(on_error)](
          const uint8_t* reply, size_t reply_size) {
        std::unique_ptr<EncodableValue> response =
            GetCodec().DecodeMessage(reply, reply_size);
        const auto& encodable_return_value = *response;
        const auto* return_value =
            std::get_if<EncodableList>(&encodable_return_value);
        on_success(return_value);
      });
}
void FlutterIntegrationCoreApi::EchoNullableMap(
    const EncodableMap* a_map_arg,
    std::function<void(const EncodableMap*)>&& on_success,
    std::function<void(const FlutterError&)>&& on_error) {
  auto channel = std::make_unique<BasicMessageChannel<>>(
      binary_messenger_,
      "dev.flutter.pigeon.FlutterIntegrationCoreApi.echoNullableMap",
      &GetCodec());
  EncodableValue encoded_api_arguments = EncodableValue(EncodableList{
      a_map_arg ? EncodableValue(*a_map_arg) : EncodableValue(),
  });
  channel->Send(
      encoded_api_arguments,
      [on_success = std::move(on_success), on_error = std::move(on_error)](
          const uint8_t* reply, size_t reply_size) {
        std::unique_ptr<EncodableValue> response =
            GetCodec().DecodeMessage(reply, reply_size);
        const auto& encodable_return_value = *response;
        const auto* return_value =
            std::get_if<EncodableMap>(&encodable_return_value);
        on_success(return_value);
      });
}
/// The codec used by HostTrivialApi.
const flutter::StandardMessageCodec& HostTrivialApi::GetCodec() {
  return flutter::StandardMessageCodec::GetInstance(
      &flutter::StandardCodecSerializer::GetInstance());
}

// Sets up an instance of `HostTrivialApi` to handle messages through the
// `binary_messenger`.
void HostTrivialApi::SetUp(flutter::BinaryMessenger* binary_messenger,
                           HostTrivialApi* api) {
  {
    auto channel = std::make_unique<BasicMessageChannel<>>(
        binary_messenger, "dev.flutter.pigeon.HostTrivialApi.noop",
        &GetCodec());
    if (api != nullptr) {
      channel->SetMessageHandler(
          [api](const EncodableValue& message,
                const flutter::MessageReply<EncodableValue>& reply) {
            try {
              std::optional<FlutterError> output = api->Noop();
              if (output.has_value()) {
                reply(WrapError(output.value()));
                return;
              }
              EncodableList wrapped;
              wrapped.push_back(EncodableValue());
              reply(EncodableValue(std::move(wrapped)));
            } catch (const std::exception& exception) {
              reply(WrapError(exception.what()));
            }
          });
    } else {
      channel->SetMessageHandler(nullptr);
    }
  }
}

EncodableValue HostTrivialApi::WrapError(std::string_view error_message) {
  return EncodableValue(
      EncodableList{EncodableValue(std::string(error_message)),
                    EncodableValue("Error"), EncodableValue()});
}
EncodableValue HostTrivialApi::WrapError(const FlutterError& error) {
  return EncodableValue(EncodableList{EncodableValue(error.message()),
                                      EncodableValue(error.code()),
                                      error.details()});
}

}  // namespace core_tests_pigeontest
