// WARNING: This file is machine generated by fidlgen.

library fidl_test_name_async;

import 'dart:async' as $async;
import 'dart:core' hide Set;
import 'dart:developer';
import 'dart:typed_data';

import 'package:fidl/fidl.dart' as $fidl;
import 'package:meta/meta.dart';
import 'package:zircon/zircon.dart' as $zx;

// ignore_for_file: always_specify_types
// ignore_for_file: avoid_positional_boolean_parameters
// ignore_for_file: avoid_returning_null
// ignore_for_file: cascade_invocations
// ignore_for_file: constant_identifier_names
// ignore_for_file: one_member_abstracts
// ignore_for_file: prefer_constructors_over_static_methods
// ignore_for_file: prefer_single_quotes
// ignore_for_file: public_member_api_docs
// ignore_for_file: unused_import
// ignore_for_file: unused_local_variable
// ignore_for_file: non_constant_identifier_names
// ignore_for_file: library_prefixes
// ignore_for_file: prefer_typing_uninitialized_variables
// ignore_for_file: avoid_js_rounded_ints
// ignore_for_file: unnecessary_parenthesis
// ignore_for_file: always_put_required_named_parameters_first
// ignore_for_file: prefer_generic_function_type_aliases
// ignore_for_file: prefer_equal_for_default_values
// ignore_for_file: avoid_catches_without_on_clauses
// ignore_for_file: unused_shown_name
// ignore_for_file: unnecessary_lambdas
// ignore_for_file: comment_references
// ignore_for_file: avoid_unused_constructor_parameters

enum OlderSimpleUnionTag {
  $unknown,
  i, // 0x3d32b1d7
  f, // 0x5136cf7e
}

const Map<int, OlderSimpleUnionTag> _OlderSimpleUnionTag_map = {
  1026732503: OlderSimpleUnionTag.i,
  1362546558: OlderSimpleUnionTag.f,
};

class OlderSimpleUnion extends $fidl.XUnion {
  const OlderSimpleUnion.withI(int value)
      : _ordinal = 1026732503,
        _data = value;

  const OlderSimpleUnion.withF(double value)
      : _ordinal = 1362546558,
        _data = value;

  OlderSimpleUnion._(int ordinal, Object data)
      : _ordinal = ordinal,
        _data = data;

  final int _ordinal;
  final _data;

  OlderSimpleUnionTag get $tag {
    final OlderSimpleUnionTag $rawtag = _OlderSimpleUnionTag_map[_ordinal];
    return $rawtag == null ? OlderSimpleUnionTag.$unknown : $rawtag;
  }

  int get i {
    if (_ordinal != 1026732503) {
      return null;
    }
    return _data;
  }

  double get f {
    if (_ordinal != 1362546558) {
      return null;
    }
    return _data;
  }

  @override
  String toString() {
    switch (_ordinal) {
      case 1026732503:
        return 'OlderSimpleUnion.i($i)';
      case 1362546558:
        return 'OlderSimpleUnion.f($f)';
      default:
        return 'OlderSimpleUnion.<UNKNOWN>';
    }
  }

  @override
  int get $ordinal => _ordinal;

  @override
  Object get $data => _data;

  static OlderSimpleUnion _ctor(int ordinal, Object data) {
    return OlderSimpleUnion._(ordinal, data);
  }
}

// See FIDL-308:
// ignore: recursive_compile_time_constant
const $fidl.XUnionType<OlderSimpleUnion> kOlderSimpleUnion_Type =
    $fidl.XUnionType<OlderSimpleUnion>(
  inlineSizeOld: 24,
  inlineSizeV1: 24,
  members: <int, $fidl.FidlType>{
    1026732503: $fidl.Int64Type(),
    1362546558: $fidl.Float32Type(),
  },
  ctor: OlderSimpleUnion._ctor,
  nullable: false,
  flexible: true,
);
// See FIDL-308:
// ignore: recursive_compile_time_constant
const $fidl.XUnionType<OlderSimpleUnion> kOlderSimpleUnion_OptType =
    $fidl.XUnionType<OlderSimpleUnion>(
  inlineSizeOld: 24,
  inlineSizeV1: 24,
  members: <int, $fidl.FidlType>{
    1026732503: $fidl.Int64Type(),
    1362546558: $fidl.Float32Type(),
  },
  ctor: OlderSimpleUnion._ctor,
  nullable: true,
  flexible: true,
);

