// 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 {
  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 => _OlderSimpleUnionTag_map[_ordinal];

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

  @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>(
  encodedSize: 24,
  members: <int, $fidl.FidlType>{
    1026732503: $fidl.Int64Type(),
    1362546558: $fidl.Float32Type(),
  },
  ctor: OlderSimpleUnion._ctor,
);
// See FIDL-308:
// ignore: recursive_compile_time_constant
const $fidl.XUnionType<OlderSimpleUnion> kOlderSimpleUnion_OptType =
    $fidl.XUnionType<OlderSimpleUnion>(
  encodedSize: 24,
  members: <int, $fidl.FidlType>{
    1026732503: $fidl.Int64Type(),
    1362546558: $fidl.Float32Type(),
  },
  ctor: OlderSimpleUnion._ctor,
  nullable: true,
);

enum NewerSimpleUnionTag {
  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 => _NewerSimpleUnionTag_map[_ordinal];

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

  @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>(
  encodedSize: 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,
);
// See FIDL-308:
// ignore: recursive_compile_time_constant
const $fidl.XUnionType<NewerSimpleUnion> kNewerSimpleUnion_OptType =
    $fidl.XUnionType<NewerSimpleUnion>(
  encodedSize: 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,
);

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

enum XUnionContainingEmptyStructTag {
  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 =>
      _XUnionContainingEmptyStructTag_map[_ordinal];

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

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

  @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>(
  encodedSize: 24,
  members: <int, $fidl.FidlType>{
    424858069: kEmpty_Type,
  },
  ctor: XUnionContainingEmptyStruct._ctor,
);
// See FIDL-308:
// ignore: recursive_compile_time_constant
const $fidl.XUnionType<XUnionContainingEmptyStruct>
    kXUnionContainingEmptyStruct_OptType =
    $fidl.XUnionType<XUnionContainingEmptyStruct>(
  encodedSize: 24,
  members: <int, $fidl.FidlType>{
    424858069: kEmpty_Type,
  },
  ctor: XUnionContainingEmptyStruct._ctor,
  nullable: 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>(
  encodedSize: 24,
  members: <int, $fidl.FidlType>{
    2024555624: $fidl.VectorType<Uint8List>(
        element: $fidl.Uint8Type(), maybeElementCount: 10, nullable: false),
  },
  ctor: StrictBoundedXUnion._ctor,
);
// See FIDL-308:
// ignore: recursive_compile_time_constant
const $fidl.XUnionType<StrictBoundedXUnion> kStrictBoundedXUnion_OptType =
    $fidl.XUnionType<StrictBoundedXUnion>(
  encodedSize: 24,
  members: <int, $fidl.FidlType>{
    2024555624: $fidl.VectorType<Uint8List>(
        element: $fidl.Uint8Type(), maybeElementCount: 10, nullable: false),
  },
  ctor: StrictBoundedXUnion._ctor,
  nullable: 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>(
  encodedSize: 1,
  members: <$fidl.MemberType>[
    $fidl.MemberType<int>(type: $fidl.Uint8Type(), offset: 0),
  ],
  ctor: Empty._ctor,
);

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

// strictXUnionHenceResponseMayBeStackAllocated: () -> (StrictBoundedXUnion xu)
const int _kTestProtocol_StrictXUnionHenceResponseMayBeStackAllocated_Ordinal =
    0x71a1b4b700000000;
const $fidl.MethodType
    _kTestProtocol_StrictXUnionHenceResponseMayBeStackAllocated_Type =
    $fidl.MethodType(
  request: null,
  response: <$fidl.MemberType>[
    $fidl.MemberType<StrictBoundedXUnion>(
        type: kStrictBoundedXUnion_Type, offset: 16),
  ],
  name: r"TestProtocol.StrictXUnionHenceResponseMayBeStackAllocated",
);
// flexibleXUnionHenceResponseMustBeHeapAllocated: () -> (OlderSimpleUnion xu)
const int
    _kTestProtocol_FlexibleXUnionHenceResponseMustBeHeapAllocated_Ordinal =
    0x3959ff0900000000;
const $fidl.MethodType
    _kTestProtocol_FlexibleXUnionHenceResponseMustBeHeapAllocated_Type =
    $fidl.MethodType(
  request: null,
  response: <$fidl.MemberType>[
    $fidl.MemberType<OlderSimpleUnion>(
        type: kOlderSimpleUnion_Type, offset: 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:
        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:
        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:
        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:
        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');
    }
  }
}
