// 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.0), 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);
        }
      }
    }
  }
}