enum NewerSimpleUnionTag {
  $unknown,
  i, // 0x295cbfde
  s, // 0x1c3b9247
  v, // 0x6c38b28f
}

const Map<int, NewerSimpleUnionTag> _NewerSimpleUnionTag_map = {
  693944286: NewerSimpleUnionTag.i,
  473666119: NewerSimpleUnionTag.s,
  1815655055: NewerSimpleUnionTag.v,
};

class NewerSimpleUnion extends $fidl.XUnion {
  const NewerSimpleUnion.withI(int value)
      : _ordinal = 693944286,
        _data = value;

  const NewerSimpleUnion.withS(String value)
      : _ordinal = 473666119,
        _data = value;

  const NewerSimpleUnion.withV(List<String> value)
      : _ordinal = 1815655055,
        _data = value;

  NewerSimpleUnion._(int ordinal, Object data)
      : _ordinal = ordinal,
        _data = data;

  final int _ordinal;
  final _data;

  NewerSimpleUnionTag get $tag {
    final NewerSimpleUnionTag $rawtag = _NewerSimpleUnionTag_map[_ordinal];
    return $rawtag == null ? NewerSimpleUnionTag.$unknown : $rawtag;
  }

  int get i {
    if (_ordinal != 693944286) {
      return null;
    }
    return _data;
  }

  String get s {
    if (_ordinal != 473666119) {
      return null;
    }
    return _data;
  }

  List<String> get v {
    if (_ordinal != 1815655055) {
      return null;
    }
    return _data;
  }

  @override
  String toString() {
    switch (_ordinal) {
      case 693944286:
        return 'NewerSimpleUnion.i($i)';
      case 473666119:
        return 'NewerSimpleUnion.s($s)';
      case 1815655055:
        return 'NewerSimpleUnion.v($v)';
      default:
        return 'NewerSimpleUnion.<UNKNOWN>';
    }
  }

  @override
  int get $ordinal => _ordinal;

  @override
  Object get $data => _data;

  static NewerSimpleUnion _ctor(int ordinal, Object data) {
    return NewerSimpleUnion._(ordinal, data);
  }
}

// See FIDL-308:
// ignore: recursive_compile_time_constant
const $fidl.XUnionType<NewerSimpleUnion> kNewerSimpleUnion_Type =
    $fidl.XUnionType<NewerSimpleUnion>(
  inlineSizeOld: 24,
  inlineSizeV1: 24,
  members: <int, $fidl.FidlType>{
    693944286: $fidl.Int64Type(),
    473666119: $fidl.StringType(maybeElementCount: null, nullable: false),
    1815655055: $fidl.VectorType<List<String>>(
        element: $fidl.StringType(maybeElementCount: null, nullable: false),
        maybeElementCount: null,
        nullable: false),
  },
  ctor: NewerSimpleUnion._ctor,
  nullable: false,
  flexible: true,
);
// See FIDL-308:
// ignore: recursive_compile_time_constant
const $fidl.XUnionType<NewerSimpleUnion> kNewerSimpleUnion_OptType =
    $fidl.XUnionType<NewerSimpleUnion>(
  inlineSizeOld: 24,
  inlineSizeV1: 24,
  members: <int, $fidl.FidlType>{
    693944286: $fidl.Int64Type(),
    473666119: $fidl.StringType(maybeElementCount: null, nullable: false),
    1815655055: $fidl.VectorType<List<String>>(
        element: $fidl.StringType(maybeElementCount: null, nullable: false),
        maybeElementCount: null,
        nullable: false),
  },
  ctor: NewerSimpleUnion._ctor,
  nullable: true,
  flexible: true,
);

