// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// WARNING: This file is machine generated by fidlgen.

library fidl_test_name;

import 'dart:async';
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;

// These imports improve deduplication by making uses of {fidl.dart},
// {fidl_async.dart} and {fidl.dart, fidl_async.dart} generate equivalent
// packages. In AOT, the dead code will be removed by tree shaking.
// ignore: unused_import
import 'fidl_async.dart' as $strongly_connect_async;

// 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

class ErrorEnun extends $fidl.Enum {
  factory ErrorEnun(int _v) {
    switch (_v) {
      case 1:
        return errFoo;
      case 2:
        return errBar;
      default:
        return null;
    }
  }
  static const ErrorEnun errFoo = ErrorEnun._(1);
  static const ErrorEnun errBar = ErrorEnun._(2);

  const ErrorEnun._(this.$value);

  @override
  final int $value;

  static const Map<String, ErrorEnun> $valuesMap = {
    r'errFoo': errFoo,
    r'errBar': errBar,
  };

  static const List<ErrorEnun> $values = [
    errFoo,
    errBar,
  ];

  // TODO: remove, see: FIDL-587
  static const List<ErrorEnun> values = ErrorEnun.$values;

  static ErrorEnun $valueOf(String name) => $valuesMap[name];

  @override
  String toString() {
    switch ($value) {
      case 1:
        return r'ErrorEnun.errFoo';
      case 2:
        return r'ErrorEnun.errBar';
      default:
        return null;
    }
  }

  static ErrorEnun _ctor(int v) => ErrorEnun(v);
}

const $fidl.EnumType<ErrorEnun> kErrorEnun_Type =
    $fidl.EnumType<ErrorEnun>(type: $fidl.Uint32Type(), ctor: ErrorEnun._ctor);

enum WithErrorSyntaxErrorAsPrimitiveResultTag {
  response,
  err,
}

class WithErrorSyntaxErrorAsPrimitiveResult extends $fidl.Union {
  const WithErrorSyntaxErrorAsPrimitiveResult.withResponse(
      WithErrorSyntaxErrorAsPrimitiveResponse value)
      : _data = value,
        _tag = WithErrorSyntaxErrorAsPrimitiveResultTag.response;

  const WithErrorSyntaxErrorAsPrimitiveResult.withErr(int value)
      : _data = value,
        _tag = WithErrorSyntaxErrorAsPrimitiveResultTag.err;

  WithErrorSyntaxErrorAsPrimitiveResult._(
      WithErrorSyntaxErrorAsPrimitiveResultTag tag, Object data)
      : _tag = tag,
        _data = data;

  final WithErrorSyntaxErrorAsPrimitiveResultTag _tag;
  final _data;
  WithErrorSyntaxErrorAsPrimitiveResponse get response {
    if (_tag != WithErrorSyntaxErrorAsPrimitiveResultTag.response) {
      return null;
    }
    return _data;
  }

  int get err {
    if (_tag != WithErrorSyntaxErrorAsPrimitiveResultTag.err) {
      return null;
    }
    return _data;
  }

  @override
  String toString() {
    switch (_tag) {
      case WithErrorSyntaxErrorAsPrimitiveResultTag.response:
        return r'WithErrorSyntaxErrorAsPrimitiveResult.response($response)';
      case WithErrorSyntaxErrorAsPrimitiveResultTag.err:
        return r'WithErrorSyntaxErrorAsPrimitiveResult.err($err)';
      default:
        return null;
    }
  }

  WithErrorSyntaxErrorAsPrimitiveResultTag get $tag => _tag;
  // TODO: remove, see: FIDL-587
  WithErrorSyntaxErrorAsPrimitiveResultTag get tag => _tag;

  @override
  int get $index => _tag.index;

  @override
  Object get $data => _data;

  static WithErrorSyntaxErrorAsPrimitiveResult _ctor(int index, Object data) {
    return WithErrorSyntaxErrorAsPrimitiveResult._(
        WithErrorSyntaxErrorAsPrimitiveResultTag.values[index], data);
  }
}

// See FIDL-308:
// ignore: recursive_compile_time_constant
const $fidl.UnionType<WithErrorSyntaxErrorAsPrimitiveResult>
    kWithErrorSyntax_ErrorAsPrimitive_Result_Type =
    $fidl.UnionType<WithErrorSyntaxErrorAsPrimitiveResult>(
  encodedSize: 8,
  members: <$fidl.MemberType>[
    $fidl.MemberType<WithErrorSyntaxErrorAsPrimitiveResponse>(
        type: kWithErrorSyntax_ErrorAsPrimitive_Response_Type, offset: 4),
    $fidl.MemberType<int>(type: $fidl.Uint32Type(), offset: 4),
  ],
  ctor: WithErrorSyntaxErrorAsPrimitiveResult._ctor,
);

enum WithErrorSyntaxErrorAsEnumResultTag {
  response,
  err,
}

class WithErrorSyntaxErrorAsEnumResult extends $fidl.Union {
  const WithErrorSyntaxErrorAsEnumResult.withResponse(
      WithErrorSyntaxErrorAsEnumResponse value)
      : _data = value,
        _tag = WithErrorSyntaxErrorAsEnumResultTag.response;

  const WithErrorSyntaxErrorAsEnumResult.withErr(ErrorEnun value)
      : _data = value,
        _tag = WithErrorSyntaxErrorAsEnumResultTag.err;

  WithErrorSyntaxErrorAsEnumResult._(
      WithErrorSyntaxErrorAsEnumResultTag tag, Object data)
      : _tag = tag,
        _data = data;

  final WithErrorSyntaxErrorAsEnumResultTag _tag;
  final _data;
  WithErrorSyntaxErrorAsEnumResponse get response {
    if (_tag != WithErrorSyntaxErrorAsEnumResultTag.response) {
      return null;
    }
    return _data;
  }

  ErrorEnun get err {
    if (_tag != WithErrorSyntaxErrorAsEnumResultTag.err) {
      return null;
    }
    return _data;
  }

  @override
  String toString() {
    switch (_tag) {
      case WithErrorSyntaxErrorAsEnumResultTag.response:
        return r'WithErrorSyntaxErrorAsEnumResult.response($response)';
      case WithErrorSyntaxErrorAsEnumResultTag.err:
        return r'WithErrorSyntaxErrorAsEnumResult.err($err)';
      default:
        return null;
    }
  }

  WithErrorSyntaxErrorAsEnumResultTag get $tag => _tag;
  // TODO: remove, see: FIDL-587
  WithErrorSyntaxErrorAsEnumResultTag get tag => _tag;

  @override
  int get $index => _tag.index;

  @override
  Object get $data => _data;

  static WithErrorSyntaxErrorAsEnumResult _ctor(int index, Object data) {
    return WithErrorSyntaxErrorAsEnumResult._(
        WithErrorSyntaxErrorAsEnumResultTag.values[index], data);
  }
}

// See FIDL-308:
// ignore: recursive_compile_time_constant
const $fidl.UnionType<WithErrorSyntaxErrorAsEnumResult>
    kWithErrorSyntax_ErrorAsEnum_Result_Type =
    $fidl.UnionType<WithErrorSyntaxErrorAsEnumResult>(
  encodedSize: 8,
  members: <$fidl.MemberType>[
    $fidl.MemberType<WithErrorSyntaxErrorAsEnumResponse>(
        type: kWithErrorSyntax_ErrorAsEnum_Response_Type, offset: 4),
    $fidl.MemberType<ErrorEnun>(type: kErrorEnun_Type, offset: 4),
  ],
  ctor: WithErrorSyntaxErrorAsEnumResult._ctor,
);

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

  WithErrorSyntaxErrorAsPrimitiveResponse._(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'WithErrorSyntaxErrorAsPrimitiveResponse' r'(reserved: ' +
        reserved.toString() +
        r')';
  }

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

// See FIDL-308:
// ignore: recursive_compile_time_constant
const $fidl.StructType<WithErrorSyntaxErrorAsPrimitiveResponse>
    kWithErrorSyntax_ErrorAsPrimitive_Response_Type =
    $fidl.StructType<WithErrorSyntaxErrorAsPrimitiveResponse>(
  encodedSize: 1,
  members: <$fidl.MemberType>[
    $fidl.MemberType<int>(type: $fidl.Uint8Type(), offset: 0),
  ],
  ctor: WithErrorSyntaxErrorAsPrimitiveResponse._ctor,
);

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

  WithErrorSyntaxErrorAsEnumResponse._(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'WithErrorSyntaxErrorAsEnumResponse' r'(reserved: ' +
        reserved.toString() +
        r')';
  }

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

