// 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.2), do not edit directly.
// See also: https://pub.dev/packages/pigeon

package com.example.alternate_language_test_plugin;

import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import io.flutter.plugin.common.BasicMessageChannel;
import io.flutter.plugin.common.BinaryMessenger;
import io.flutter.plugin.common.MessageCodec;
import io.flutter.plugin.common.StandardMessageCodec;
import java.io.ByteArrayOutputStream;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
import java.util.Map;

/** Generated class from Pigeon. */
@SuppressWarnings({"unused", "unchecked", "CodeBlock2Expr", "RedundantSuppression"})
public class CoreTests {
  @NonNull
  private static ArrayList<Object> wrapError(@NonNull Throwable exception) {
    ArrayList<Object> errorList = new ArrayList<>(3);
    errorList.add(exception.toString());
    errorList.add(exception.getClass().getSimpleName());
    errorList.add(
        "Cause: " + exception.getCause() + ", Stacktrace: " + Log.getStackTraceString(exception));
    return errorList;
  }

  public enum AnEnum {
    ONE(0),
    TWO(1),
    THREE(2);

    private final int index;

    private AnEnum(final int index) {
      this.index = index;
    }
  }

  /** Generated class from Pigeon that represents data sent in messages. */
  public static final class AllTypes {
    private @NonNull Boolean aBool;

    public @NonNull Boolean getABool() {
      return aBool;
    }

    public void setABool(@NonNull Boolean setterArg) {
      if (setterArg == null) {
        throw new IllegalStateException("Nonnull field \"aBool\" is null.");
      }
      this.aBool = setterArg;
    }

    private @NonNull Long anInt;

    public @NonNull Long getAnInt() {
      return anInt;
    }

    public void setAnInt(@NonNull Long setterArg) {
      if (setterArg == null) {
        throw new IllegalStateException("Nonnull field \"anInt\" is null.");
      }
      this.anInt = setterArg;
    }

    private @NonNull Double aDouble;

    public @NonNull Double getADouble() {
      return aDouble;
    }

    public void setADouble(@NonNull Double setterArg) {
      if (setterArg == null) {
        throw new IllegalStateException("Nonnull field \"aDouble\" is null.");
      }
      this.aDouble = setterArg;
    }

    private @NonNull byte[] aByteArray;

    public @NonNull byte[] getAByteArray() {
      return aByteArray;
    }

    public void setAByteArray(@NonNull byte[] setterArg) {
      if (setterArg == null) {
        throw new IllegalStateException("Nonnull field \"aByteArray\" is null.");
      }
      this.aByteArray = setterArg;
    }

    private @NonNull int[] a4ByteArray;

    public @NonNull int[] getA4ByteArray() {
      return a4ByteArray;
    }

    public void setA4ByteArray(@NonNull int[] setterArg) {
      if (setterArg == null) {
        throw new IllegalStateException("Nonnull field \"a4ByteArray\" is null.");
      }
      this.a4ByteArray = setterArg;
    }

    private @NonNull long[] a8ByteArray;

    public @NonNull long[] getA8ByteArray() {
      return a8ByteArray;
    }

    public void setA8ByteArray(@NonNull long[] setterArg) {
      if (setterArg == null) {
        throw new IllegalStateException("Nonnull field \"a8ByteArray\" is null.");
      }
      this.a8ByteArray = setterArg;
    }

    private @NonNull double[] aFloatArray;

    public @NonNull double[] getAFloatArray() {
      return aFloatArray;
    }

    public void setAFloatArray(@NonNull double[] setterArg) {
      if (setterArg == null) {
        throw new IllegalStateException("Nonnull field \"aFloatArray\" is null.");
      }
      this.aFloatArray = setterArg;
    }

    private @NonNull List<Object> aList;

    public @NonNull List<Object> getAList() {
      return aList;
    }

    public void setAList(@NonNull List<Object> setterArg) {
      if (setterArg == null) {
        throw new IllegalStateException("Nonnull field \"aList\" is null.");
      }
      this.aList = setterArg;
    }

    private @NonNull Map<Object, Object> aMap;

    public @NonNull Map<Object, Object> getAMap() {
      return aMap;
    }

    public void setAMap(@NonNull Map<Object, Object> setterArg) {
      if (setterArg == null) {
        throw new IllegalStateException("Nonnull field \"aMap\" is null.");
      }
      this.aMap = setterArg;
    }

    private @NonNull AnEnum anEnum;

    public @NonNull AnEnum getAnEnum() {
      return anEnum;
    }

    public void setAnEnum(@NonNull AnEnum setterArg) {
      if (setterArg == null) {
        throw new IllegalStateException("Nonnull field \"anEnum\" is null.");
      }
      this.anEnum = setterArg;
    }

    private @NonNull String aString;

    public @NonNull String getAString() {
      return aString;
    }

    public void setAString(@NonNull String setterArg) {
      if (setterArg == null) {
        throw new IllegalStateException("Nonnull field \"aString\" is null.");
      }
      this.aString = setterArg;
    }

    /** Constructor is private to enforce null safety; use Builder. */
    private AllTypes() {}

    public static final class Builder {

      private @Nullable Boolean aBool;

      public @NonNull Builder setABool(@NonNull Boolean setterArg) {
        this.aBool = setterArg;
        return this;
      }

      private @Nullable Long anInt;

      public @NonNull Builder setAnInt(@NonNull Long setterArg) {
        this.anInt = setterArg;
        return this;
      }

      private @Nullable Double aDouble;

      public @NonNull Builder setADouble(@NonNull Double setterArg) {
        this.aDouble = setterArg;
        return this;
      }

      private @Nullable byte[] aByteArray;

      public @NonNull Builder setAByteArray(@NonNull byte[] setterArg) {
        this.aByteArray = setterArg;
        return this;
      }

      private @Nullable int[] a4ByteArray;

      public @NonNull Builder setA4ByteArray(@NonNull int[] setterArg) {
        this.a4ByteArray = setterArg;
        return this;
      }

      private @Nullable long[] a8ByteArray;

      public @NonNull Builder setA8ByteArray(@NonNull long[] setterArg) {
        this.a8ByteArray = setterArg;
        return this;
      }

      private @Nullable double[] aFloatArray;

      public @NonNull Builder setAFloatArray(@NonNull double[] setterArg) {
        this.aFloatArray = setterArg;
        return this;
      }

      private @Nullable List<Object> aList;

      public @NonNull Builder setAList(@NonNull List<Object> setterArg) {
        this.aList = setterArg;
        return this;
      }

      private @Nullable Map<Object, Object> aMap;

      public @NonNull Builder setAMap(@NonNull Map<Object, Object> setterArg) {
        this.aMap = setterArg;
        return this;
      }

      private @Nullable AnEnum anEnum;

      public @NonNull Builder setAnEnum(@NonNull AnEnum setterArg) {
        this.anEnum = setterArg;
        return this;
      }

      private @Nullable String aString;

      public @NonNull Builder setAString(@NonNull String setterArg) {
        this.aString = setterArg;
        return this;
      }

      public @NonNull AllTypes build() {
        AllTypes pigeonReturn = new AllTypes();
        pigeonReturn.setABool(aBool);
        pigeonReturn.setAnInt(anInt);
        pigeonReturn.setADouble(aDouble);
        pigeonReturn.setAByteArray(aByteArray);
        pigeonReturn.setA4ByteArray(a4ByteArray);
        pigeonReturn.setA8ByteArray(a8ByteArray);
        pigeonReturn.setAFloatArray(aFloatArray);
        pigeonReturn.setAList(aList);
        pigeonReturn.setAMap(aMap);
        pigeonReturn.setAnEnum(anEnum);
        pigeonReturn.setAString(aString);
        return pigeonReturn;
      }
    }

    @NonNull
    ArrayList<Object> toList() {
      ArrayList<Object> toListResult = new ArrayList<Object>(11);
      toListResult.add(aBool);
      toListResult.add(anInt);
      toListResult.add(aDouble);
      toListResult.add(aByteArray);
      toListResult.add(a4ByteArray);
      toListResult.add(a8ByteArray);
      toListResult.add(aFloatArray);
      toListResult.add(aList);
      toListResult.add(aMap);
      toListResult.add(anEnum == null ? null : anEnum.index);
      toListResult.add(aString);
      return toListResult;
    }

