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

    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;
    }

    /** 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 String aString;

      public @NonNull Builder setAString(@NonNull String setterArg) {
        this.aString = 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;
      }

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

    @NonNull
    ArrayList<Object> toList() {
      ArrayList<Object> toListResult = new ArrayList<Object>(11);
      toListResult.add(aBool);
      toListResult.add(anInt);
      toListResult.add(aDouble);
      toListResult.add(aString);
      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);
      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 aString = list.get(3);
      pigeonResult.setAString((String) aString);
      Object aByteArray = list.get(4);
      pigeonResult.setAByteArray((byte[]) aByteArray);
      Object a4ByteArray = list.get(5);
      pigeonResult.setA4ByteArray((int[]) a4ByteArray);
      Object a8ByteArray = list.get(6);
      pigeonResult.setA8ByteArray((long[]) a8ByteArray);
      Object aFloatArray = list.get(7);
      pigeonResult.setAFloatArray((double[]) aFloatArray);
      Object aList = list.get(8);
      pigeonResult.setAList((List<Object>) aList);
      Object aMap = list.get(9);
      pigeonResult.setAMap((Map<Object, Object>) aMap);
      Object anEnum = list.get(10);
      pigeonResult.setAnEnum(anEnum == null ? null : AnEnum.values()[(int) anEnum]);
      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 String aNullableString;

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

    public void setANullableString(@Nullable String setterArg) {
      this.aNullableString = 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;
    }

    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 String aNullableString;

      public @NonNull Builder setANullableString(@Nullable String setterArg) {
        this.aNullableString = 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;
      }

      public @NonNull AllNullableTypes build() {
        AllNullableTypes pigeonReturn = new AllNullableTypes();
        pigeonReturn.setANullableBool(aNullableBool);
        pigeonReturn.setANullableInt(aNullableInt);
        pigeonReturn.setANullableDouble(aNullableDouble);
        pigeonReturn.setANullableString(aNullableString);
        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);
        return pigeonReturn;
      }
    }

    @NonNull
    ArrayList<Object> toList() {
      ArrayList<Object> toListResult = new ArrayList<Object>(14);
      toListResult.add(aNullableBool);
      toListResult.add(aNullableInt);
      toListResult.add(aNullableDouble);
      toListResult.add(aNullableString);
      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);
      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 aNullableString = list.get(3);
      pigeonResult.setANullableString((String) aNullableString);
      Object aNullableByteArray = list.get(4);
      pigeonResult.setANullableByteArray((byte[]) aNullableByteArray);
      Object aNullable4ByteArray = list.get(5);
      pigeonResult.setANullable4ByteArray((int[]) aNullable4ByteArray);
      Object aNullable8ByteArray = list.get(6);
      pigeonResult.setANullable8ByteArray((long[]) aNullable8ByteArray);
      Object aNullableFloatArray = list.get(7);
      pigeonResult.setANullableFloatArray((double[]) aNullableFloatArray);
      Object aNullableList = list.get(8);
      pigeonResult.setANullableList((List<Object>) aNullableList);
      Object aNullableMap = list.get(9);
      pigeonResult.setANullableMap((Map<Object, Object>) aNullableMap);
      Object nullableNestedList = list.get(10);
      pigeonResult.setNullableNestedList((List<List<Boolean>>) nullableNestedList);
      Object nullableMapWithAnnotations = list.get(11);
      pigeonResult.setNullableMapWithAnnotations((Map<String, String>) nullableMapWithAnnotations);
      Object nullableMapWithObject = list.get(12);
      pigeonResult.setNullableMapWithObject((Map<String, Object>) nullableMapWithObject);
      Object aNullableEnum = list.get(13);
      pigeonResult.setANullableEnum(
          aNullableEnum == null ? null : AnEnum.values()[(int) aNullableEnum]);
      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);
        }
      }
    }
  }
}