// See FIDL-308:
// ignore: recursive_compile_time_constant
const $fidl.StructType<WithErrorSyntaxErrorAsEnumResponse>
    kWithErrorSyntax_ErrorAsEnum_Response_Type =
    $fidl.StructType<WithErrorSyntaxErrorAsEnumResponse>(
  encodedSize: 1,
  members: <$fidl.MemberType>[
    $fidl.MemberType<int>(type: $fidl.Uint8Type(), offset: 0),
  ],
  ctor: WithErrorSyntaxErrorAsEnumResponse._ctor,
);

abstract class WithAndWithoutRequestResponse {
  static const String $serviceName = null;
  void noRequestNoResponse();
  void noRequestEmptyResponse(void callback());
  void noRequestWithResponse(void callback(String ret));
  void withRequestNoResponse(String arg);
  void withRequestEmptyResponse(String arg, void callback());
  void withRequestWithResponse(String arg, void callback(String ret));
}

// noRequestNoResponse: ()
const int _kWithAndWithoutRequestResponse_NoRequestNoResponse_Ordinal =
    503576693;
const $fidl.MethodType
    _kWithAndWithoutRequestResponse_NoRequestNoResponse_Type = $fidl.MethodType(
  request: null,
  response: null,
  name: r"WithAndWithoutRequestResponse.NoRequestNoResponse",
);
// noRequestEmptyResponse: () -> ()
const int _kWithAndWithoutRequestResponse_NoRequestEmptyResponse_Ordinal =
    1308023765;
const $fidl.MethodType
    _kWithAndWithoutRequestResponse_NoRequestEmptyResponse_Type =
    $fidl.MethodType(
  request: null,
  response: null,
  name: r"WithAndWithoutRequestResponse.NoRequestEmptyResponse",
);
// noRequestWithResponse: () -> (String ret)
const int _kWithAndWithoutRequestResponse_NoRequestWithResponse_Ordinal =
    107534328;
const $fidl.MethodType
    _kWithAndWithoutRequestResponse_NoRequestWithResponse_Type =
    $fidl.MethodType(
  request: null,
  response: <$fidl.MemberType>[
    $fidl.MemberType<String>(
        type: $fidl.StringType(maybeElementCount: null, nullable: false),
        offset: 16),
  ],
  name: r"WithAndWithoutRequestResponse.NoRequestWithResponse",
);
// withRequestNoResponse: (String arg)
const int _kWithAndWithoutRequestResponse_WithRequestNoResponse_Ordinal =
    432149361;
const $fidl.MethodType
    _kWithAndWithoutRequestResponse_WithRequestNoResponse_Type =
    $fidl.MethodType(
  request: <$fidl.MemberType>[
    $fidl.MemberType<String>(
        type: $fidl.StringType(maybeElementCount: null, nullable: false),
        offset: 16),
  ],
  response: null,
  name: r"WithAndWithoutRequestResponse.WithRequestNoResponse",
);
// withRequestEmptyResponse: (String arg) -> ()
const int _kWithAndWithoutRequestResponse_WithRequestEmptyResponse_Ordinal =
    1995585907;
const $fidl.MethodType
    _kWithAndWithoutRequestResponse_WithRequestEmptyResponse_Type =
    $fidl.MethodType(
  request: <$fidl.MemberType>[
    $fidl.MemberType<String>(
        type: $fidl.StringType(maybeElementCount: null, nullable: false),
        offset: 16),
  ],
  response: null,
  name: r"WithAndWithoutRequestResponse.WithRequestEmptyResponse",
);
// withRequestWithResponse: (String arg) -> (String ret)
const int _kWithAndWithoutRequestResponse_WithRequestWithResponse_Ordinal =
    426977568;
const $fidl.MethodType
    _kWithAndWithoutRequestResponse_WithRequestWithResponse_Type =
    $fidl.MethodType(
  request: <$fidl.MemberType>[
    $fidl.MemberType<String>(
        type: $fidl.StringType(maybeElementCount: null, nullable: false),
        offset: 16),
  ],
  response: <$fidl.MemberType>[
    $fidl.MemberType<String>(
        type: $fidl.StringType(maybeElementCount: null, nullable: false),
        offset: 16),
  ],
  name: r"WithAndWithoutRequestResponse.WithRequestWithResponse",
);
// onEmptyResponse:  -> ()
const int _kWithAndWithoutRequestResponse_OnEmptyResponse_Ordinal = 1769985842;
const $fidl.MethodType _kWithAndWithoutRequestResponse_OnEmptyResponse_Type =
    $fidl.MethodType(
  request: null,
  response: null,
  name: r"WithAndWithoutRequestResponse.OnEmptyResponse",
);
// onWithResponse:  -> (String ret)
const int _kWithAndWithoutRequestResponse_OnWithResponse_Ordinal = 2051478023;
const $fidl.MethodType _kWithAndWithoutRequestResponse_OnWithResponse_Type =
    $fidl.MethodType(
  request: null,
  response: <$fidl.MemberType>[
    $fidl.MemberType<String>(
        type: $fidl.StringType(maybeElementCount: null, nullable: false),
        offset: 16),
  ],
  name: r"WithAndWithoutRequestResponse.OnWithResponse",
);

typedef void WithAndWithoutRequestResponseOnEmptyResponseCallback();
typedef void WithAndWithoutRequestResponseOnWithResponseCallback(String ret);