    static @NonNull AllTypes fromList(@NonNull ArrayList<Object> list) {
      AllTypes pigeonResult = new AllTypes();
      Object aBool = list.get(0);
      pigeonResult.setABool((Boolean) aBool);
      Object anInt = list.get(1);
      pigeonResult.setAnInt(
          (anInt == null) ? null : ((anInt instanceof Integer) ? (Integer) anInt : (Long) anInt));
      Object aDouble = list.get(2);
      pigeonResult.setADouble((Double) aDouble);
      Object aByteArray = list.get(3);
      pigeonResult.setAByteArray((byte[]) aByteArray);
      Object a4ByteArray = list.get(4);
      pigeonResult.setA4ByteArray((int[]) a4ByteArray);
      Object a8ByteArray = list.get(5);
      pigeonResult.setA8ByteArray((long[]) a8ByteArray);
      Object aFloatArray = list.get(6);
      pigeonResult.setAFloatArray((double[]) aFloatArray);
      Object aList = list.get(7);
      pigeonResult.setAList((List<Object>) aList);
      Object aMap = list.get(8);
      pigeonResult.setAMap((Map<Object, Object>) aMap);
      Object anEnum = list.get(9);
      pigeonResult.setAnEnum(anEnum == null ? null : AnEnum.values()[(int) anEnum]);
      Object aString = list.get(10);
      pigeonResult.setAString((String) aString);
      return pigeonResult;
    }
  }

  /** Generated class from Pigeon that represents data sent in messages. */
  public static final class AllNullableTypes {
    private @Nullable Boolean aNullableBool;

    public @Nullable Boolean getANullableBool() {
      return aNullableBool;
    }

    public void setANullableBool(@Nullable Boolean setterArg) {
      this.aNullableBool = setterArg;
    }

    private @Nullable Long aNullableInt;

    public @Nullable Long getANullableInt() {
      return aNullableInt;
    }

    public void setANullableInt(@Nullable Long setterArg) {
      this.aNullableInt = setterArg;
    }

    private @Nullable Double aNullableDouble;

    public @Nullable Double getANullableDouble() {
      return aNullableDouble;
    }

    public void setANullableDouble(@Nullable Double setterArg) {
      this.aNullableDouble = setterArg;
    }

    private @Nullable byte[] aNullableByteArray;

    public @Nullable byte[] getANullableByteArray() {
      return aNullableByteArray;
    }

    public void setANullableByteArray(@Nullable byte[] setterArg) {
      this.aNullableByteArray = setterArg;
    }

    private @Nullable int[] aNullable4ByteArray;

    public @Nullable int[] getANullable4ByteArray() {
      return aNullable4ByteArray;
    }

    public void setANullable4ByteArray(@Nullable int[] setterArg) {
      this.aNullable4ByteArray = setterArg;
    }

    private @Nullable long[] aNullable8ByteArray;

    public @Nullable long[] getANullable8ByteArray() {
      return aNullable8ByteArray;
    }

    public void setANullable8ByteArray(@Nullable long[] setterArg) {
      this.aNullable8ByteArray = setterArg;
    }

    private @Nullable double[] aNullableFloatArray;

    public @Nullable double[] getANullableFloatArray() {
      return aNullableFloatArray;
    }

    public void setANullableFloatArray(@Nullable double[] setterArg) {
      this.aNullableFloatArray = setterArg;
    }

    private @Nullable List<Object> aNullableList;

    public @Nullable List<Object> getANullableList() {
      return aNullableList;
    }

    public void setANullableList(@Nullable List<Object> setterArg) {
      this.aNullableList = setterArg;
    }

    private @Nullable Map<Object, Object> aNullableMap;

    public @Nullable Map<Object, Object> getANullableMap() {
      return aNullableMap;
    }

    public void setANullableMap(@Nullable Map<Object, Object> setterArg) {
      this.aNullableMap = setterArg;
    }

    private @Nullable List<List<Boolean>> nullableNestedList;

    public @Nullable List<List<Boolean>> getNullableNestedList() {
      return nullableNestedList;
    }

    public void setNullableNestedList(@Nullable List<List<Boolean>> setterArg) {
      this.nullableNestedList = setterArg;
    }

    private @Nullable Map<String, String> nullableMapWithAnnotations;

    public @Nullable Map<String, String> getNullableMapWithAnnotations() {
      return nullableMapWithAnnotations;
    }

    public void setNullableMapWithAnnotations(@Nullable Map<String, String> setterArg) {
      this.nullableMapWithAnnotations = setterArg;
    }

    private @Nullable Map<String, Object> nullableMapWithObject;

    public @Nullable Map<String, Object> getNullableMapWithObject() {
      return nullableMapWithObject;
    }

    public void setNullableMapWithObject(@Nullable Map<String, Object> setterArg) {
      this.nullableMapWithObject = setterArg;
    }

    private @Nullable AnEnum aNullableEnum;

    public @Nullable AnEnum getANullableEnum() {
      return aNullableEnum;
    }

    public void setANullableEnum(@Nullable AnEnum setterArg) {
      this.aNullableEnum = setterArg;
    }

    private @Nullable String aNullableString;

    public @Nullable String getANullableString() {
      return aNullableString;
    }

    public void setANullableString(@Nullable String setterArg) {
      this.aNullableString = setterArg;
    }

    public static final class Builder {

      private @Nullable Boolean aNullableBool;

      public @NonNull Builder setANullableBool(@Nullable Boolean setterArg) {
        this.aNullableBool = setterArg;
        return this;
      }

      private @Nullable Long aNullableInt;

      public @NonNull Builder setANullableInt(@Nullable Long setterArg) {
        this.aNullableInt = setterArg;
        return this;
      }

      private @Nullable Double aNullableDouble;

      public @NonNull Builder setANullableDouble(@Nullable Double setterArg) {
        this.aNullableDouble = setterArg;
        return this;
      }

      private @Nullable byte[] aNullableByteArray;

      public @NonNull Builder setANullableByteArray(@Nullable byte[] setterArg) {
        this.aNullableByteArray = setterArg;
        return this;
      }

      private @Nullable int[] aNullable4ByteArray;

      public @NonNull Builder setANullable4ByteArray(@Nullable int[] setterArg) {
        this.aNullable4ByteArray = setterArg;
        return this;
      }

      private @Nullable long[] aNullable8ByteArray;

      public @NonNull Builder setANullable8ByteArray(@Nullable long[] setterArg) {
        this.aNullable8ByteArray = setterArg;
        return this;
      }

      private @Nullable double[] aNullableFloatArray;

      public @NonNull Builder setANullableFloatArray(@Nullable double[] setterArg) {
        this.aNullableFloatArray = setterArg;
        return this;
      }

      private @Nullable List<Object> aNullableList;

      public @NonNull Builder setANullableList(@Nullable List<Object> setterArg) {
        this.aNullableList = setterArg;
        return this;
      }

      private @Nullable Map<Object, Object> aNullableMap;

      public @NonNull Builder setANullableMap(@Nullable Map<Object, Object> setterArg) {
        this.aNullableMap = setterArg;
        return this;
      }

      private @Nullable List<List<Boolean>> nullableNestedList;

      public @NonNull Builder setNullableNestedList(@Nullable List<List<Boolean>> setterArg) {
        this.nullableNestedList = setterArg;
        return this;
      }

      private @Nullable Map<String, String> nullableMapWithAnnotations;

      public @NonNull Builder setNullableMapWithAnnotations(
          @Nullable Map<String, String> setterArg) {
        this.nullableMapWithAnnotations = setterArg;
        return this;
      }

      private @Nullable Map<String, Object> nullableMapWithObject;

      public @NonNull Builder setNullableMapWithObject(@Nullable Map<String, Object> setterArg) {
        this.nullableMapWithObject = setterArg;
        return this;
      }

      private @Nullable AnEnum aNullableEnum;

      public @NonNull Builder setANullableEnum(@Nullable AnEnum setterArg) {
        this.aNullableEnum = setterArg;
        return this;
      }

      private @Nullable String aNullableString;

      public @NonNull Builder setANullableString(@Nullable String setterArg) {
        this.aNullableString = setterArg;
        return this;
      }

      public @NonNull AllNullableTypes build() {
        AllNullableTypes pigeonReturn = new AllNullableTypes();
        pigeonReturn.setANullableBool(aNullableBool);
        pigeonReturn.setANullableInt(aNullableInt);
        pigeonReturn.setANullableDouble(aNullableDouble);
        pigeonReturn.setANullableByteArray(aNullableByteArray);
        pigeonReturn.setANullable4ByteArray(aNullable4ByteArray);
        pigeonReturn.setANullable8ByteArray(aNullable8ByteArray);
        pigeonReturn.setANullableFloatArray(aNullableFloatArray);
        pigeonReturn.setANullableList(aNullableList);
        pigeonReturn.setANullableMap(aNullableMap);
        pigeonReturn.setNullableNestedList(nullableNestedList);
        pigeonReturn.setNullableMapWithAnnotations(nullableMapWithAnnotations);
        pigeonReturn.setNullableMapWithObject(nullableMapWithObject);
        pigeonReturn.setANullableEnum(aNullableEnum);
        pigeonReturn.setANullableString(aNullableString);
        return pigeonReturn;
      }
    }

