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

package com.example.alternate_language_test_plugin;

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

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

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

    private final int index;

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

  /** Generated class from Pigeon that represents data sent in messages. */
  public static 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 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 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 callFlutterEchoString(@NonNull String aString, Result<String> 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.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);
        }
      }
    }
  }

  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 class FlutterIntegrationCoreApi {
    private final BinaryMessenger binaryMessenger;

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

    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(
        @NonNull 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);
        }
      }
    }
  }
}