enum StrictSimpleXUnionTag {
  i, // 0x6e5ea87c
  f, // 0x32f96c97
  s, // 0x32b329f7
}

const Map<int, StrictSimpleXUnionTag> _StrictSimpleXUnionTag_map = {
  1851697276: StrictSimpleXUnionTag.i,
  855207063: StrictSimpleXUnionTag.f,
  850602487: StrictSimpleXUnionTag.s,
};

class StrictSimpleXUnion extends $fidl.XUnion {
  const StrictSimpleXUnion.withI(int value)
      : _ordinal = 1851697276,
        _data = value;

  const StrictSimpleXUnion.withF(double value)
      : _ordinal = 855207063,
        _data = value;

  const StrictSimpleXUnion.withS(String value)
      : _ordinal = 850602487,
        _data = value;

  StrictSimpleXUnion._(int ordinal, Object data)
      : _ordinal = ordinal,
        _data = data;

  final int _ordinal;
  final _data;

  StrictSimpleXUnionTag get $tag => _StrictSimpleXUnionTag_map[_ordinal];

  int get i {
    if (_ordinal != 1851697276) {
      return null;
    }
    return _data;
  }

  double get f {
    if (_ordinal != 855207063) {
      return null;
    }
    return _data;
  }

  String get s {
    if (_ordinal != 850602487) {
      return null;
    }
    return _data;
  }

  @override
  String toString() {
    switch (_ordinal) {
      case 1851697276:
        return 'StrictSimpleXUnion.i($i)';
      case 855207063:
        return 'StrictSimpleXUnion.f($f)';
      case 850602487:
        return 'StrictSimpleXUnion.s($s)';
      default:
        return null;
    }
  }

  @override
  int get $ordinal => _ordinal;

  @override
  Object get $data => _data;

  static StrictSimpleXUnion _ctor(int ordinal, Object data) {
    return StrictSimpleXUnion._(ordinal, data);
  }
}

// See FIDL-308:
// ignore: recursive_compile_time_constant
const $fidl.XUnionType<StrictSimpleXUnion> kStrictSimpleXUnion_Type =
    $fidl.XUnionType<StrictSimpleXUnion>(
  inlineSizeOld: 24,
  inlineSizeV1: 24,
  members: <int, $fidl.FidlType>{
    1851697276: $fidl.Int32Type(),
    855207063: $fidl.Float32Type(),
    850602487: $fidl.StringType(maybeElementCount: null, nullable: false),
  },
  ctor: StrictSimpleXUnion._ctor,
  nullable: false,
  flexible: false,
);
// See FIDL-308:
// ignore: recursive_compile_time_constant
const $fidl.XUnionType<StrictSimpleXUnion> kStrictSimpleXUnion_OptType =
    $fidl.XUnionType<StrictSimpleXUnion>(
  inlineSizeOld: 24,
  inlineSizeV1: 24,
  members: <int, $fidl.FidlType>{
    1851697276: $fidl.Int32Type(),
    855207063: $fidl.Float32Type(),
    850602487: $fidl.StringType(maybeElementCount: null, nullable: false),
  },
  ctor: StrictSimpleXUnion._ctor,
  nullable: true,
  flexible: false,
);

enum XUnionContainingEmptyStructTag {
  $unknown,
  empty, // 0x1952d1d5
}

const Map<int, XUnionContainingEmptyStructTag>
    _XUnionContainingEmptyStructTag_map = {
  424858069: XUnionContainingEmptyStructTag.empty,
};

class XUnionContainingEmptyStruct extends $fidl.XUnion {
  const XUnionContainingEmptyStruct.withEmpty(Empty value)
      : _ordinal = 424858069,
        _data = value;

  XUnionContainingEmptyStruct._(int ordinal, Object data)
      : _ordinal = ordinal,
        _data = data;

  final int _ordinal;
  final _data;