class WithAndWithoutRequestResponseProxy
    extends $fidl.Proxy<WithAndWithoutRequestResponse>
    implements WithAndWithoutRequestResponse {
  WithAndWithoutRequestResponseProxy()
      : super($fidl.ProxyController<WithAndWithoutRequestResponse>(
            $serviceName: null,
            $interfaceName: r'WithAndWithoutRequestResponse')) {
    ctrl.onResponse = _handleResponse;
  }

  void _handleEvent($fidl.Message $message) {
    final $fidl.Decoder $decoder = $fidl.Decoder($message);
    switch ($message.ordinal) {
      case _kWithAndWithoutRequestResponse_OnEmptyResponse_Ordinal:
        final String _name =
            _kWithAndWithoutRequestResponse_OnEmptyResponse_Type.name;
        try {
          Timeline.startSync(_name);
          final Function $callback = onEmptyResponse;
          if ($callback == null) {
            $message.closeHandles();
            return;
          }
          final List<$fidl.MemberType> $types =
              _kWithAndWithoutRequestResponse_OnEmptyResponse_Type.response;
          $decoder.claimMemory(16);
          $callback();
          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          ctrl.proxyError('Exception handling event $_name: $_e');
          ctrl.close();
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      case _kWithAndWithoutRequestResponse_OnWithResponse_Ordinal:
        final String _name =
            _kWithAndWithoutRequestResponse_OnWithResponse_Type.name;
        try {
          Timeline.startSync(_name);
          final Function $callback = onWithResponse;
          if ($callback == null) {
            $message.closeHandles();
            return;
          }
          final List<$fidl.MemberType> $types =
              _kWithAndWithoutRequestResponse_OnWithResponse_Type.response;
          $decoder.claimMemory(32);
          $callback(
            $types[0].decode($decoder, 0),
          );
          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          ctrl.proxyError('Exception handling event $_name: $_e');
          ctrl.close();
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      default:
        ctrl.proxyError('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 Function $callback = ctrl.getCallback($txid);
    if ($callback == null) {
      $message.closeHandles();
      return;
    }
    final $fidl.Decoder $decoder = $fidl.Decoder($message);
    switch ($message.ordinal) {
      case _kWithAndWithoutRequestResponse_NoRequestEmptyResponse_Ordinal:
        final String _name =
            _kWithAndWithoutRequestResponse_NoRequestEmptyResponse_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kWithAndWithoutRequestResponse_NoRequestEmptyResponse_Type
                  .response;
          $decoder.claimMemory(16);
          $callback();
          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          ctrl.proxyError('Exception handling method response $_name: $_e');
          ctrl.close();
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      case _kWithAndWithoutRequestResponse_NoRequestWithResponse_Ordinal:
        final String _name =
            _kWithAndWithoutRequestResponse_NoRequestWithResponse_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kWithAndWithoutRequestResponse_NoRequestWithResponse_Type
                  .response;
          $decoder.claimMemory(32);
          $callback(
            $types[0].decode($decoder, 0),
          );
          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          ctrl.proxyError('Exception handling method response $_name: $_e');
          ctrl.close();
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      case _kWithAndWithoutRequestResponse_WithRequestEmptyResponse_Ordinal:
        final String _name =
            _kWithAndWithoutRequestResponse_WithRequestEmptyResponse_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kWithAndWithoutRequestResponse_WithRequestEmptyResponse_Type
                  .response;
          $decoder.claimMemory(16);
          $callback();
          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          ctrl.proxyError('Exception handling method response $_name: $_e');
          ctrl.close();
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      case _kWithAndWithoutRequestResponse_WithRequestWithResponse_Ordinal:
        final String _name =
            _kWithAndWithoutRequestResponse_WithRequestWithResponse_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kWithAndWithoutRequestResponse_WithRequestWithResponse_Type
                  .response;
          $decoder.claimMemory(32);
          $callback(
            $types[0].decode($decoder, 0),
          );
          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          ctrl.proxyError('Exception handling method response $_name: $_e');
          ctrl.close();
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      default:
        ctrl.proxyError('Unexpected message ordinal: ${$message.ordinal}');
        ctrl.close();
        break;
    }
  }

  @override
  void noRequestNoResponse() {
    if (!ctrl.isBound) {
      ctrl.proxyError('The proxy is closed.');
      return;
    }

    final $fidl.Encoder $encoder = $fidl.Encoder();
    $encoder.encodeMessageHeader(
        _kWithAndWithoutRequestResponse_NoRequestNoResponse_Ordinal, 0);
    ctrl.sendMessage($encoder.message);
  }

  @override
  void noRequestEmptyResponse(void callback()) {
    if (!ctrl.isBound) {
      ctrl.proxyError('The proxy is closed.');
      return;
    }

    final $fidl.Encoder $encoder = $fidl.Encoder();
    $encoder.encodeMessageHeader(
        _kWithAndWithoutRequestResponse_NoRequestEmptyResponse_Ordinal, 0);
    Function $zonedCallback;
    if ((callback == null) || identical(Zone.current, Zone.root)) {
      $zonedCallback = callback;
    } else {
      Zone $z = Zone.current;
      $zonedCallback = $z.bindCallback(callback);
    }
    ctrl.sendMessageWithResponse($encoder.message, $zonedCallback);
  }

  @override
  void noRequestWithResponse(void callback(String ret)) {
    if (!ctrl.isBound) {
      ctrl.proxyError('The proxy is closed.');
      return;
    }

    final $fidl.Encoder $encoder = $fidl.Encoder();
    $encoder.encodeMessageHeader(
        _kWithAndWithoutRequestResponse_NoRequestWithResponse_Ordinal, 0);
    Function $zonedCallback;
    if ((callback == null) || identical(Zone.current, Zone.root)) {
      $zonedCallback = callback;
    } else {
      Zone $z = Zone.current;
      $zonedCallback = ((String ret) {
        $z.bindCallback(() {
          callback(
            ret,
          );
        })();
      });
    }
    ctrl.sendMessageWithResponse($encoder.message, $zonedCallback);
  }

  @override
  void withRequestNoResponse(String arg) {
    if (!ctrl.isBound) {
      ctrl.proxyError('The proxy is closed.');
      return;
    }

    final $fidl.Encoder $encoder = $fidl.Encoder();
    $encoder.encodeMessageHeader(
        _kWithAndWithoutRequestResponse_WithRequestNoResponse_Ordinal, 0);
    $encoder.alloc(32 - $fidl.kMessageHeaderSize);
    final List<$fidl.MemberType> $types =
        _kWithAndWithoutRequestResponse_WithRequestNoResponse_Type.request;
    $types[0].encode($encoder, arg, 0);
    ctrl.sendMessage($encoder.message);
  }

  @override
  void withRequestEmptyResponse(String arg, void callback()) {
    if (!ctrl.isBound) {
      ctrl.proxyError('The proxy is closed.');
      return;
    }

    final $fidl.Encoder $encoder = $fidl.Encoder();
    $encoder.encodeMessageHeader(
        _kWithAndWithoutRequestResponse_WithRequestEmptyResponse_Ordinal, 0);
    $encoder.alloc(32 - $fidl.kMessageHeaderSize);
    final List<$fidl.MemberType> $types =
        _kWithAndWithoutRequestResponse_WithRequestEmptyResponse_Type.request;
    $types[0].encode($encoder, arg, 0);
    Function $zonedCallback;
    if ((callback == null) || identical(Zone.current, Zone.root)) {
      $zonedCallback = callback;
    } else {
      Zone $z = Zone.current;
      $zonedCallback = $z.bindCallback(callback);
    }
    ctrl.sendMessageWithResponse($encoder.message, $zonedCallback);
  }

  @override
  void withRequestWithResponse(String arg, void callback(String ret)) {
    if (!ctrl.isBound) {
      ctrl.proxyError('The proxy is closed.');
      return;
    }

    final $fidl.Encoder $encoder = $fidl.Encoder();
    $encoder.encodeMessageHeader(
        _kWithAndWithoutRequestResponse_WithRequestWithResponse_Ordinal, 0);
    $encoder.alloc(32 - $fidl.kMessageHeaderSize);
    final List<$fidl.MemberType> $types =
        _kWithAndWithoutRequestResponse_WithRequestWithResponse_Type.request;
    $types[0].encode($encoder, arg, 0);
    Function $zonedCallback;
    if ((callback == null) || identical(Zone.current, Zone.root)) {
      $zonedCallback = callback;
    } else {
      Zone $z = Zone.current;
      $zonedCallback = ((String ret) {
        $z.bindCallback(() {
          callback(
            ret,
          );
        })();
      });
    }
    ctrl.sendMessageWithResponse($encoder.message, $zonedCallback);
  }

  WithAndWithoutRequestResponseOnEmptyResponseCallback onEmptyResponse;
  WithAndWithoutRequestResponseOnWithResponseCallback onWithResponse;
}

class WithAndWithoutRequestResponseEvents {
  $fidl.Binding<WithAndWithoutRequestResponse> _binding;
  void onEmptyResponse() {
    final $fidl.Encoder $encoder = $fidl.Encoder();
    $encoder.encodeMessageHeader(
        _kWithAndWithoutRequestResponse_OnEmptyResponse_Ordinal, 0);
    _binding.sendMessage($encoder.message);
  }

  void onWithResponse(String ret) {
    final $fidl.Encoder $encoder = $fidl.Encoder();
    $encoder.encodeMessageHeader(
        _kWithAndWithoutRequestResponse_OnWithResponse_Ordinal, 0);
    $encoder.alloc(32 - $fidl.kMessageHeaderSize);
    final List<$fidl.MemberType> $types =
        _kWithAndWithoutRequestResponse_OnWithResponse_Type.response;
    $types[0].encode($encoder, ret, 0);
    _binding.sendMessage($encoder.message);
  }
}

class WithAndWithoutRequestResponseBinding
    extends $fidl.Binding<WithAndWithoutRequestResponse> {
  WithAndWithoutRequestResponseBinding() {
    events._binding = this;
  }

  final WithAndWithoutRequestResponseEvents events =
      WithAndWithoutRequestResponseEvents();

  Function _noRequestEmptyResponseResponder(
      $fidl.MessageSink $respond, int $txid) {
    return () {
      final $fidl.Encoder $encoder = $fidl.Encoder();
      $encoder.encodeMessageHeader(
          _kWithAndWithoutRequestResponse_NoRequestEmptyResponse_Ordinal,
          $txid);
      $respond($encoder.message);
    };
  }

  Function _noRequestWithResponseResponder(
      $fidl.MessageSink $respond, int $txid) {
    return (String ret) {
      final $fidl.Encoder $encoder = $fidl.Encoder();
      $encoder.encodeMessageHeader(
          _kWithAndWithoutRequestResponse_NoRequestWithResponse_Ordinal, $txid);
      $encoder.alloc(32 - $fidl.kMessageHeaderSize);
      final List<$fidl.MemberType> $types =
          _kWithAndWithoutRequestResponse_NoRequestWithResponse_Type.response;
      $types[0].encode($encoder, ret, 0);
      $respond($encoder.message);
    };
  }

  Function _withRequestEmptyResponseResponder(
      $fidl.MessageSink $respond, int $txid) {
    return () {
      final $fidl.Encoder $encoder = $fidl.Encoder();
      $encoder.encodeMessageHeader(
          _kWithAndWithoutRequestResponse_WithRequestEmptyResponse_Ordinal,
          $txid);
      $respond($encoder.message);
    };
  }

  Function _withRequestWithResponseResponder(
      $fidl.MessageSink $respond, int $txid) {
    return (String ret) {
      final $fidl.Encoder $encoder = $fidl.Encoder();
      $encoder.encodeMessageHeader(
          _kWithAndWithoutRequestResponse_WithRequestWithResponse_Ordinal,
          $txid);
      $encoder.alloc(32 - $fidl.kMessageHeaderSize);
      final List<$fidl.MemberType> $types =
          _kWithAndWithoutRequestResponse_WithRequestWithResponse_Type.response;
      $types[0].encode($encoder, ret, 0);
      $respond($encoder.message);
    };
  }

  @override
  void handleMessage($fidl.Message $message, $fidl.MessageSink $respond) {
    final $fidl.Decoder $decoder = $fidl.Decoder($message);
    switch ($message.ordinal) {
      case _kWithAndWithoutRequestResponse_NoRequestNoResponse_Ordinal:
        final String _name =
            _kWithAndWithoutRequestResponse_NoRequestNoResponse_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kWithAndWithoutRequestResponse_NoRequestNoResponse_Type.request;
          $decoder.claimMemory(16);
          impl.noRequestNoResponse();
          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          close();
          print('Exception handling method call $_name: $_e');
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      case _kWithAndWithoutRequestResponse_NoRequestEmptyResponse_Ordinal:
        final String _name =
            _kWithAndWithoutRequestResponse_NoRequestEmptyResponse_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kWithAndWithoutRequestResponse_NoRequestEmptyResponse_Type
                  .request;
          $decoder.claimMemory(16);
          impl.noRequestEmptyResponse(
            _noRequestEmptyResponseResponder($respond, $message.txid),
          );
          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          close();
          print('Exception handling method call $_name: $_e');
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      case _kWithAndWithoutRequestResponse_NoRequestWithResponse_Ordinal:
        final String _name =
            _kWithAndWithoutRequestResponse_NoRequestWithResponse_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kWithAndWithoutRequestResponse_NoRequestWithResponse_Type
                  .request;
          $decoder.claimMemory(16);
          impl.noRequestWithResponse(
            _noRequestWithResponseResponder($respond, $message.txid),
          );
          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          close();
          print('Exception handling method call $_name: $_e');
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      case _kWithAndWithoutRequestResponse_WithRequestNoResponse_Ordinal:
        final String _name =
            _kWithAndWithoutRequestResponse_WithRequestNoResponse_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kWithAndWithoutRequestResponse_WithRequestNoResponse_Type
                  .request;
          $decoder.claimMemory(32);
          impl.withRequestNoResponse(
            $types[0].decode($decoder, 0),
          );
          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          close();
          print('Exception handling method call $_name: $_e');
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      case _kWithAndWithoutRequestResponse_WithRequestEmptyResponse_Ordinal:
        final String _name =
            _kWithAndWithoutRequestResponse_WithRequestEmptyResponse_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kWithAndWithoutRequestResponse_WithRequestEmptyResponse_Type
                  .request;
          $decoder.claimMemory(32);
          impl.withRequestEmptyResponse(
            $types[0].decode($decoder, 0),
            _withRequestEmptyResponseResponder($respond, $message.txid),
          );
          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          close();
          print('Exception handling method call $_name: $_e');
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      case _kWithAndWithoutRequestResponse_WithRequestWithResponse_Ordinal:
        final String _name =
            _kWithAndWithoutRequestResponse_WithRequestWithResponse_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kWithAndWithoutRequestResponse_WithRequestWithResponse_Type
                  .request;
          $decoder.claimMemory(32);
          impl.withRequestWithResponse(
            $types[0].decode($decoder, 0),
            _withRequestWithResponseResponder($respond, $message.txid),
          );
          // 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 WithAndWithoutRequestResponseBinding');
    }
  }
}

abstract class WithErrorSyntax {
  static const String $serviceName = null;
  void errorAsPrimitive(
      void callback(WithErrorSyntaxErrorAsPrimitiveResult result));
  void errorAsEnum(void callback(WithErrorSyntaxErrorAsEnumResult result));
}

// errorAsPrimitive: () -> (WithErrorSyntaxErrorAsPrimitiveResult result)
const int _kWithErrorSyntax_ErrorAsPrimitive_Ordinal = 2069369145;
const $fidl.MethodType _kWithErrorSyntax_ErrorAsPrimitive_Type =
    $fidl.MethodType(
  request: null,
  response: <$fidl.MemberType>[
    $fidl.MemberType<WithErrorSyntaxErrorAsPrimitiveResult>(
        type: kWithErrorSyntax_ErrorAsPrimitive_Result_Type, offset: 16),
  ],
  name: r"WithErrorSyntax.ErrorAsPrimitive",
);
// errorAsEnum: () -> (WithErrorSyntaxErrorAsEnumResult result)
const int _kWithErrorSyntax_ErrorAsEnum_Ordinal = 1284890143;
const $fidl.MethodType _kWithErrorSyntax_ErrorAsEnum_Type = $fidl.MethodType(
  request: null,
  response: <$fidl.MemberType>[
    $fidl.MemberType<WithErrorSyntaxErrorAsEnumResult>(
        type: kWithErrorSyntax_ErrorAsEnum_Result_Type, offset: 16),
  ],
  name: r"WithErrorSyntax.ErrorAsEnum",
);

class WithErrorSyntaxProxy extends $fidl.Proxy<WithErrorSyntax>
    implements WithErrorSyntax {
  WithErrorSyntaxProxy()
      : super($fidl.ProxyController<WithErrorSyntax>(
            $serviceName: null, $interfaceName: r'WithErrorSyntax')) {
    ctrl.onResponse = _handleResponse;
  }

  void _handleEvent($fidl.Message $message) {
    final $fidl.Decoder $decoder = $fidl.Decoder($message);
    switch ($message.ordinal) {
      default:
        ctrl.proxyError('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 Function $callback = ctrl.getCallback($txid);
    if ($callback == null) {
      $message.closeHandles();
      return;
    }
    final $fidl.Decoder $decoder = $fidl.Decoder($message);
    switch ($message.ordinal) {
      case _kWithErrorSyntax_ErrorAsPrimitive_Ordinal:
        final String _name = _kWithErrorSyntax_ErrorAsPrimitive_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kWithErrorSyntax_ErrorAsPrimitive_Type.response;
          $decoder.claimMemory(24);
          $callback(
            $types[0].decode($decoder, 0),
          );
          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          ctrl.proxyError('Exception handling method response $_name: $_e');
          ctrl.close();
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      case _kWithErrorSyntax_ErrorAsEnum_Ordinal:
        final String _name = _kWithErrorSyntax_ErrorAsEnum_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kWithErrorSyntax_ErrorAsEnum_Type.response;
          $decoder.claimMemory(24);
          $callback(
            $types[0].decode($decoder, 0),
          );
          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          ctrl.proxyError('Exception handling method response $_name: $_e');
          ctrl.close();
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      default:
        ctrl.proxyError('Unexpected message ordinal: ${$message.ordinal}');
        ctrl.close();
        break;
    }
  }

  @override
  void errorAsPrimitive(
      void callback(WithErrorSyntaxErrorAsPrimitiveResult result)) {
    if (!ctrl.isBound) {
      ctrl.proxyError('The proxy is closed.');
      return;
    }

    final $fidl.Encoder $encoder = $fidl.Encoder();
    $encoder.encodeMessageHeader(_kWithErrorSyntax_ErrorAsPrimitive_Ordinal, 0);
    Function $zonedCallback;
    if ((callback == null) || identical(Zone.current, Zone.root)) {
      $zonedCallback = callback;
    } else {
      Zone $z = Zone.current;
      $zonedCallback = ((WithErrorSyntaxErrorAsPrimitiveResult result) {
        $z.bindCallback(() {
          callback(
            result,
          );
        })();
      });
    }
    ctrl.sendMessageWithResponse($encoder.message, $zonedCallback);
  }

  @override
  void errorAsEnum(void callback(WithErrorSyntaxErrorAsEnumResult result)) {
    if (!ctrl.isBound) {
      ctrl.proxyError('The proxy is closed.');
      return;
    }

    final $fidl.Encoder $encoder = $fidl.Encoder();
    $encoder.encodeMessageHeader(_kWithErrorSyntax_ErrorAsEnum_Ordinal, 0);
    Function $zonedCallback;
    if ((callback == null) || identical(Zone.current, Zone.root)) {
      $zonedCallback = callback;
    } else {
      Zone $z = Zone.current;
      $zonedCallback = ((WithErrorSyntaxErrorAsEnumResult result) {
        $z.bindCallback(() {
          callback(
            result,
          );
        })();
      });
    }
    ctrl.sendMessageWithResponse($encoder.message, $zonedCallback);
  }
}

class WithErrorSyntaxBinding extends $fidl.Binding<WithErrorSyntax> {
  Function _errorAsPrimitiveResponder($fidl.MessageSink $respond, int $txid) {
    return (WithErrorSyntaxErrorAsPrimitiveResult result) {
      final $fidl.Encoder $encoder = $fidl.Encoder();
      $encoder.encodeMessageHeader(
          _kWithErrorSyntax_ErrorAsPrimitive_Ordinal, $txid);
      $encoder.alloc(24 - $fidl.kMessageHeaderSize);
      final List<$fidl.MemberType> $types =
          _kWithErrorSyntax_ErrorAsPrimitive_Type.response;
      $types[0].encode($encoder, result, 0);
      $respond($encoder.message);
    };
  }

  Function _errorAsEnumResponder($fidl.MessageSink $respond, int $txid) {
    return (WithErrorSyntaxErrorAsEnumResult result) {
      final $fidl.Encoder $encoder = $fidl.Encoder();
      $encoder.encodeMessageHeader(
          _kWithErrorSyntax_ErrorAsEnum_Ordinal, $txid);
      $encoder.alloc(24 - $fidl.kMessageHeaderSize);
      final List<$fidl.MemberType> $types =
          _kWithErrorSyntax_ErrorAsEnum_Type.response;
      $types[0].encode($encoder, result, 0);
      $respond($encoder.message);
    };
  }

  @override
  void handleMessage($fidl.Message $message, $fidl.MessageSink $respond) {
    final $fidl.Decoder $decoder = $fidl.Decoder($message);
    switch ($message.ordinal) {
      case _kWithErrorSyntax_ErrorAsPrimitive_Ordinal:
        final String _name = _kWithErrorSyntax_ErrorAsPrimitive_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kWithErrorSyntax_ErrorAsPrimitive_Type.request;
          $decoder.claimMemory(16);
          impl.errorAsPrimitive(
            _errorAsPrimitiveResponder($respond, $message.txid),
          );
          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          close();
          print('Exception handling method call $_name: $_e');
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      case _kWithErrorSyntax_ErrorAsEnum_Ordinal:
        final String _name = _kWithErrorSyntax_ErrorAsEnum_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kWithErrorSyntax_ErrorAsEnum_Type.request;
          $decoder.claimMemory(16);
          impl.errorAsEnum(
            _errorAsEnumResponder($respond, $message.txid),
          );
          // 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 WithErrorSyntaxBinding');
    }
  }
}

abstract class OvernetInternalProtocol {
  static const String $serviceName = null;
  void methodA(int a, int b);
  void methodB(int a, int b, void callback(int result));
}

// methodA: (int a, int b)
const int _kOvernetInternalProtocol_MethodA_Ordinal = 1993818253;
const $fidl.MethodType _kOvernetInternalProtocol_MethodA_Type =
    $fidl.MethodType(
  request: <$fidl.MemberType>[
    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 16),
    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 24),
  ],
  response: null,
  name: r"OvernetInternalProtocol.MethodA",
);
// eventA:  -> (int a, int b)
const int _kOvernetInternalProtocol_EventA_Ordinal = 1746007436;
const $fidl.MethodType _kOvernetInternalProtocol_EventA_Type = $fidl.MethodType(
  request: null,
  response: <$fidl.MemberType>[
    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 16),
    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 24),
  ],
  name: r"OvernetInternalProtocol.EventA",
);
// methodB: (int a, int b) -> (int result)
const int _kOvernetInternalProtocol_MethodB_Ordinal = 952134976;
const $fidl.MethodType _kOvernetInternalProtocol_MethodB_Type =
    $fidl.MethodType(
  request: <$fidl.MemberType>[
    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 16),
    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 24),
  ],
  response: <$fidl.MemberType>[
    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 16),
  ],
  name: r"OvernetInternalProtocol.MethodB",
);