    @NonNull
    ArrayList<Object> toList() {
      ArrayList<Object> toListResult = new ArrayList<Object>(14);
      toListResult.add(aNullableBool);
      toListResult.add(aNullableInt);
      toListResult.add(aNullableDouble);
      toListResult.add(aNullableByteArray);
      toListResult.add(aNullable4ByteArray);
      toListResult.add(aNullable8ByteArray);
      toListResult.add(aNullableFloatArray);
      toListResult.add(aNullableList);
      toListResult.add(aNullableMap);
      toListResult.add(nullableNestedList);
      toListResult.add(nullableMapWithAnnotations);
      toListResult.add(nullableMapWithObject);
      toListResult.add(aNullableEnum == null ? null : aNullableEnum.index);
      toListResult.add(aNullableString);
      return toListResult;
    }

    static @NonNull AllNullableTypes fromList(@NonNull ArrayList<Object> list) {
      AllNullableTypes pigeonResult = new AllNullableTypes();
      Object aNullableBool = list.get(0);
      pigeonResult.setANullableBool((Boolean) aNullableBool);
      Object aNullableInt = list.get(1);
      pigeonResult.setANullableInt(
          (aNullableInt == null)
              ? null
              : ((aNullableInt instanceof Integer) ? (Integer) aNullableInt : (Long) aNullableInt));
      Object aNullableDouble = list.get(2);
      pigeonResult.setANullableDouble((Double) aNullableDouble);
      Object aNullableByteArray = list.get(3);
      pigeonResult.setANullableByteArray((byte[]) aNullableByteArray);
      Object aNullable4ByteArray = list.get(4);
      pigeonResult.setANullable4ByteArray((int[]) aNullable4ByteArray);
      Object aNullable8ByteArray = list.get(5);
      pigeonResult.setANullable8ByteArray((long[]) aNullable8ByteArray);
      Object aNullableFloatArray = list.get(6);
      pigeonResult.setANullableFloatArray((double[]) aNullableFloatArray);
      Object aNullableList = list.get(7);
      pigeonResult.setANullableList((List<Object>) aNullableList);
      Object aNullableMap = list.get(8);
      pigeonResult.setANullableMap((Map<Object, Object>) aNullableMap);
      Object nullableNestedList = list.get(9);
      pigeonResult.setNullableNestedList((List<List<Boolean>>) nullableNestedList);
      Object nullableMapWithAnnotations = list.get(10);
      pigeonResult.setNullableMapWithAnnotations((Map<String, String>) nullableMapWithAnnotations);
      Object nullableMapWithObject = list.get(11);
      pigeonResult.setNullableMapWithObject((Map<String, Object>) nullableMapWithObject);
      Object aNullableEnum = list.get(12);
      pigeonResult.setANullableEnum(
          aNullableEnum == null ? null : AnEnum.values()[(int) aNullableEnum]);
      Object aNullableString = list.get(13);
      pigeonResult.setANullableString((String) aNullableString);
      return pigeonResult;
    }
  }

  /** Generated class from Pigeon that represents data sent in messages. */
  public static final class AllNullableTypesWrapper {
    private @NonNull AllNullableTypes values;

    public @NonNull AllNullableTypes getValues() {
      return values;
    }

    public void setValues(@NonNull AllNullableTypes setterArg) {
      if (setterArg == null) {
        throw new IllegalStateException("Nonnull field \"values\" is null.");
      }
      this.values = setterArg;
    }

    /** Constructor is private to enforce null safety; use Builder. */
    private AllNullableTypesWrapper() {}

    public static final class Builder {

      private @Nullable AllNullableTypes values;

      public @NonNull Builder setValues(@NonNull AllNullableTypes setterArg) {
        this.values = setterArg;
        return this;
      }

      public @NonNull AllNullableTypesWrapper build() {
        AllNullableTypesWrapper pigeonReturn = new AllNullableTypesWrapper();
        pigeonReturn.setValues(values);
        return pigeonReturn;
      }
    }

    @NonNull
    ArrayList<Object> toList() {
      ArrayList<Object> toListResult = new ArrayList<Object>(1);
      toListResult.add((values == null) ? null : values.toList());
      return toListResult;
    }

    static @NonNull AllNullableTypesWrapper fromList(@NonNull ArrayList<Object> list) {
      AllNullableTypesWrapper pigeonResult = new AllNullableTypesWrapper();
      Object values = list.get(0);
      pigeonResult.setValues(
          (values == null) ? null : AllNullableTypes.fromList((ArrayList<Object>) values));
      return pigeonResult;
    }
  }

  public interface Result<T> {
    void success(T result);

    void error(Throwable error);
  }

  private static class HostIntegrationCoreApiCodec extends StandardMessageCodec {
    public static final HostIntegrationCoreApiCodec INSTANCE = new HostIntegrationCoreApiCodec();

    private HostIntegrationCoreApiCodec() {}

    @Override
    protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) {
      switch (type) {
        case (byte) 128:
          return AllNullableTypes.fromList((ArrayList<Object>) readValue(buffer));

        case (byte) 129:
          return AllNullableTypesWrapper.fromList((ArrayList<Object>) readValue(buffer));

        case (byte) 130:
          return AllTypes.fromList((ArrayList<Object>) readValue(buffer));

        default:
          return super.readValueOfType(type, buffer);
      }
    }