  XUnionContainingEmptyStructTag get $tag {
    final XUnionContainingEmptyStructTag $rawtag =
        _XUnionContainingEmptyStructTag_map[_ordinal];
    return $rawtag == null ? XUnionContainingEmptyStructTag.$unknown : $rawtag;
  }

  Empty get empty {
    if (_ordinal != 424858069) {
      return null;
    }
    return _data;
  }

  @override
  String toString() {
    switch (_ordinal) {
      case 424858069:
        return 'XUnionContainingEmptyStruct.empty($empty)';
      default:
        return 'XUnionContainingEmptyStruct.<UNKNOWN>';
    }
  }

  @override
  int get $ordinal => _ordinal;

  @override
  Object get $data => _data;

  static XUnionContainingEmptyStruct _ctor(int ordinal, Object data) {
    return XUnionContainingEmptyStruct._(ordinal, data);
  }
}

// See FIDL-308:
// ignore: recursive_compile_time_constant
const $fidl.XUnionType<XUnionContainingEmptyStruct>
    kXUnionContainingEmptyStruct_Type =
    $fidl.XUnionType<XUnionContainingEmptyStruct>(
  inlineSizeOld: 24,
  inlineSizeV1: 24,
  members: <int, $fidl.FidlType>{
    424858069: kEmpty_Type,
  },
  ctor: XUnionContainingEmptyStruct._ctor,
  nullable: false,
  flexible: true,
);
// See FIDL-308:
// ignore: recursive_compile_time_constant
const $fidl.XUnionType<XUnionContainingEmptyStruct>
    kXUnionContainingEmptyStruct_OptType =
    $fidl.XUnionType<XUnionContainingEmptyStruct>(
  inlineSizeOld: 24,
  inlineSizeV1: 24,
  members: <int, $fidl.FidlType>{
    424858069: kEmpty_Type,
  },
  ctor: XUnionContainingEmptyStruct._ctor,
  nullable: true,
  flexible: true,
);

enum StrictBoundedXUnionTag {
  v, // 0x78ac4468
}

const Map<int, StrictBoundedXUnionTag> _StrictBoundedXUnionTag_map = {
  2024555624: StrictBoundedXUnionTag.v,
};

class StrictBoundedXUnion extends $fidl.XUnion {
  const StrictBoundedXUnion.withV(Uint8List value)
      : _ordinal = 2024555624,
        _data = value;

  StrictBoundedXUnion._(int ordinal, Object data)
      : _ordinal = ordinal,
        _data = data;

  final int _ordinal;
  final _data;

  StrictBoundedXUnionTag get $tag => _StrictBoundedXUnionTag_map[_ordinal];

  Uint8List get v {
    if (_ordinal != 2024555624) {
      return null;
    }
    return _data;
  }

  @override
  String toString() {
    switch (_ordinal) {
      case 2024555624:
        return 'StrictBoundedXUnion.v($v)';
      default:
        return null;
    }
  }

  @override
  int get $ordinal => _ordinal;

  @override
  Object get $data => _data;

  static StrictBoundedXUnion _ctor(int ordinal, Object data) {
    return StrictBoundedXUnion._(ordinal, data);
  }
}

// See FIDL-308:
// ignore: recursive_compile_time_constant
const $fidl.XUnionType<StrictBoundedXUnion> kStrictBoundedXUnion_Type =
    $fidl.XUnionType<StrictBoundedXUnion>(
  inlineSizeOld: 24,
  inlineSizeV1: 24,
  members: <int, $fidl.FidlType>{
    2024555624: $fidl.VectorType<Uint8List>(
        element: $fidl.Uint8Type(), maybeElementCount: 10, nullable: false),
  },
  ctor: StrictBoundedXUnion._ctor,
  nullable: false,
  flexible: false,
);
// See FIDL-308:
// ignore: recursive_compile_time_constant
const $fidl.XUnionType<StrictBoundedXUnion> kStrictBoundedXUnion_OptType =
    $fidl.XUnionType<StrictBoundedXUnion>(
  inlineSizeOld: 24,
  inlineSizeV1: 24,
  members: <int, $fidl.FidlType>{
    2024555624: $fidl.VectorType<Uint8List>(
        element: $fidl.Uint8Type(), maybeElementCount: 10, nullable: false),
  },
  ctor: StrictBoundedXUnion._ctor,
  nullable: true,
  flexible: false,
);