typedef void OvernetInternalProtocolEventACallback(int a, int b);

class OvernetInternalProtocolProxy extends $fidl.Proxy<OvernetInternalProtocol>
    implements OvernetInternalProtocol {
  OvernetInternalProtocolProxy()
      : super($fidl.ProxyController<OvernetInternalProtocol>(
            $serviceName: null, $interfaceName: r'OvernetInternalProtocol')) {
    ctrl.onResponse = _handleResponse;
  }

  void _handleEvent($fidl.Message $message) {
    final $fidl.Decoder $decoder = $fidl.Decoder($message);
    switch ($message.ordinal) {
      case _kOvernetInternalProtocol_EventA_Ordinal:
        final String _name = _kOvernetInternalProtocol_EventA_Type.name;
        try {
          Timeline.startSync(_name);
          final Function $callback = eventA;
          if ($callback == null) {
            $message.closeHandles();
            return;
          }
          final List<$fidl.MemberType> $types =
              _kOvernetInternalProtocol_EventA_Type.response;
          $decoder.claimMemory(32);
          $callback(
            $types[0].decode($decoder, 0),
            $types[1].decode($decoder, 0),
          );
          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          ctrl.proxyError('Exception handling event $_name: $_e');
          ctrl.close();
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      default:
        ctrl.proxyError('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 Function $callback = ctrl.getCallback($txid);
    if ($callback == null) {
      $message.closeHandles();
      return;
    }
    final $fidl.Decoder $decoder = $fidl.Decoder($message);
    switch ($message.ordinal) {
      case _kOvernetInternalProtocol_MethodB_Ordinal:
        final String _name = _kOvernetInternalProtocol_MethodB_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kOvernetInternalProtocol_MethodB_Type.response;
          $decoder.claimMemory(24);
          $callback(
            $types[0].decode($decoder, 0),
          );
          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          ctrl.proxyError('Exception handling method response $_name: $_e');
          ctrl.close();
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      default:
        ctrl.proxyError('Unexpected message ordinal: ${$message.ordinal}');
        ctrl.close();
        break;
    }
  }

  @override
  void methodA(int a, int b) {
    if (!ctrl.isBound) {
      ctrl.proxyError('The proxy is closed.');
      return;
    }

    final $fidl.Encoder $encoder = $fidl.Encoder();
    $encoder.encodeMessageHeader(_kOvernetInternalProtocol_MethodA_Ordinal, 0);
    $encoder.alloc(32 - $fidl.kMessageHeaderSize);
    final List<$fidl.MemberType> $types =
        _kOvernetInternalProtocol_MethodA_Type.request;
    $types[0].encode($encoder, a, 0);
    $types[1].encode($encoder, b, 0);
    ctrl.sendMessage($encoder.message);
  }

  OvernetInternalProtocolEventACallback eventA;
  @override
  void methodB(int a, int b, void callback(int result)) {
    if (!ctrl.isBound) {
      ctrl.proxyError('The proxy is closed.');
      return;
    }

    final $fidl.Encoder $encoder = $fidl.Encoder();
    $encoder.encodeMessageHeader(_kOvernetInternalProtocol_MethodB_Ordinal, 0);
    $encoder.alloc(32 - $fidl.kMessageHeaderSize);
    final List<$fidl.MemberType> $types =
        _kOvernetInternalProtocol_MethodB_Type.request;
    $types[0].encode($encoder, a, 0);
    $types[1].encode($encoder, b, 0);
    Function $zonedCallback;
    if ((callback == null) || identical(Zone.current, Zone.root)) {
      $zonedCallback = callback;
    } else {
      Zone $z = Zone.current;
      $zonedCallback = ((int result) {
        $z.bindCallback(() {
          callback(
            result,
          );
        })();
      });
    }
    ctrl.sendMessageWithResponse($encoder.message, $zonedCallback);
  }
}

class OvernetInternalProtocolEvents {
  $fidl.Binding<OvernetInternalProtocol> _binding;
  void eventA(int a, int b) {
    final $fidl.Encoder $encoder = $fidl.Encoder();
    $encoder.encodeMessageHeader(_kOvernetInternalProtocol_EventA_Ordinal, 0);
    $encoder.alloc(32 - $fidl.kMessageHeaderSize);
    final List<$fidl.MemberType> $types =
        _kOvernetInternalProtocol_EventA_Type.response;
    $types[0].encode($encoder, a, 0);
    $types[1].encode($encoder, b, 0);
    _binding.sendMessage($encoder.message);
  }
}

class OvernetInternalProtocolBinding
    extends $fidl.Binding<OvernetInternalProtocol> {
  OvernetInternalProtocolBinding() {
    events._binding = this;
  }

  final OvernetInternalProtocolEvents events = OvernetInternalProtocolEvents();

  Function _methodBResponder($fidl.MessageSink $respond, int $txid) {
    return (int result) {
      final $fidl.Encoder $encoder = $fidl.Encoder();
      $encoder.encodeMessageHeader(
          _kOvernetInternalProtocol_MethodB_Ordinal, $txid);
      $encoder.alloc(24 - $fidl.kMessageHeaderSize);
      final List<$fidl.MemberType> $types =
          _kOvernetInternalProtocol_MethodB_Type.response;
      $types[0].encode($encoder, result, 0);
      $respond($encoder.message);
    };
  }

  @override
  void handleMessage($fidl.Message $message, $fidl.MessageSink $respond) {
    final $fidl.Decoder $decoder = $fidl.Decoder($message);
    switch ($message.ordinal) {
      case _kOvernetInternalProtocol_MethodA_Ordinal:
        final String _name = _kOvernetInternalProtocol_MethodA_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kOvernetInternalProtocol_MethodA_Type.request;
          $decoder.claimMemory(32);
          impl.methodA(
            $types[0].decode($decoder, 0),
            $types[1].decode($decoder, 0),
          );
          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          close();
          print('Exception handling method call $_name: $_e');
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      case _kOvernetInternalProtocol_MethodB_Ordinal:
        final String _name = _kOvernetInternalProtocol_MethodB_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kOvernetInternalProtocol_MethodB_Type.request;
          $decoder.claimMemory(32);
          impl.methodB(
            $types[0].decode($decoder, 0),
            $types[1].decode($decoder, 0),
            _methodBResponder($respond, $message.txid),
          );
          // 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 OvernetInternalProtocolBinding');
    }
  }
}

abstract class SocketControlProtocol {
  static const String $serviceName = null;
  void methodA(int a, int b);
  void methodB(int a, int b, void callback(int result));
}

// methodA: (int a, int b)
const int _kSocketControlProtocol_MethodA_Ordinal = 1007842318;
const $fidl.MethodType _kSocketControlProtocol_MethodA_Type = $fidl.MethodType(
  request: <$fidl.MemberType>[
    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 16),
    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 24),
  ],
  response: null,
  name: r"SocketControlProtocol.MethodA",
);
// eventA:  -> (int a, int b)
const int _kSocketControlProtocol_EventA_Ordinal = 955483393;
const $fidl.MethodType _kSocketControlProtocol_EventA_Type = $fidl.MethodType(
  request: null,
  response: <$fidl.MemberType>[
    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 16),
    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 24),
  ],
  name: r"SocketControlProtocol.EventA",
);
// methodB: (int a, int b) -> (int result)
const int _kSocketControlProtocol_MethodB_Ordinal = 677342235;
const $fidl.MethodType _kSocketControlProtocol_MethodB_Type = $fidl.MethodType(
  request: <$fidl.MemberType>[
    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 16),
    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 24),
  ],
  response: <$fidl.MemberType>[
    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 16),
  ],
  name: r"SocketControlProtocol.MethodB",
);