    @Override
    protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) {
      if (value instanceof AllNullableTypes) {
        stream.write(128);
        writeValue(stream, ((AllNullableTypes) value).toList());
      } else if (value instanceof AllNullableTypesWrapper) {
        stream.write(129);
        writeValue(stream, ((AllNullableTypesWrapper) value).toList());
      } else if (value instanceof AllTypes) {
        stream.write(130);
        writeValue(stream, ((AllTypes) value).toList());
      } else {
        super.writeValue(stream, value);
      }
    }
  }

  /**
   * The core interface that each host language plugin must implement in platform_test integration
   * tests.
   *
   * <p>Generated interface from Pigeon that represents a handler of messages from Flutter.
   */
  public interface HostIntegrationCoreApi {
    /**
     * A no-op function taking no arguments and returning no value, to sanity test basic calling.
     */
    void noop();
    /** Returns the passed object, to test serialization and deserialization. */
    @NonNull
    AllTypes echoAllTypes(@NonNull AllTypes everything);
    /** Returns the passed object, to test serialization and deserialization. */
    @Nullable
    AllNullableTypes echoAllNullableTypes(@Nullable AllNullableTypes everything);
    /** Returns an error, to test error handling. */
    void throwError();
    /** Returns passed in int. */
    @NonNull
    Long echoInt(@NonNull Long anInt);
    /** Returns passed in double. */
    @NonNull
    Double echoDouble(@NonNull Double aDouble);
    /** Returns the passed in boolean. */
    @NonNull
    Boolean echoBool(@NonNull Boolean aBool);
    /** Returns the passed in string. */
    @NonNull
    String echoString(@NonNull String aString);
    /** Returns the passed in Uint8List. */
    @NonNull
    byte[] echoUint8List(@NonNull byte[] aUint8List);
    /** Returns the passed in generic Object. */
    @NonNull
    Object echoObject(@NonNull Object anObject);
    /**
     * Returns the inner `aString` value from the wrapped object, to test sending of nested objects.
     */
    @Nullable
    String extractNestedNullableString(@NonNull AllNullableTypesWrapper wrapper);
    /**
     * Returns the inner `aString` value from the wrapped object, to test sending of nested objects.
     */
    @NonNull
    AllNullableTypesWrapper createNestedNullableString(@Nullable String nullableString);
    /** Returns passed in arguments of multiple types. */
    @NonNull
    AllNullableTypes sendMultipleNullableTypes(
        @Nullable Boolean aNullableBool,
        @Nullable Long aNullableInt,
        @Nullable String aNullableString);
    /** Returns passed in int. */
    @Nullable
    Long echoNullableInt(@Nullable Long aNullableInt);
    /** Returns passed in double. */
    @Nullable
    Double echoNullableDouble(@Nullable Double aNullableDouble);
    /** Returns the passed in boolean. */
    @Nullable
    Boolean echoNullableBool(@Nullable Boolean aNullableBool);
    /** Returns the passed in string. */
    @Nullable
    String echoNullableString(@Nullable String aNullableString);
    /** Returns the passed in Uint8List. */
    @Nullable
    byte[] echoNullableUint8List(@Nullable byte[] aNullableUint8List);
    /** Returns the passed in generic Object. */
    @Nullable
    Object echoNullableObject(@Nullable Object aNullableObject);
    /**
     * A no-op function taking no arguments and returning no value, to sanity test basic
     * asynchronous calling.
     */
    void noopAsync(Result<Void> result);
    /** Returns the passed string asynchronously. */
    void echoAsyncString(@NonNull String aString, Result<String> result);

    void callFlutterNoop(Result<Void> result);

    void callFlutterEchoAllTypes(@NonNull AllTypes everything, Result<AllTypes> result);

    void callFlutterSendMultipleNullableTypes(
        @Nullable Boolean aNullableBool,
        @Nullable Long aNullableInt,
        @Nullable String aNullableString,
        Result<AllNullableTypes> result);

    void callFlutterEchoBool(@NonNull Boolean aBool, Result<Boolean> result);

    void callFlutterEchoInt(@NonNull Long anInt, Result<Long> result);

    void callFlutterEchoDouble(@NonNull Double aDouble, Result<Double> result);

    void callFlutterEchoString(@NonNull String aString, Result<String> result);

    void callFlutterEchoUint8List(@NonNull byte[] aList, Result<byte[]> result);

    void callFlutterEchoList(@NonNull List<Object> aList, Result<List<Object>> result);

    void callFlutterEchoMap(@NonNull Map<String, Object> aMap, Result<Map<String, Object>> result);

    void callFlutterEchoNullableBool(@Nullable Boolean aBool, Result<Boolean> result);

    void callFlutterEchoNullableInt(@Nullable Long anInt, Result<Long> result);

    void callFlutterEchoNullableDouble(@Nullable Double aDouble, Result<Double> result);

    void callFlutterEchoNullableString(@Nullable String aString, Result<String> result);

    void callFlutterEchoNullableUint8List(@Nullable byte[] aList, Result<byte[]> result);

    void callFlutterEchoNullableList(@Nullable List<Object> aList, Result<List<Object>> result);

    void callFlutterEchoNullableMap(
        @Nullable Map<String, Object> aMap, Result<Map<String, Object>> result);

    /** The codec used by HostIntegrationCoreApi. */
    static MessageCodec<Object> getCodec() {
      return HostIntegrationCoreApiCodec.INSTANCE;
    }
    /**
     * Sets up an instance of `HostIntegrationCoreApi` to handle messages through the
     * `binaryMessenger`.
     */
    static void setup(BinaryMessenger binaryMessenger, HostIntegrationCoreApi api) {
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger, "dev.flutter.pigeon.HostIntegrationCoreApi.noop", getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                ArrayList wrapped = new ArrayList<>();
                try {
                  api.noop();
                  wrapped.add(0, null);
                } catch (Error | RuntimeException exception) {
                  ArrayList<Object> wrappedError = wrapError(exception);
                  wrapped = wrappedError;
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.HostIntegrationCoreApi.echoAllTypes",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                ArrayList wrapped = new ArrayList<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  assert args != null;
                  AllTypes everythingArg = (AllTypes) args.get(0);
                  if (everythingArg == null) {
                    throw new NullPointerException("everythingArg unexpectedly null.");
                  }
                  AllTypes output = api.echoAllTypes(everythingArg);
                  wrapped.add(0, output);
                } catch (Error | RuntimeException exception) {
                  ArrayList<Object> wrappedError = wrapError(exception);
                  wrapped = wrappedError;
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.HostIntegrationCoreApi.echoAllNullableTypes",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                ArrayList wrapped = new ArrayList<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  assert args != null;
                  AllNullableTypes everythingArg = (AllNullableTypes) args.get(0);
                  AllNullableTypes output = api.echoAllNullableTypes(everythingArg);
                  wrapped.add(0, output);
                } catch (Error | RuntimeException exception) {
                  ArrayList<Object> wrappedError = wrapError(exception);
                  wrapped = wrappedError;
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.HostIntegrationCoreApi.throwError",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                ArrayList wrapped = new ArrayList<>();
                try {
                  api.throwError();
                  wrapped.add(0, null);
                } catch (Error | RuntimeException exception) {
                  ArrayList<Object> wrappedError = wrapError(exception);
                  wrapped = wrappedError;
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger, "dev.flutter.pigeon.HostIntegrationCoreApi.echoInt", getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                ArrayList wrapped = new ArrayList<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  assert args != null;
                  Number anIntArg = (Number) args.get(0);
                  if (anIntArg == null) {
                    throw new NullPointerException("anIntArg unexpectedly null.");
                  }
                  Long output = api.echoInt((anIntArg == null) ? null : anIntArg.longValue());
                  wrapped.add(0, output);
                } catch (Error | RuntimeException exception) {
                  ArrayList<Object> wrappedError = wrapError(exception);
                  wrapped = wrappedError;
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.HostIntegrationCoreApi.echoDouble",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                ArrayList wrapped = new ArrayList<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  assert args != null;
                  Double aDoubleArg = (Double) args.get(0);
                  if (aDoubleArg == null) {
                    throw new NullPointerException("aDoubleArg unexpectedly null.");
                  }
                  Double output = api.echoDouble(aDoubleArg);
                  wrapped.add(0, output);
                } catch (Error | RuntimeException exception) {
                  ArrayList<Object> wrappedError = wrapError(exception);
                  wrapped = wrappedError;
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger, "dev.flutter.pigeon.HostIntegrationCoreApi.echoBool", getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                ArrayList wrapped = new ArrayList<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  assert args != null;
                  Boolean aBoolArg = (Boolean) args.get(0);
                  if (aBoolArg == null) {
                    throw new NullPointerException("aBoolArg unexpectedly null.");
                  }
                  Boolean output = api.echoBool(aBoolArg);
                  wrapped.add(0, output);
                } catch (Error | RuntimeException exception) {
                  ArrayList<Object> wrappedError = wrapError(exception);
                  wrapped = wrappedError;
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.HostIntegrationCoreApi.echoString",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                ArrayList wrapped = new ArrayList<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  assert args != null;
                  String aStringArg = (String) args.get(0);
                  if (aStringArg == null) {
                    throw new NullPointerException("aStringArg unexpectedly null.");
                  }
                  String output = api.echoString(aStringArg);
                  wrapped.add(0, output);
                } catch (Error | RuntimeException exception) {
                  ArrayList<Object> wrappedError = wrapError(exception);
                  wrapped = wrappedError;
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.HostIntegrationCoreApi.echoUint8List",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                ArrayList wrapped = new ArrayList<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  assert args != null;
                  byte[] aUint8ListArg = (byte[]) args.get(0);
                  if (aUint8ListArg == null) {
                    throw new NullPointerException("aUint8ListArg unexpectedly null.");
                  }
                  byte[] output = api.echoUint8List(aUint8ListArg);
                  wrapped.add(0, output);
                } catch (Error | RuntimeException exception) {
                  ArrayList<Object> wrappedError = wrapError(exception);
                  wrapped = wrappedError;
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.HostIntegrationCoreApi.echoObject",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                ArrayList wrapped = new ArrayList<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  assert args != null;
                  Object anObjectArg = args.get(0);
                  if (anObjectArg == null) {
                    throw new NullPointerException("anObjectArg unexpectedly null.");
                  }
                  Object output = api.echoObject(anObjectArg);
                  wrapped.add(0, output);
                } catch (Error | RuntimeException exception) {
                  ArrayList<Object> wrappedError = wrapError(exception);
                  wrapped = wrappedError;
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.HostIntegrationCoreApi.extractNestedNullableString",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                ArrayList wrapped = new ArrayList<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  assert args != null;
                  AllNullableTypesWrapper wrapperArg = (AllNullableTypesWrapper) args.get(0);
                  if (wrapperArg == null) {
                    throw new NullPointerException("wrapperArg unexpectedly null.");
                  }
                  String output = api.extractNestedNullableString(wrapperArg);
                  wrapped.add(0, output);
                } catch (Error | RuntimeException exception) {
                  ArrayList<Object> wrappedError = wrapError(exception);
                  wrapped = wrappedError;
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.HostIntegrationCoreApi.createNestedNullableString",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                ArrayList wrapped = new ArrayList<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  assert args != null;
                  String nullableStringArg = (String) args.get(0);
                  AllNullableTypesWrapper output =
                      api.createNestedNullableString(nullableStringArg);
                  wrapped.add(0, output);
                } catch (Error | RuntimeException exception) {
                  ArrayList<Object> wrappedError = wrapError(exception);
                  wrapped = wrappedError;
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.HostIntegrationCoreApi.sendMultipleNullableTypes",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                ArrayList wrapped = new ArrayList<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  assert args != null;
                  Boolean aNullableBoolArg = (Boolean) args.get(0);
                  Number aNullableIntArg = (Number) args.get(1);
                  String aNullableStringArg = (String) args.get(2);
                  AllNullableTypes output =
                      api.sendMultipleNullableTypes(
                          aNullableBoolArg,
                          (aNullableIntArg == null) ? null : aNullableIntArg.longValue(),
                          aNullableStringArg);
                  wrapped.add(0, output);
                } catch (Error | RuntimeException exception) {
                  ArrayList<Object> wrappedError = wrapError(exception);
                  wrapped = wrappedError;
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.HostIntegrationCoreApi.echoNullableInt",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                ArrayList wrapped = new ArrayList<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  assert args != null;
                  Number aNullableIntArg = (Number) args.get(0);
                  Long output =
                      api.echoNullableInt(
                          (aNullableIntArg == null) ? null : aNullableIntArg.longValue());
                  wrapped.add(0, output);
                } catch (Error | RuntimeException exception) {
                  ArrayList<Object> wrappedError = wrapError(exception);
                  wrapped = wrappedError;
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.HostIntegrationCoreApi.echoNullableDouble",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                ArrayList wrapped = new ArrayList<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  assert args != null;
                  Double aNullableDoubleArg = (Double) args.get(0);
                  Double output = api.echoNullableDouble(aNullableDoubleArg);
                  wrapped.add(0, output);
                } catch (Error | RuntimeException exception) {
                  ArrayList<Object> wrappedError = wrapError(exception);
                  wrapped = wrappedError;
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.HostIntegrationCoreApi.echoNullableBool",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                ArrayList wrapped = new ArrayList<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  assert args != null;
                  Boolean aNullableBoolArg = (Boolean) args.get(0);
                  Boolean output = api.echoNullableBool(aNullableBoolArg);
                  wrapped.add(0, output);
                } catch (Error | RuntimeException exception) {
                  ArrayList<Object> wrappedError = wrapError(exception);
                  wrapped = wrappedError;
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.HostIntegrationCoreApi.echoNullableString",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                ArrayList wrapped = new ArrayList<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  assert args != null;
                  String aNullableStringArg = (String) args.get(0);
                  String output = api.echoNullableString(aNullableStringArg);
                  wrapped.add(0, output);
                } catch (Error | RuntimeException exception) {
                  ArrayList<Object> wrappedError = wrapError(exception);
                  wrapped = wrappedError;
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.HostIntegrationCoreApi.echoNullableUint8List",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                ArrayList wrapped = new ArrayList<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  assert args != null;
                  byte[] aNullableUint8ListArg = (byte[]) args.get(0);
                  byte[] output = api.echoNullableUint8List(aNullableUint8ListArg);
                  wrapped.add(0, output);
                } catch (Error | RuntimeException exception) {
                  ArrayList<Object> wrappedError = wrapError(exception);
                  wrapped = wrappedError;
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.HostIntegrationCoreApi.echoNullableObject",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                ArrayList wrapped = new ArrayList<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  assert args != null;
                  Object aNullableObjectArg = args.get(0);
                  Object output = api.echoNullableObject(aNullableObjectArg);
                  wrapped.add(0, output);
                } catch (Error | RuntimeException exception) {
                  ArrayList<Object> wrappedError = wrapError(exception);
                  wrapped = wrappedError;
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger, "dev.flutter.pigeon.HostIntegrationCoreApi.noopAsync", getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                ArrayList wrapped = new ArrayList<>();
                try {
                  Result<Void> resultCallback =
                      new Result<Void>() {
                        public void success(Void result) {
                          wrapped.add(0, null);
                          reply.reply(wrapped);
                        }

                        public void error(Throwable error) {
                          ArrayList<Object> wrappedError = wrapError(error);
                          reply.reply(wrappedError);
                        }
                      };

                  api.noopAsync(resultCallback);
                } catch (Error | RuntimeException exception) {
                  ArrayList<Object> wrappedError = wrapError(exception);
                  reply.reply(wrappedError);
                }
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.HostIntegrationCoreApi.echoAsyncString",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                ArrayList wrapped = new ArrayList<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  assert args != null;
                  String aStringArg = (String) args.get(0);
                  if (aStringArg == null) {
                    throw new NullPointerException("aStringArg unexpectedly null.");
                  }
                  Result<String> resultCallback =
                      new Result<String>() {
                        public void success(String result) {
                          wrapped.add(0, result);
                          reply.reply(wrapped);
                        }

                        public void error(Throwable error) {
                          ArrayList<Object> wrappedError = wrapError(error);
                          reply.reply(wrappedError);
                        }
                      };

                  api.echoAsyncString(aStringArg, resultCallback);
                } catch (Error | RuntimeException exception) {
                  ArrayList<Object> wrappedError = wrapError(exception);
                  reply.reply(wrappedError);
                }
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.HostIntegrationCoreApi.callFlutterNoop",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                ArrayList wrapped = new ArrayList<>();
                try {
                  Result<Void> resultCallback =
                      new Result<Void>() {
                        public void success(Void result) {
                          wrapped.add(0, null);
                          reply.reply(wrapped);
                        }

                        public void error(Throwable error) {
                          ArrayList<Object> wrappedError = wrapError(error);
                          reply.reply(wrappedError);
                        }
                      };

                  api.callFlutterNoop(resultCallback);
                } catch (Error | RuntimeException exception) {
                  ArrayList<Object> wrappedError = wrapError(exception);
                  reply.reply(wrappedError);
                }
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.HostIntegrationCoreApi.callFlutterEchoAllTypes",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                ArrayList wrapped = new ArrayList<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  assert args != null;
                  AllTypes everythingArg = (AllTypes) args.get(0);
                  if (everythingArg == null) {
                    throw new NullPointerException("everythingArg unexpectedly null.");
                  }
                  Result<AllTypes> resultCallback =
                      new Result<AllTypes>() {
                        public void success(AllTypes result) {
                          wrapped.add(0, result);
                          reply.reply(wrapped);
                        }

                        public void error(Throwable error) {
                          ArrayList<Object> wrappedError = wrapError(error);
                          reply.reply(wrappedError);
                        }
                      };

                  api.callFlutterEchoAllTypes(everythingArg, resultCallback);
                } catch (Error | RuntimeException exception) {
                  ArrayList<Object> wrappedError = wrapError(exception);
                  reply.reply(wrappedError);
                }
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.HostIntegrationCoreApi.callFlutterSendMultipleNullableTypes",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                ArrayList wrapped = new ArrayList<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  assert args != null;
                  Boolean aNullableBoolArg = (Boolean) args.get(0);
                  Number aNullableIntArg = (Number) args.get(1);
                  String aNullableStringArg = (String) args.get(2);
                  Result<AllNullableTypes> resultCallback =
                      new Result<AllNullableTypes>() {
                        public void success(AllNullableTypes result) {
                          wrapped.add(0, result);
                          reply.reply(wrapped);
                        }

                        public void error(Throwable error) {
                          ArrayList<Object> wrappedError = wrapError(error);
                          reply.reply(wrappedError);
                        }
                      };

                  api.callFlutterSendMultipleNullableTypes(
                      aNullableBoolArg,
                      (aNullableIntArg == null) ? null : aNullableIntArg.longValue(),
                      aNullableStringArg,
                      resultCallback);
                } catch (Error | RuntimeException exception) {
                  ArrayList<Object> wrappedError = wrapError(exception);
                  reply.reply(wrappedError);
                }
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.HostIntegrationCoreApi.callFlutterEchoBool",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                ArrayList wrapped = new ArrayList<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  assert args != null;
                  Boolean aBoolArg = (Boolean) args.get(0);
                  if (aBoolArg == null) {
                    throw new NullPointerException("aBoolArg unexpectedly null.");
                  }
                  Result<Boolean> resultCallback =
                      new Result<Boolean>() {
                        public void success(Boolean result) {
                          wrapped.add(0, result);
                          reply.reply(wrapped);
                        }

                        public void error(Throwable error) {
                          ArrayList<Object> wrappedError = wrapError(error);
                          reply.reply(wrappedError);
                        }
                      };

                  api.callFlutterEchoBool(aBoolArg, resultCallback);
                } catch (Error | RuntimeException exception) {
                  ArrayList<Object> wrappedError = wrapError(exception);
                  reply.reply(wrappedError);
                }
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.HostIntegrationCoreApi.callFlutterEchoInt",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                ArrayList wrapped = new ArrayList<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  assert args != null;
                  Number anIntArg = (Number) args.get(0);
                  if (anIntArg == null) {
                    throw new NullPointerException("anIntArg unexpectedly null.");
                  }
                  Result<Long> resultCallback =
                      new Result<Long>() {
                        public void success(Long result) {
                          wrapped.add(0, result);
                          reply.reply(wrapped);
                        }

                        public void error(Throwable error) {
                          ArrayList<Object> wrappedError = wrapError(error);
                          reply.reply(wrappedError);
                        }
                      };

                  api.callFlutterEchoInt(
                      (anIntArg == null) ? null : anIntArg.longValue(), resultCallback);
                } catch (Error | RuntimeException exception) {
                  ArrayList<Object> wrappedError = wrapError(exception);
                  reply.reply(wrappedError);
                }
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.HostIntegrationCoreApi.callFlutterEchoDouble",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                ArrayList wrapped = new ArrayList<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  assert args != null;
                  Double aDoubleArg = (Double) args.get(0);
                  if (aDoubleArg == null) {
                    throw new NullPointerException("aDoubleArg unexpectedly null.");
                  }
                  Result<Double> resultCallback =
                      new Result<Double>() {
                        public void success(Double result) {
                          wrapped.add(0, result);
                          reply.reply(wrapped);
                        }

                        public void error(Throwable error) {
                          ArrayList<Object> wrappedError = wrapError(error);
                          reply.reply(wrappedError);
                        }
                      };

                  api.callFlutterEchoDouble(aDoubleArg, resultCallback);
                } catch (Error | RuntimeException exception) {
                  ArrayList<Object> wrappedError = wrapError(exception);
                  reply.reply(wrappedError);
                }
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.HostIntegrationCoreApi.callFlutterEchoString",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                ArrayList wrapped = new ArrayList<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  assert args != null;
                  String aStringArg = (String) args.get(0);
                  if (aStringArg == null) {
                    throw new NullPointerException("aStringArg unexpectedly null.");
                  }
                  Result<String> resultCallback =
                      new Result<String>() {
                        public void success(String result) {
                          wrapped.add(0, result);
                          reply.reply(wrapped);
                        }

                        public void error(Throwable error) {
                          ArrayList<Object> wrappedError = wrapError(error);
                          reply.reply(wrappedError);
                        }
                      };

                  api.callFlutterEchoString(aStringArg, resultCallback);
                } catch (Error | RuntimeException exception) {
                  ArrayList<Object> wrappedError = wrapError(exception);
                  reply.reply(wrappedError);
                }
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.HostIntegrationCoreApi.callFlutterEchoUint8List",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                ArrayList wrapped = new ArrayList<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  assert args != null;
                  byte[] aListArg = (byte[]) args.get(0);
                  if (aListArg == null) {
                    throw new NullPointerException("aListArg unexpectedly null.");
                  }
                  Result<byte[]> resultCallback =
                      new Result<byte[]>() {
                        public void success(byte[] result) {
                          wrapped.add(0, result);
                          reply.reply(wrapped);
                        }

                        public void error(Throwable error) {
                          ArrayList<Object> wrappedError = wrapError(error);
                          reply.reply(wrappedError);
                        }
                      };

                  api.callFlutterEchoUint8List(aListArg, resultCallback);
                } catch (Error | RuntimeException exception) {
                  ArrayList<Object> wrappedError = wrapError(exception);
                  reply.reply(wrappedError);
                }
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.HostIntegrationCoreApi.callFlutterEchoList",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                ArrayList wrapped = new ArrayList<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  assert args != null;
                  List<Object> aListArg = (List<Object>) args.get(0);
                  if (aListArg == null) {
                    throw new NullPointerException("aListArg unexpectedly null.");
                  }
                  Result<List<Object>> resultCallback =
                      new Result<List<Object>>() {
                        public void success(List<Object> result) {
                          wrapped.add(0, result);
                          reply.reply(wrapped);
                        }

                        public void error(Throwable error) {
                          ArrayList<Object> wrappedError = wrapError(error);
                          reply.reply(wrappedError);
                        }
                      };

                  api.callFlutterEchoList(aListArg, resultCallback);
                } catch (Error | RuntimeException exception) {
                  ArrayList<Object> wrappedError = wrapError(exception);
                  reply.reply(wrappedError);
                }
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.HostIntegrationCoreApi.callFlutterEchoMap",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                ArrayList wrapped = new ArrayList<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  assert args != null;
                  Map<String, Object> aMapArg = (Map<String, Object>) args.get(0);
                  if (aMapArg == null) {
                    throw new NullPointerException("aMapArg unexpectedly null.");
                  }
                  Result<Map<String, Object>> resultCallback =
                      new Result<Map<String, Object>>() {
                        public void success(Map<String, Object> result) {
                          wrapped.add(0, result);
                          reply.reply(wrapped);
                        }

                        public void error(Throwable error) {
                          ArrayList<Object> wrappedError = wrapError(error);
                          reply.reply(wrappedError);
                        }
                      };

                  api.callFlutterEchoMap(aMapArg, resultCallback);
                } catch (Error | RuntimeException exception) {
                  ArrayList<Object> wrappedError = wrapError(exception);
                  reply.reply(wrappedError);
                }
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.HostIntegrationCoreApi.callFlutterEchoNullableBool",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                ArrayList wrapped = new ArrayList<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  assert args != null;
                  Boolean aBoolArg = (Boolean) args.get(0);
                  Result<Boolean> resultCallback =
                      new Result<Boolean>() {
                        public void success(Boolean result) {
                          wrapped.add(0, result);
                          reply.reply(wrapped);
                        }

                        public void error(Throwable error) {
                          ArrayList<Object> wrappedError = wrapError(error);
                          reply.reply(wrappedError);
                        }
                      };

                  api.callFlutterEchoNullableBool(aBoolArg, resultCallback);
                } catch (Error | RuntimeException exception) {
                  ArrayList<Object> wrappedError = wrapError(exception);
                  reply.reply(wrappedError);
                }
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.HostIntegrationCoreApi.callFlutterEchoNullableInt",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                ArrayList wrapped = new ArrayList<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  assert args != null;
                  Number anIntArg = (Number) args.get(0);
                  Result<Long> resultCallback =
                      new Result<Long>() {
                        public void success(Long result) {
                          wrapped.add(0, result);
                          reply.reply(wrapped);
                        }

                        public void error(Throwable error) {
                          ArrayList<Object> wrappedError = wrapError(error);
                          reply.reply(wrappedError);
                        }
                      };

                  api.callFlutterEchoNullableInt(
                      (anIntArg == null) ? null : anIntArg.longValue(), resultCallback);
                } catch (Error | RuntimeException exception) {
                  ArrayList<Object> wrappedError = wrapError(exception);
                  reply.reply(wrappedError);
                }
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.HostIntegrationCoreApi.callFlutterEchoNullableDouble",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                ArrayList wrapped = new ArrayList<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  assert args != null;
                  Double aDoubleArg = (Double) args.get(0);
                  Result<Double> resultCallback =
                      new Result<Double>() {
                        public void success(Double result) {
                          wrapped.add(0, result);
                          reply.reply(wrapped);
                        }

                        public void error(Throwable error) {
                          ArrayList<Object> wrappedError = wrapError(error);
                          reply.reply(wrappedError);
                        }
                      };

                  api.callFlutterEchoNullableDouble(aDoubleArg, resultCallback);
                } catch (Error | RuntimeException exception) {
                  ArrayList<Object> wrappedError = wrapError(exception);
                  reply.reply(wrappedError);
                }
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.HostIntegrationCoreApi.callFlutterEchoNullableString",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                ArrayList wrapped = new ArrayList<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  assert args != null;
                  String aStringArg = (String) args.get(0);
                  Result<String> resultCallback =
                      new Result<String>() {
                        public void success(String result) {
                          wrapped.add(0, result);
                          reply.reply(wrapped);
                        }

                        public void error(Throwable error) {
                          ArrayList<Object> wrappedError = wrapError(error);
                          reply.reply(wrappedError);
                        }
                      };

                  api.callFlutterEchoNullableString(aStringArg, resultCallback);
                } catch (Error | RuntimeException exception) {
                  ArrayList<Object> wrappedError = wrapError(exception);
                  reply.reply(wrappedError);
                }
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.HostIntegrationCoreApi.callFlutterEchoNullableUint8List",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                ArrayList wrapped = new ArrayList<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  assert args != null;
                  byte[] aListArg = (byte[]) args.get(0);
                  Result<byte[]> resultCallback =
                      new Result<byte[]>() {
                        public void success(byte[] result) {
                          wrapped.add(0, result);
                          reply.reply(wrapped);
                        }

                        public void error(Throwable error) {
                          ArrayList<Object> wrappedError = wrapError(error);
                          reply.reply(wrappedError);
                        }
                      };

                  api.callFlutterEchoNullableUint8List(aListArg, resultCallback);
                } catch (Error | RuntimeException exception) {
                  ArrayList<Object> wrappedError = wrapError(exception);
                  reply.reply(wrappedError);
                }
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.HostIntegrationCoreApi.callFlutterEchoNullableList",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                ArrayList wrapped = new ArrayList<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  assert args != null;
                  List<Object> aListArg = (List<Object>) args.get(0);
                  Result<List<Object>> resultCallback =
                      new Result<List<Object>>() {
                        public void success(List<Object> result) {
                          wrapped.add(0, result);
                          reply.reply(wrapped);
                        }

                        public void error(Throwable error) {
                          ArrayList<Object> wrappedError = wrapError(error);
                          reply.reply(wrappedError);
                        }
                      };

                  api.callFlutterEchoNullableList(aListArg, resultCallback);
                } catch (Error | RuntimeException exception) {
                  ArrayList<Object> wrappedError = wrapError(exception);
                  reply.reply(wrappedError);
                }
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger,
                "dev.flutter.pigeon.HostIntegrationCoreApi.callFlutterEchoNullableMap",
                getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                ArrayList wrapped = new ArrayList<>();
                try {
                  ArrayList<Object> args = (ArrayList<Object>) message;
                  assert args != null;
                  Map<String, Object> aMapArg = (Map<String, Object>) args.get(0);
                  Result<Map<String, Object>> resultCallback =
                      new Result<Map<String, Object>>() {
                        public void success(Map<String, Object> result) {
                          wrapped.add(0, result);
                          reply.reply(wrapped);
                        }

                        public void error(Throwable error) {
                          ArrayList<Object> wrappedError = wrapError(error);
                          reply.reply(wrappedError);
                        }
                      };

                  api.callFlutterEchoNullableMap(aMapArg, resultCallback);
                } catch (Error | RuntimeException exception) {
                  ArrayList<Object> wrappedError = wrapError(exception);
                  reply.reply(wrappedError);
                }
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
    }
  }

  private static class FlutterIntegrationCoreApiCodec extends StandardMessageCodec {
    public static final FlutterIntegrationCoreApiCodec INSTANCE =
        new FlutterIntegrationCoreApiCodec();

    private FlutterIntegrationCoreApiCodec() {}

    @Override
    protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) {
      switch (type) {
        case (byte) 128:
          return AllNullableTypes.fromList((ArrayList<Object>) readValue(buffer));

        case (byte) 129:
          return AllNullableTypesWrapper.fromList((ArrayList<Object>) readValue(buffer));

        case (byte) 130:
          return AllTypes.fromList((ArrayList<Object>) readValue(buffer));

        default:
          return super.readValueOfType(type, buffer);
      }
    }

    @Override
    protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) {
      if (value instanceof AllNullableTypes) {
        stream.write(128);
        writeValue(stream, ((AllNullableTypes) value).toList());
      } else if (value instanceof AllNullableTypesWrapper) {
        stream.write(129);
        writeValue(stream, ((AllNullableTypesWrapper) value).toList());
      } else if (value instanceof AllTypes) {
        stream.write(130);
        writeValue(stream, ((AllTypes) value).toList());
      } else {
        super.writeValue(stream, value);
      }
    }
  }

  /**
   * The core interface that the Dart platform_test code implements for host integration tests to
   * call into.
   *
   * <p>Generated class from Pigeon that represents Flutter messages that can be called from Java.
   */
  public static final class FlutterIntegrationCoreApi {
    private final BinaryMessenger binaryMessenger;

    public FlutterIntegrationCoreApi(BinaryMessenger argBinaryMessenger) {
      this.binaryMessenger = argBinaryMessenger;
    }

    /** Public interface for sending reply. */
    public interface Reply<T> {
      void reply(T reply);
    }
    /** The codec used by FlutterIntegrationCoreApi. */
    static MessageCodec<Object> getCodec() {
      return FlutterIntegrationCoreApiCodec.INSTANCE;
    }
    /**
     * A no-op function taking no arguments and returning no value, to sanity test basic calling.
     */
    public void noop(Reply<Void> callback) {
      BasicMessageChannel<Object> channel =
          new BasicMessageChannel<>(
              binaryMessenger, "dev.flutter.pigeon.FlutterIntegrationCoreApi.noop", getCodec());
      channel.send(null, channelReply -> callback.reply(null));
    }
    /** Returns the passed object, to test serialization and deserialization. */
    public void echoAllTypes(@NonNull AllTypes everythingArg, Reply<AllTypes> callback) {
      BasicMessageChannel<Object> channel =
          new BasicMessageChannel<>(
              binaryMessenger,
              "dev.flutter.pigeon.FlutterIntegrationCoreApi.echoAllTypes",
              getCodec());
      channel.send(
          new ArrayList<Object>(Collections.singletonList(everythingArg)),
          channelReply -> {
            @SuppressWarnings("ConstantConditions")
            AllTypes output = (AllTypes) channelReply;
            callback.reply(output);
          });
    }
    /** Returns the passed object, to test serialization and deserialization. */
    public void echoAllNullableTypes(
        @NonNull AllNullableTypes everythingArg, Reply<AllNullableTypes> callback) {
      BasicMessageChannel<Object> channel =
          new BasicMessageChannel<>(
              binaryMessenger,
              "dev.flutter.pigeon.FlutterIntegrationCoreApi.echoAllNullableTypes",
              getCodec());
      channel.send(
          new ArrayList<Object>(Collections.singletonList(everythingArg)),
          channelReply -> {
            @SuppressWarnings("ConstantConditions")
            AllNullableTypes output = (AllNullableTypes) channelReply;
            callback.reply(output);
          });
    }
    /**
     * Returns passed in arguments of multiple types.
     *
     * <p>Tests multiple-arity FlutterApi handling.
     */
    public void sendMultipleNullableTypes(
        @Nullable Boolean aNullableBoolArg,
        @Nullable Long aNullableIntArg,
        @Nullable String aNullableStringArg,
        Reply<AllNullableTypes> callback) {
      BasicMessageChannel<Object> channel =
          new BasicMessageChannel<>(
              binaryMessenger,
              "dev.flutter.pigeon.FlutterIntegrationCoreApi.sendMultipleNullableTypes",
              getCodec());
      channel.send(
          new ArrayList<Object>(
              Arrays.asList(aNullableBoolArg, aNullableIntArg, aNullableStringArg)),
          channelReply -> {
            @SuppressWarnings("ConstantConditions")
            AllNullableTypes output = (AllNullableTypes) channelReply;
            callback.reply(output);
          });
    }
    /** Returns the passed boolean, to test serialization and deserialization. */
    public void echoBool(@NonNull Boolean aBoolArg, Reply<Boolean> callback) {
      BasicMessageChannel<Object> channel =
          new BasicMessageChannel<>(
              binaryMessenger, "dev.flutter.pigeon.FlutterIntegrationCoreApi.echoBool", getCodec());
      channel.send(
          new ArrayList<Object>(Collections.singletonList(aBoolArg)),
          channelReply -> {
            @SuppressWarnings("ConstantConditions")
            Boolean output = (Boolean) channelReply;
            callback.reply(output);
          });
    }
    /** Returns the passed int, to test serialization and deserialization. */
    public void echoInt(@NonNull Long anIntArg, Reply<Long> callback) {
      BasicMessageChannel<Object> channel =
          new BasicMessageChannel<>(
              binaryMessenger, "dev.flutter.pigeon.FlutterIntegrationCoreApi.echoInt", getCodec());
      channel.send(
          new ArrayList<Object>(Collections.singletonList(anIntArg)),
          channelReply -> {
            @SuppressWarnings("ConstantConditions")
            Long output = channelReply == null ? null : ((Number) channelReply).longValue();
            callback.reply(output);
          });
    }
    /** Returns the passed double, to test serialization and deserialization. */
    public void echoDouble(@NonNull Double aDoubleArg, Reply<Double> callback) {
      BasicMessageChannel<Object> channel =
          new BasicMessageChannel<>(
              binaryMessenger,
              "dev.flutter.pigeon.FlutterIntegrationCoreApi.echoDouble",
              getCodec());
      channel.send(
          new ArrayList<Object>(Collections.singletonList(aDoubleArg)),
          channelReply -> {
            @SuppressWarnings("ConstantConditions")
            Double output = (Double) channelReply;
            callback.reply(output);
          });
    }
    /** Returns the passed string, to test serialization and deserialization. */
    public void echoString(@NonNull String aStringArg, Reply<String> callback) {
      BasicMessageChannel<Object> channel =
          new BasicMessageChannel<>(
              binaryMessenger,
              "dev.flutter.pigeon.FlutterIntegrationCoreApi.echoString",
              getCodec());
      channel.send(
          new ArrayList<Object>(Collections.singletonList(aStringArg)),
          channelReply -> {
            @SuppressWarnings("ConstantConditions")
            String output = (String) channelReply;
            callback.reply(output);
          });
    }
    /** Returns the passed byte list, to test serialization and deserialization. */
    public void echoUint8List(@NonNull byte[] aListArg, Reply<byte[]> callback) {
      BasicMessageChannel<Object> channel =
          new BasicMessageChannel<>(
              binaryMessenger,
              "dev.flutter.pigeon.FlutterIntegrationCoreApi.echoUint8List",
              getCodec());
      channel.send(
          new ArrayList<Object>(Collections.singletonList(aListArg)),
          channelReply -> {
            @SuppressWarnings("ConstantConditions")
            byte[] output = (byte[]) channelReply;
            callback.reply(output);
          });
    }
    /** Returns the passed list, to test serialization and deserialization. */
    public void echoList(@NonNull List<Object> aListArg, Reply<List<Object>> callback) {
      BasicMessageChannel<Object> channel =
          new BasicMessageChannel<>(
              binaryMessenger, "dev.flutter.pigeon.FlutterIntegrationCoreApi.echoList", getCodec());
      channel.send(
          new ArrayList<Object>(Collections.singletonList(aListArg)),
          channelReply -> {
            @SuppressWarnings("ConstantConditions")
            List<Object> output = (List<Object>) channelReply;
            callback.reply(output);
          });
    }
    /** Returns the passed map, to test serialization and deserialization. */
    public void echoMap(@NonNull Map<String, Object> aMapArg, Reply<Map<String, Object>> callback) {
      BasicMessageChannel<Object> channel =
          new BasicMessageChannel<>(
              binaryMessenger, "dev.flutter.pigeon.FlutterIntegrationCoreApi.echoMap", getCodec());
      channel.send(
          new ArrayList<Object>(Collections.singletonList(aMapArg)),
          channelReply -> {
            @SuppressWarnings("ConstantConditions")
            Map<String, Object> output = (Map<String, Object>) channelReply;
            callback.reply(output);
          });
    }
    /** Returns the passed boolean, to test serialization and deserialization. */
    public void echoNullableBool(@Nullable Boolean aBoolArg, Reply<Boolean> callback) {
      BasicMessageChannel<Object> channel =
          new BasicMessageChannel<>(
              binaryMessenger,
              "dev.flutter.pigeon.FlutterIntegrationCoreApi.echoNullableBool",
              getCodec());
      channel.send(
          new ArrayList<Object>(Collections.singletonList(aBoolArg)),
          channelReply -> {
            @SuppressWarnings("ConstantConditions")
            Boolean output = (Boolean) channelReply;
            callback.reply(output);
          });
    }
    /** Returns the passed int, to test serialization and deserialization. */
    public void echoNullableInt(@Nullable Long anIntArg, Reply<Long> callback) {
      BasicMessageChannel<Object> channel =
          new BasicMessageChannel<>(
              binaryMessenger,
              "dev.flutter.pigeon.FlutterIntegrationCoreApi.echoNullableInt",
              getCodec());
      channel.send(
          new ArrayList<Object>(Collections.singletonList(anIntArg)),
          channelReply -> {
            @SuppressWarnings("ConstantConditions")
            Long output = channelReply == null ? null : ((Number) channelReply).longValue();
            callback.reply(output);
          });
    }
    /** Returns the passed double, to test serialization and deserialization. */
    public void echoNullableDouble(@Nullable Double aDoubleArg, Reply<Double> callback) {
      BasicMessageChannel<Object> channel =
          new BasicMessageChannel<>(
              binaryMessenger,
              "dev.flutter.pigeon.FlutterIntegrationCoreApi.echoNullableDouble",
              getCodec());
      channel.send(
          new ArrayList<Object>(Collections.singletonList(aDoubleArg)),
          channelReply -> {
            @SuppressWarnings("ConstantConditions")
            Double output = (Double) channelReply;
            callback.reply(output);
          });
    }
    /** Returns the passed string, to test serialization and deserialization. */
    public void echoNullableString(@Nullable String aStringArg, Reply<String> callback) {
      BasicMessageChannel<Object> channel =
          new BasicMessageChannel<>(
              binaryMessenger,
              "dev.flutter.pigeon.FlutterIntegrationCoreApi.echoNullableString",
              getCodec());
      channel.send(
          new ArrayList<Object>(Collections.singletonList(aStringArg)),
          channelReply -> {
            @SuppressWarnings("ConstantConditions")
            String output = (String) channelReply;
            callback.reply(output);
          });
    }
    /** Returns the passed byte list, to test serialization and deserialization. */
    public void echoNullableUint8List(@Nullable byte[] aListArg, Reply<byte[]> callback) {
      BasicMessageChannel<Object> channel =
          new BasicMessageChannel<>(
              binaryMessenger,
              "dev.flutter.pigeon.FlutterIntegrationCoreApi.echoNullableUint8List",
              getCodec());
      channel.send(
          new ArrayList<Object>(Collections.singletonList(aListArg)),
          channelReply -> {
            @SuppressWarnings("ConstantConditions")
            byte[] output = (byte[]) channelReply;
            callback.reply(output);
          });
    }
    /** Returns the passed list, to test serialization and deserialization. */
    public void echoNullableList(@Nullable List<Object> aListArg, Reply<List<Object>> callback) {
      BasicMessageChannel<Object> channel =
          new BasicMessageChannel<>(
              binaryMessenger,
              "dev.flutter.pigeon.FlutterIntegrationCoreApi.echoNullableList",
              getCodec());
      channel.send(
          new ArrayList<Object>(Collections.singletonList(aListArg)),
          channelReply -> {
            @SuppressWarnings("ConstantConditions")
            List<Object> output = (List<Object>) channelReply;
            callback.reply(output);
          });
    }
    /** Returns the passed map, to test serialization and deserialization. */
    public void echoNullableMap(
        @Nullable Map<String, Object> aMapArg, Reply<Map<String, Object>> callback) {
      BasicMessageChannel<Object> channel =
          new BasicMessageChannel<>(
              binaryMessenger,
              "dev.flutter.pigeon.FlutterIntegrationCoreApi.echoNullableMap",
              getCodec());
      channel.send(
          new ArrayList<Object>(Collections.singletonList(aMapArg)),
          channelReply -> {
            @SuppressWarnings("ConstantConditions")
            Map<String, Object> output = (Map<String, Object>) channelReply;
            callback.reply(output);
          });
    }
  }
  /**
   * An API that can be implemented for minimal, compile-only tests.
   *
   * <p>Generated interface from Pigeon that represents a handler of messages from Flutter.
   */
  public interface HostTrivialApi {

    void noop();

    /** The codec used by HostTrivialApi. */
    static MessageCodec<Object> getCodec() {
      return new StandardMessageCodec();
    }
    /** Sets up an instance of `HostTrivialApi` to handle messages through the `binaryMessenger`. */
    static void setup(BinaryMessenger binaryMessenger, HostTrivialApi api) {
      {
        BasicMessageChannel<Object> channel =
            new BasicMessageChannel<>(
                binaryMessenger, "dev.flutter.pigeon.HostTrivialApi.noop", getCodec());
        if (api != null) {
          channel.setMessageHandler(
              (message, reply) -> {
                ArrayList wrapped = new ArrayList<>();
                try {
                  api.noop();
                  wrapped.add(0, null);
                } catch (Error | RuntimeException exception) {
                  ArrayList<Object> wrappedError = wrapError(exception);
                  wrapped = wrappedError;
                }
                reply.reply(wrapped);
              });
        } else {
          channel.setMessageHandler(null);
        }
      }
    }
  }
}