enum ExplicitXUnionTag {
  $unknown,
  i, // 0x1
  f, // 0x4
}

const Map<int, ExplicitXUnionTag> _ExplicitXUnionTag_map = {
  1: ExplicitXUnionTag.i,
  4: ExplicitXUnionTag.f,
};

class ExplicitXUnion extends $fidl.XUnion {
  const ExplicitXUnion.withI(int value)
      : _ordinal = 1,
        _data = value;

  const ExplicitXUnion.withF(double value)
      : _ordinal = 4,
        _data = value;

  ExplicitXUnion._(int ordinal, Object data)
      : _ordinal = ordinal,
        _data = data;

  final int _ordinal;
  final _data;

  ExplicitXUnionTag get $tag {
    final ExplicitXUnionTag $rawtag = _ExplicitXUnionTag_map[_ordinal];
    return $rawtag == null ? ExplicitXUnionTag.$unknown : $rawtag;
  }

  int get i {
    if (_ordinal != 1) {
      return null;
    }
    return _data;
  }

  double get f {
    if (_ordinal != 4) {
      return null;
    }
    return _data;
  }

  @override
  String toString() {
    switch (_ordinal) {
      case 1:
        return 'ExplicitXUnion.i($i)';
      case 4:
        return 'ExplicitXUnion.f($f)';
      default:
        return 'ExplicitXUnion.<UNKNOWN>';
    }
  }

  @override
  int get $ordinal => _ordinal;

  @override
  Object get $data => _data;

  static ExplicitXUnion _ctor(int ordinal, Object data) {
    return ExplicitXUnion._(ordinal, data);
  }
}

// See FIDL-308:
// ignore: recursive_compile_time_constant
const $fidl.XUnionType<ExplicitXUnion> kExplicitXUnion_Type =
    $fidl.XUnionType<ExplicitXUnion>(
  inlineSizeOld: 24,
  inlineSizeV1: 24,
  members: <int, $fidl.FidlType>{
    1: $fidl.Int64Type(),
    4: $fidl.Float32Type(),
  },
  ctor: ExplicitXUnion._ctor,
  nullable: false,
  flexible: true,
);
// See FIDL-308:
// ignore: recursive_compile_time_constant
const $fidl.XUnionType<ExplicitXUnion> kExplicitXUnion_OptType =
    $fidl.XUnionType<ExplicitXUnion>(
  inlineSizeOld: 24,
  inlineSizeV1: 24,
  members: <int, $fidl.FidlType>{
    1: $fidl.Int64Type(),
    4: $fidl.Float32Type(),
  },
  ctor: ExplicitXUnion._ctor,
  nullable: true,
  flexible: true,
);

class Empty extends $fidl.Struct {
  const Empty({
    this.reserved: 0x0,
  });
  Empty.clone(
    Empty $orig, {
    int reserved,
  }) : this(
          reserved: reserved ?? $orig.reserved,
        );

  Empty._(List<Object> argv) : reserved = argv[0];
  final int reserved;

  @override
  List<Object> get $fields {
    return <Object>[
      reserved,
    ];
  }

  @override
  String toString() {
    // ignore: prefer_interpolation_to_compose_strings
    return r'Empty' r'(reserved: ' + reserved.toString() + r')';
  }

  static Empty _ctor(List<Object> argv) => Empty._(argv);
}