typedef void SocketControlProtocolEventACallback(int a, int b);

class SocketControlProtocolProxy extends $fidl.Proxy<SocketControlProtocol>
    implements SocketControlProtocol {
  SocketControlProtocolProxy()
      : super($fidl.ProxyController<SocketControlProtocol>(
            $serviceName: null, $interfaceName: r'SocketControlProtocol')) {
    ctrl.onResponse = _handleResponse;
  }

  void _handleEvent($fidl.Message $message) {
    final $fidl.Decoder $decoder = $fidl.Decoder($message);
    switch ($message.ordinal) {
      case _kSocketControlProtocol_EventA_Ordinal:
        final String _name = _kSocketControlProtocol_EventA_Type.name;
        try {
          Timeline.startSync(_name);
          final Function $callback = eventA;
          if ($callback == null) {
            $message.closeHandles();
            return;
          }
          final List<$fidl.MemberType> $types =
              _kSocketControlProtocol_EventA_Type.response;
          $decoder.claimMemory(32);
          $callback(
            $types[0].decode($decoder, 0),
            $types[1].decode($decoder, 0),
          );
          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          ctrl.proxyError('Exception handling event $_name: $_e');
          ctrl.close();
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      default:
        ctrl.proxyError('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 Function $callback = ctrl.getCallback($txid);
    if ($callback == null) {
      $message.closeHandles();
      return;
    }
    final $fidl.Decoder $decoder = $fidl.Decoder($message);
    switch ($message.ordinal) {
      case _kSocketControlProtocol_MethodB_Ordinal:
        final String _name = _kSocketControlProtocol_MethodB_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kSocketControlProtocol_MethodB_Type.response;
          $decoder.claimMemory(24);
          $callback(
            $types[0].decode($decoder, 0),
          );
          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          ctrl.proxyError('Exception handling method response $_name: $_e');
          ctrl.close();
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      default:
        ctrl.proxyError('Unexpected message ordinal: ${$message.ordinal}');
        ctrl.close();
        break;
    }
  }

  @override
  void methodA(int a, int b) {
    if (!ctrl.isBound) {
      ctrl.proxyError('The proxy is closed.');
      return;
    }

    final $fidl.Encoder $encoder = $fidl.Encoder();
    $encoder.encodeMessageHeader(_kSocketControlProtocol_MethodA_Ordinal, 0);
    $encoder.alloc(32 - $fidl.kMessageHeaderSize);
    final List<$fidl.MemberType> $types =
        _kSocketControlProtocol_MethodA_Type.request;
    $types[0].encode($encoder, a, 0);
    $types[1].encode($encoder, b, 0);
    ctrl.sendMessage($encoder.message);
  }

  SocketControlProtocolEventACallback eventA;
  @override
  void methodB(int a, int b, void callback(int result)) {
    if (!ctrl.isBound) {
      ctrl.proxyError('The proxy is closed.');
      return;
    }

    final $fidl.Encoder $encoder = $fidl.Encoder();
    $encoder.encodeMessageHeader(_kSocketControlProtocol_MethodB_Ordinal, 0);
    $encoder.alloc(32 - $fidl.kMessageHeaderSize);
    final List<$fidl.MemberType> $types =
        _kSocketControlProtocol_MethodB_Type.request;
    $types[0].encode($encoder, a, 0);
    $types[1].encode($encoder, b, 0);
    Function $zonedCallback;
    if ((callback == null) || identical(Zone.current, Zone.root)) {
      $zonedCallback = callback;
    } else {
      Zone $z = Zone.current;
      $zonedCallback = ((int result) {
        $z.bindCallback(() {
          callback(
            result,
          );
        })();
      });
    }
    ctrl.sendMessageWithResponse($encoder.message, $zonedCallback);
  }
}

class SocketControlProtocolEvents {
  $fidl.Binding<SocketControlProtocol> _binding;
  void eventA(int a, int b) {
    final $fidl.Encoder $encoder = $fidl.Encoder();
    $encoder.encodeMessageHeader(_kSocketControlProtocol_EventA_Ordinal, 0);
    $encoder.alloc(32 - $fidl.kMessageHeaderSize);
    final List<$fidl.MemberType> $types =
        _kSocketControlProtocol_EventA_Type.response;
    $types[0].encode($encoder, a, 0);
    $types[1].encode($encoder, b, 0);
    _binding.sendMessage($encoder.message);
  }
}

class SocketControlProtocolBinding
    extends $fidl.Binding<SocketControlProtocol> {
  SocketControlProtocolBinding() {
    events._binding = this;
  }

  final SocketControlProtocolEvents events = SocketControlProtocolEvents();

  Function _methodBResponder($fidl.MessageSink $respond, int $txid) {
    return (int result) {
      final $fidl.Encoder $encoder = $fidl.Encoder();
      $encoder.encodeMessageHeader(
          _kSocketControlProtocol_MethodB_Ordinal, $txid);
      $encoder.alloc(24 - $fidl.kMessageHeaderSize);
      final List<$fidl.MemberType> $types =
          _kSocketControlProtocol_MethodB_Type.response;
      $types[0].encode($encoder, result, 0);
      $respond($encoder.message);
    };
  }

  @override
  void handleMessage($fidl.Message $message, $fidl.MessageSink $respond) {
    final $fidl.Decoder $decoder = $fidl.Decoder($message);
    switch ($message.ordinal) {
      case _kSocketControlProtocol_MethodA_Ordinal:
        final String _name = _kSocketControlProtocol_MethodA_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kSocketControlProtocol_MethodA_Type.request;
          $decoder.claimMemory(32);
          impl.methodA(
            $types[0].decode($decoder, 0),
            $types[1].decode($decoder, 0),
          );
          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          close();
          print('Exception handling method call $_name: $_e');
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      case _kSocketControlProtocol_MethodB_Ordinal:
        final String _name = _kSocketControlProtocol_MethodB_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kSocketControlProtocol_MethodB_Type.request;
          $decoder.claimMemory(32);
          impl.methodB(
            $types[0].decode($decoder, 0),
            $types[1].decode($decoder, 0),
            _methodBResponder($respond, $message.txid),
          );
          // 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 SocketControlProtocolBinding');
    }
  }
}

abstract class ChannelProtocol {
  static const String $serviceName = null;
  void methodA(int a, int b);
  void methodB(int a, int b, void callback(int result));
}

// methodA: (int a, int b)
const int _kChannelProtocol_MethodA_Ordinal = 1432785874;
const $fidl.MethodType _kChannelProtocol_MethodA_Type = $fidl.MethodType(
  request: <$fidl.MemberType>[
    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 16),
    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 24),
  ],
  response: null,
  name: r"ChannelProtocol.MethodA",
);
// eventA:  -> (int a, int b)
const int _kChannelProtocol_EventA_Ordinal = 477676034;
const $fidl.MethodType _kChannelProtocol_EventA_Type = $fidl.MethodType(
  request: null,
  response: <$fidl.MemberType>[
    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 16),
    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 24),
  ],
  name: r"ChannelProtocol.EventA",
);
// methodB: (int a, int b) -> (int result)
const int _kChannelProtocol_MethodB_Ordinal = 180770075;
const $fidl.MethodType _kChannelProtocol_MethodB_Type = $fidl.MethodType(
  request: <$fidl.MemberType>[
    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 16),
    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 24),
  ],
  response: <$fidl.MemberType>[
    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 16),
  ],
  name: r"ChannelProtocol.MethodB",
);