// See FIDL-308:
// ignore: recursive_compile_time_constant
const $fidl.StructType<Empty> kEmpty_Type = $fidl.StructType<Empty>(
  inlineSizeOld: 1,
  inlineSizeV1: 1,
  members: <$fidl.MemberType>[
    $fidl.MemberType<int>(type: $fidl.Uint8Type(), offsetOld: 0, offsetV1: 0),
  ],
  ctor: Empty._ctor,
);

class StructWithNullableXUnion extends $fidl.Struct {
  const StructWithNullableXUnion({
    this.x1,
  });
  StructWithNullableXUnion.clone(
    StructWithNullableXUnion $orig, {
    OlderSimpleUnion x1,
  }) : this(
          x1: x1 ?? $orig.x1,
        );

  StructWithNullableXUnion.cloneWithout(
    StructWithNullableXUnion $orig, {
    bool x1,
  }) : this(
          x1: x1 ? null : $orig.x1,
        );

  StructWithNullableXUnion._(List<Object> argv) : x1 = argv[0];
  final OlderSimpleUnion x1;

  @override
  List<Object> get $fields {
    return <Object>[
      x1,
    ];
  }

  @override
  String toString() {
    // ignore: prefer_interpolation_to_compose_strings
    return r'StructWithNullableXUnion' r'(x1: ' + x1.toString() + r')';
  }

  static StructWithNullableXUnion _ctor(List<Object> argv) =>
      StructWithNullableXUnion._(argv);
}

// See FIDL-308:
// ignore: recursive_compile_time_constant
const $fidl.StructType<StructWithNullableXUnion>
    kStructWithNullableXUnion_Type = $fidl.StructType<StructWithNullableXUnion>(
  inlineSizeOld: 24,
  inlineSizeV1: 24,
  members: <$fidl.MemberType>[
    $fidl.MemberType<OlderSimpleUnion>(
        type: kOlderSimpleUnion_OptType, offsetOld: 0, offsetV1: 0),
  ],
  ctor: StructWithNullableXUnion._ctor,
);

// ignore: unused_element, avoid_private_typedef_functions
typedef _VoidCallback = void Function();

// strictXUnionHenceResponseMayBeStackAllocated: () -> (StrictBoundedXUnion xu)
const int _kTestProtocol_StrictXUnionHenceResponseMayBeStackAllocated_Ordinal =
    0x71a1b4b700000000;
const int
    _kTestProtocol_StrictXUnionHenceResponseMayBeStackAllocated_GenOrdinal =
    0x2b158c786064d0de;
const $fidl.MethodType
    _kTestProtocol_StrictXUnionHenceResponseMayBeStackAllocated_Type =
    $fidl.MethodType(
  request: null,
  response: <$fidl.MemberType>[
    $fidl.MemberType<StrictBoundedXUnion>(
        type: kStrictBoundedXUnion_Type, offsetOld: 16, offsetV1: 16),
  ],
  name: r"TestProtocol.StrictXUnionHenceResponseMayBeStackAllocated",
);
// flexibleXUnionHenceResponseMustBeHeapAllocated: () -> (OlderSimpleUnion xu)
const int
    _kTestProtocol_FlexibleXUnionHenceResponseMustBeHeapAllocated_Ordinal =
    0x3959ff0900000000;
const int
    _kTestProtocol_FlexibleXUnionHenceResponseMustBeHeapAllocated_GenOrdinal =
    0x5ecf85aadd137696;
const $fidl.MethodType
    _kTestProtocol_FlexibleXUnionHenceResponseMustBeHeapAllocated_Type =
    $fidl.MethodType(
  request: null,
  response: <$fidl.MemberType>[
    $fidl.MemberType<OlderSimpleUnion>(
        type: kOlderSimpleUnion_Type, offsetOld: 16, offsetV1: 16),
  ],
  name: r"TestProtocol.FlexibleXUnionHenceResponseMustBeHeapAllocated",
);

abstract class TestProtocol extends $fidl.Service {
  static const String $serviceName = null;
  @override
  $fidl.ServiceData get $serviceData => TestProtocolData();
  $async.Future<StrictBoundedXUnion>
      strictXUnionHenceResponseMayBeStackAllocated();
  $async.Future<OlderSimpleUnion>
      flexibleXUnionHenceResponseMustBeHeapAllocated();
}

class TestProtocolData implements $fidl.ServiceData<TestProtocol> {
  const TestProtocolData();

  @override
  String getName() {
    return TestProtocol.$serviceName;
  }

  @override
  $fidl.AsyncBinding getBinding() {
    return TestProtocolBinding();
  }
}

class TestProtocolProxy extends $fidl.AsyncProxy<TestProtocol>
    implements TestProtocol {
  TestProtocolProxy()
      : super($fidl.AsyncProxyController<TestProtocol>(
            $serviceName: null, $interfaceName: r'TestProtocol')) {
    ctrl.onResponse = _handleResponse;
  }

  @override
  $fidl.ServiceData get $serviceData => TestProtocolData();

  void _handleEvent($fidl.Message $message) {
    final $fidl.Decoder $decoder = $fidl.Decoder($message);
    switch ($message.ordinal) {
      default:
        ctrl.proxyError(
            $fidl.FidlError('Unexpected message ordinal: ${$message.ordinal}'));
        ctrl.close();
        break;
    }
  }

  void _handleResponse($fidl.Message $message) {
    final int $txid = $message.txid;
    if ($txid == 0) {
      _handleEvent($message);
      return;
    }
    final $async.Completer $completer = ctrl.getCompleter($txid);
    if ($completer == null) {
      $message.closeHandles();
      return;
    }
    final $fidl.Decoder $decoder = $fidl.Decoder($message);
    switch ($message.ordinal) {
      case _kTestProtocol_StrictXUnionHenceResponseMayBeStackAllocated_Ordinal:
      case _kTestProtocol_StrictXUnionHenceResponseMayBeStackAllocated_GenOrdinal:
        final String _name =
            _kTestProtocol_StrictXUnionHenceResponseMayBeStackAllocated_Type
                .name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kTestProtocol_StrictXUnionHenceResponseMayBeStackAllocated_Type
                  .response;
          $decoder.claimMemory(40);
          // ignore: prefer_const_declarations
          final $response = $types[0].decode($decoder, 0);

          $completer.complete($response);

          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          ctrl.proxyError($fidl.FidlError(
              'Exception handling method response $_name: $_e'));
          ctrl.close();
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      case _kTestProtocol_FlexibleXUnionHenceResponseMustBeHeapAllocated_Ordinal:
      case _kTestProtocol_FlexibleXUnionHenceResponseMustBeHeapAllocated_GenOrdinal:
        final String _name =
            _kTestProtocol_FlexibleXUnionHenceResponseMustBeHeapAllocated_Type
                .name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kTestProtocol_FlexibleXUnionHenceResponseMustBeHeapAllocated_Type
                  .response;
          $decoder.claimMemory(40);
          // ignore: prefer_const_declarations
          final $response = $types[0].decode($decoder, 0);

          $completer.complete($response);

          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          ctrl.proxyError($fidl.FidlError(
              'Exception handling method response $_name: $_e'));
          ctrl.close();
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      default:
        ctrl.proxyError(
            $fidl.FidlError('Unexpected message ordinal: ${$message.ordinal}'));
        ctrl.close();
        break;
    }
  }

  @override
  $async.Future<StrictBoundedXUnion>
      strictXUnionHenceResponseMayBeStackAllocated() async {
    if (!ctrl.isBound) {
      return $async.Future.error(
          $fidl.FidlStateException('Proxy<${ctrl.$interfaceName}> is closed.'),
          StackTrace.current);
    }

    final $fidl.Encoder $encoder = $fidl.Encoder();
    $encoder.encodeMessageHeader(
        _kTestProtocol_StrictXUnionHenceResponseMayBeStackAllocated_Ordinal, 0);
    final $completer = $async.Completer<StrictBoundedXUnion>();
    ctrl.sendMessageWithResponse($encoder.message, $completer);
    return $completer.future;
  }

  @override
  $async.Future<OlderSimpleUnion>
      flexibleXUnionHenceResponseMustBeHeapAllocated() async {
    if (!ctrl.isBound) {
      return $async.Future.error(
          $fidl.FidlStateException('Proxy<${ctrl.$interfaceName}> is closed.'),
          StackTrace.current);
    }

    final $fidl.Encoder $encoder = $fidl.Encoder();
    $encoder.encodeMessageHeader(
        _kTestProtocol_FlexibleXUnionHenceResponseMustBeHeapAllocated_Ordinal,
        0);
    final $completer = $async.Completer<OlderSimpleUnion>();
    ctrl.sendMessageWithResponse($encoder.message, $completer);
    return $completer.future;
  }
}