typedef void ChannelProtocolEventACallback(int a, int b);

class ChannelProtocolProxy extends $fidl.Proxy<ChannelProtocol>
    implements ChannelProtocol {
  ChannelProtocolProxy()
      : super($fidl.ProxyController<ChannelProtocol>(
            $serviceName: null, $interfaceName: r'ChannelProtocol')) {
    ctrl.onResponse = _handleResponse;
  }

  void _handleEvent($fidl.Message $message) {
    final $fidl.Decoder $decoder = $fidl.Decoder($message);
    switch ($message.ordinal) {
      case _kChannelProtocol_EventA_Ordinal:
        final String _name = _kChannelProtocol_EventA_Type.name;
        try {
          Timeline.startSync(_name);
          final Function $callback = eventA;
          if ($callback == null) {
            $message.closeHandles();
            return;
          }
          final List<$fidl.MemberType> $types =
              _kChannelProtocol_EventA_Type.response;
          $decoder.claimMemory(32);
          $callback(
            $types[0].decode($decoder, 0),
            $types[1].decode($decoder, 0),
          );
          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          ctrl.proxyError('Exception handling event $_name: $_e');
          ctrl.close();
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      default:
        ctrl.proxyError('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 Function $callback = ctrl.getCallback($txid);
    if ($callback == null) {
      $message.closeHandles();
      return;
    }
    final $fidl.Decoder $decoder = $fidl.Decoder($message);
    switch ($message.ordinal) {
      case _kChannelProtocol_MethodB_Ordinal:
        final String _name = _kChannelProtocol_MethodB_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kChannelProtocol_MethodB_Type.response;
          $decoder.claimMemory(24);
          $callback(
            $types[0].decode($decoder, 0),
          );
          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          ctrl.proxyError('Exception handling method response $_name: $_e');
          ctrl.close();
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      default:
        ctrl.proxyError('Unexpected message ordinal: ${$message.ordinal}');
        ctrl.close();
        break;
    }
  }

  @override
  void methodA(int a, int b) {
    if (!ctrl.isBound) {
      ctrl.proxyError('The proxy is closed.');
      return;
    }

    final $fidl.Encoder $encoder = $fidl.Encoder();
    $encoder.encodeMessageHeader(_kChannelProtocol_MethodA_Ordinal, 0);
    $encoder.alloc(32 - $fidl.kMessageHeaderSize);
    final List<$fidl.MemberType> $types =
        _kChannelProtocol_MethodA_Type.request;
    $types[0].encode($encoder, a, 0);
    $types[1].encode($encoder, b, 0);
    ctrl.sendMessage($encoder.message);
  }

  ChannelProtocolEventACallback eventA;
  @override
  void methodB(int a, int b, void callback(int result)) {
    if (!ctrl.isBound) {
      ctrl.proxyError('The proxy is closed.');
      return;
    }

    final $fidl.Encoder $encoder = $fidl.Encoder();
    $encoder.encodeMessageHeader(_kChannelProtocol_MethodB_Ordinal, 0);
    $encoder.alloc(32 - $fidl.kMessageHeaderSize);
    final List<$fidl.MemberType> $types =
        _kChannelProtocol_MethodB_Type.request;
    $types[0].encode($encoder, a, 0);
    $types[1].encode($encoder, b, 0);
    Function $zonedCallback;
    if ((callback == null) || identical(Zone.current, Zone.root)) {
      $zonedCallback = callback;
    } else {
      Zone $z = Zone.current;
      $zonedCallback = ((int result) {
        $z.bindCallback(() {
          callback(
            result,
          );
        })();
      });
    }
    ctrl.sendMessageWithResponse($encoder.message, $zonedCallback);
  }
}

class ChannelProtocolEvents {
  $fidl.Binding<ChannelProtocol> _binding;
  void eventA(int a, int b) {
    final $fidl.Encoder $encoder = $fidl.Encoder();
    $encoder.encodeMessageHeader(_kChannelProtocol_EventA_Ordinal, 0);
    $encoder.alloc(32 - $fidl.kMessageHeaderSize);
    final List<$fidl.MemberType> $types =
        _kChannelProtocol_EventA_Type.response;
    $types[0].encode($encoder, a, 0);
    $types[1].encode($encoder, b, 0);
    _binding.sendMessage($encoder.message);
  }
}

class ChannelProtocolBinding extends $fidl.Binding<ChannelProtocol> {
  ChannelProtocolBinding() {
    events._binding = this;
  }

  final ChannelProtocolEvents events = ChannelProtocolEvents();

  Function _methodBResponder($fidl.MessageSink $respond, int $txid) {
    return (int result) {
      final $fidl.Encoder $encoder = $fidl.Encoder();
      $encoder.encodeMessageHeader(_kChannelProtocol_MethodB_Ordinal, $txid);
      $encoder.alloc(24 - $fidl.kMessageHeaderSize);
      final List<$fidl.MemberType> $types =
          _kChannelProtocol_MethodB_Type.response;
      $types[0].encode($encoder, result, 0);
      $respond($encoder.message);
    };
  }

  @override
  void handleMessage($fidl.Message $message, $fidl.MessageSink $respond) {
    final $fidl.Decoder $decoder = $fidl.Decoder($message);
    switch ($message.ordinal) {
      case _kChannelProtocol_MethodA_Ordinal:
        final String _name = _kChannelProtocol_MethodA_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kChannelProtocol_MethodA_Type.request;
          $decoder.claimMemory(32);
          impl.methodA(
            $types[0].decode($decoder, 0),
            $types[1].decode($decoder, 0),
          );
          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          close();
          print('Exception handling method call $_name: $_e');
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      case _kChannelProtocol_MethodB_Ordinal:
        final String _name = _kChannelProtocol_MethodB_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kChannelProtocol_MethodB_Type.request;
          $decoder.claimMemory(32);
          impl.methodB(
            $types[0].decode($decoder, 0),
            $types[1].decode($decoder, 0),
            _methodBResponder($respond, $message.txid),
          );
          // 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 ChannelProtocolBinding');
    }
  }
}

abstract class KitchenSink {
  static const String $serviceName = null;
  void methodA(int a, int b);
  void methodB(int a, int b, void callback(int result));
}

// methodA: (int a, int b)
const int _kKitchenSink_MethodA_Ordinal = 450577456;
const $fidl.MethodType _kKitchenSink_MethodA_Type = $fidl.MethodType(
  request: <$fidl.MemberType>[
    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 16),
    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 24),
  ],
  response: null,
  name: r"KitchenSink.MethodA",
);
// eventA:  -> (int a, int b)
const int _kKitchenSink_EventA_Ordinal = 1795426833;
const $fidl.MethodType _kKitchenSink_EventA_Type = $fidl.MethodType(
  request: null,
  response: <$fidl.MemberType>[
    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 16),
    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 24),
  ],
  name: r"KitchenSink.EventA",
);
// methodB: (int a, int b) -> (int result)
const int _kKitchenSink_MethodB_Ordinal = 1999489700;
const $fidl.MethodType _kKitchenSink_MethodB_Type = $fidl.MethodType(
  request: <$fidl.MemberType>[
    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 16),
    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 24),
  ],
  response: <$fidl.MemberType>[
    $fidl.MemberType<int>(type: $fidl.Int64Type(), offset: 16),
  ],
  name: r"KitchenSink.MethodB",
);