class TestProtocolBinding extends $fidl.AsyncBinding<TestProtocol> {
  TestProtocolBinding() : super(r"TestProtocol");

  @override
  void handleMessage($fidl.Message $message, $fidl.MessageSink $respond) {
    final $fidl.Decoder $decoder = $fidl.Decoder($message);
    switch ($message.ordinal) {
      case _kTestProtocol_StrictXUnionHenceResponseMayBeStackAllocated_Ordinal:
      case _kTestProtocol_StrictXUnionHenceResponseMayBeStackAllocated_GenOrdinal:
        final String _name =
            _kTestProtocol_StrictXUnionHenceResponseMayBeStackAllocated_Type
                .name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kTestProtocol_StrictXUnionHenceResponseMayBeStackAllocated_Type
                  .request;
          $decoder.claimMemory(16);
          final $async.Future<StrictBoundedXUnion> $future =
              impl.strictXUnionHenceResponseMayBeStackAllocated();
          $future.then(($response) {
            final $fidl.Encoder $encoder = $fidl.Encoder();
            $encoder.encodeMessageHeader(
                _kTestProtocol_StrictXUnionHenceResponseMayBeStackAllocated_Ordinal,
                $message.txid);
            $encoder.alloc(40 - $fidl.kMessageHeaderSize);
            final List<$fidl.MemberType> $types =
                _kTestProtocol_StrictXUnionHenceResponseMayBeStackAllocated_Type
                    .response;
            $types[0].encode($encoder, $response, 0);
            $respond($encoder.message);
          }, onError: (_e) {
            close();
            print('Exception handling method call $_name: $_e');
          });
          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          close();
          print('Exception handling method call $_name: $_e');
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      case _kTestProtocol_FlexibleXUnionHenceResponseMustBeHeapAllocated_Ordinal:
      case _kTestProtocol_FlexibleXUnionHenceResponseMustBeHeapAllocated_GenOrdinal:
        final String _name =
            _kTestProtocol_FlexibleXUnionHenceResponseMustBeHeapAllocated_Type
                .name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kTestProtocol_FlexibleXUnionHenceResponseMustBeHeapAllocated_Type
                  .request;
          $decoder.claimMemory(16);
          final $async.Future<OlderSimpleUnion> $future =
              impl.flexibleXUnionHenceResponseMustBeHeapAllocated();
          $future.then(($response) {
            final $fidl.Encoder $encoder = $fidl.Encoder();
            $encoder.encodeMessageHeader(
                _kTestProtocol_FlexibleXUnionHenceResponseMustBeHeapAllocated_Ordinal,
                $message.txid);
            $encoder.alloc(40 - $fidl.kMessageHeaderSize);
            final List<$fidl.MemberType> $types =
                _kTestProtocol_FlexibleXUnionHenceResponseMustBeHeapAllocated_Type
                    .response;
            $types[0].encode($encoder, $response, 0);
            $respond($encoder.message);
          }, onError: (_e) {
            close();
            print('Exception handling method call $_name: $_e');
          });
          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          close();
          print('Exception handling method call $_name: $_e');
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      default:
        throw $fidl.FidlError(
            r'Unexpected message name for TestProtocolBinding');
    }
  }
}