typedef void KitchenSinkEventACallback(int a, int b);

class KitchenSinkProxy extends $fidl.Proxy<KitchenSink> implements KitchenSink {
  KitchenSinkProxy()
      : super($fidl.ProxyController<KitchenSink>(
            $serviceName: null, $interfaceName: r'KitchenSink')) {
    ctrl.onResponse = _handleResponse;
  }

  void _handleEvent($fidl.Message $message) {
    final $fidl.Decoder $decoder = $fidl.Decoder($message);
    switch ($message.ordinal) {
      case _kKitchenSink_EventA_Ordinal:
        final String _name = _kKitchenSink_EventA_Type.name;
        try {
          Timeline.startSync(_name);
          final Function $callback = eventA;
          if ($callback == null) {
            $message.closeHandles();
            return;
          }
          final List<$fidl.MemberType> $types =
              _kKitchenSink_EventA_Type.response;
          $decoder.claimMemory(32);
          $callback(
            $types[0].decode($decoder, 0),
            $types[1].decode($decoder, 0),
          );
          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          ctrl.proxyError('Exception handling event $_name: $_e');
          ctrl.close();
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      default:
        ctrl.proxyError('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 Function $callback = ctrl.getCallback($txid);
    if ($callback == null) {
      $message.closeHandles();
      return;
    }
    final $fidl.Decoder $decoder = $fidl.Decoder($message);
    switch ($message.ordinal) {
      case _kKitchenSink_MethodB_Ordinal:
        final String _name = _kKitchenSink_MethodB_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kKitchenSink_MethodB_Type.response;
          $decoder.claimMemory(24);
          $callback(
            $types[0].decode($decoder, 0),
          );
          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          ctrl.proxyError('Exception handling method response $_name: $_e');
          ctrl.close();
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      default:
        ctrl.proxyError('Unexpected message ordinal: ${$message.ordinal}');
        ctrl.close();
        break;
    }
  }

  @override
  void methodA(int a, int b) {
    if (!ctrl.isBound) {
      ctrl.proxyError('The proxy is closed.');
      return;
    }

    final $fidl.Encoder $encoder = $fidl.Encoder();
    $encoder.encodeMessageHeader(_kKitchenSink_MethodA_Ordinal, 0);
    $encoder.alloc(32 - $fidl.kMessageHeaderSize);
    final List<$fidl.MemberType> $types = _kKitchenSink_MethodA_Type.request;
    $types[0].encode($encoder, a, 0);
    $types[1].encode($encoder, b, 0);
    ctrl.sendMessage($encoder.message);
  }

  KitchenSinkEventACallback eventA;
  @override
  void methodB(int a, int b, void callback(int result)) {
    if (!ctrl.isBound) {
      ctrl.proxyError('The proxy is closed.');
      return;
    }

    final $fidl.Encoder $encoder = $fidl.Encoder();
    $encoder.encodeMessageHeader(_kKitchenSink_MethodB_Ordinal, 0);
    $encoder.alloc(32 - $fidl.kMessageHeaderSize);
    final List<$fidl.MemberType> $types = _kKitchenSink_MethodB_Type.request;
    $types[0].encode($encoder, a, 0);
    $types[1].encode($encoder, b, 0);
    Function $zonedCallback;
    if ((callback == null) || identical(Zone.current, Zone.root)) {
      $zonedCallback = callback;
    } else {
      Zone $z = Zone.current;
      $zonedCallback = ((int result) {
        $z.bindCallback(() {
          callback(
            result,
          );
        })();
      });
    }
    ctrl.sendMessageWithResponse($encoder.message, $zonedCallback);
  }
}

class KitchenSinkEvents {
  $fidl.Binding<KitchenSink> _binding;
  void eventA(int a, int b) {
    final $fidl.Encoder $encoder = $fidl.Encoder();
    $encoder.encodeMessageHeader(_kKitchenSink_EventA_Ordinal, 0);
    $encoder.alloc(32 - $fidl.kMessageHeaderSize);
    final List<$fidl.MemberType> $types = _kKitchenSink_EventA_Type.response;
    $types[0].encode($encoder, a, 0);
    $types[1].encode($encoder, b, 0);
    _binding.sendMessage($encoder.message);
  }
}

class KitchenSinkBinding extends $fidl.Binding<KitchenSink> {
  KitchenSinkBinding() {
    events._binding = this;
  }

  final KitchenSinkEvents events = KitchenSinkEvents();

  Function _methodBResponder($fidl.MessageSink $respond, int $txid) {
    return (int result) {
      final $fidl.Encoder $encoder = $fidl.Encoder();
      $encoder.encodeMessageHeader(_kKitchenSink_MethodB_Ordinal, $txid);
      $encoder.alloc(24 - $fidl.kMessageHeaderSize);
      final List<$fidl.MemberType> $types = _kKitchenSink_MethodB_Type.response;
      $types[0].encode($encoder, result, 0);
      $respond($encoder.message);
    };
  }

  @override
  void handleMessage($fidl.Message $message, $fidl.MessageSink $respond) {
    final $fidl.Decoder $decoder = $fidl.Decoder($message);
    switch ($message.ordinal) {
      case _kKitchenSink_MethodA_Ordinal:
        final String _name = _kKitchenSink_MethodA_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kKitchenSink_MethodA_Type.request;
          $decoder.claimMemory(32);
          impl.methodA(
            $types[0].decode($decoder, 0),
            $types[1].decode($decoder, 0),
          );
          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          close();
          print('Exception handling method call $_name: $_e');
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      case _kKitchenSink_MethodB_Ordinal:
        final String _name = _kKitchenSink_MethodB_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kKitchenSink_MethodB_Type.request;
          $decoder.claimMemory(32);
          impl.methodB(
            $types[0].decode($decoder, 0),
            $types[1].decode($decoder, 0),
            _methodBResponder($respond, $message.txid),
          );
          // 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 KitchenSinkBinding');
    }
  }
}
