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

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

// 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.dart' as $strongly_connect_sync;

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

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 = const ErrorEnun._(1);
  static const ErrorEnun errBar = const ErrorEnun._(2);

  const ErrorEnun._(this.value);

  @override
  final int value;

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

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

  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) => new ErrorEnun(v);
}

const $fidl.EnumType<ErrorEnun> kErrorEnun_Type =
    const $fidl.EnumType<ErrorEnun>(
        type: const $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._(this.tag, Object data) : _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 'WithErrorSyntaxErrorAsPrimitiveResult.response($response)';
      case WithErrorSyntaxErrorAsPrimitiveResultTag.err:
        return 'WithErrorSyntaxErrorAsPrimitiveResult.err($err)';
      default:
        return null;
    }
  }

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

  @override
  Object get $data => _data;

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

// See FIDL-308:
// ignore: recursive_compile_time_constant
const $fidl.UnionType<WithErrorSyntaxErrorAsPrimitiveResult>
    kWithErrorSyntax_ErrorAsPrimitive_Result_Type =
    const $fidl.UnionType<WithErrorSyntaxErrorAsPrimitiveResult>(
  encodedSize: 8,
  members: const <$fidl.MemberType>[
    const $fidl.MemberType<WithErrorSyntaxErrorAsPrimitiveResponse>(
        type: kWithErrorSyntax_ErrorAsPrimitive_Response_Type, offset: 4),
    const $fidl.MemberType<int>(type: const $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._(this.tag, Object data) : _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 'WithErrorSyntaxErrorAsEnumResult.response($response)';
      case WithErrorSyntaxErrorAsEnumResultTag.err:
        return 'WithErrorSyntaxErrorAsEnumResult.err($err)';
      default:
        return null;
    }
  }

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

  @override
  Object get $data => _data;

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

// See FIDL-308:
// ignore: recursive_compile_time_constant
const $fidl.UnionType<WithErrorSyntaxErrorAsEnumResult>
    kWithErrorSyntax_ErrorAsEnum_Result_Type =
    const $fidl.UnionType<WithErrorSyntaxErrorAsEnumResult>(
  encodedSize: 8,
  members: const <$fidl.MemberType>[
    const $fidl.MemberType<WithErrorSyntaxErrorAsEnumResponse>(
        type: kWithErrorSyntax_ErrorAsEnum_Response_Type, offset: 4),
    const $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) =>
      new WithErrorSyntaxErrorAsPrimitiveResponse._(argv);
}

// See FIDL-308:
// ignore: recursive_compile_time_constant
const $fidl.StructType<WithErrorSyntaxErrorAsPrimitiveResponse>
    kWithErrorSyntax_ErrorAsPrimitive_Response_Type =
    const $fidl.StructType<WithErrorSyntaxErrorAsPrimitiveResponse>(
  encodedSize: 1,
  members: const <$fidl.MemberType>[
    const $fidl.MemberType<int>(type: const $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) =>
      new WithErrorSyntaxErrorAsEnumResponse._(argv);
}

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

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

// noRequestNoResponse: ()
const int _kWithAndWithoutRequestResponse_NoRequestNoResponse_Ordinal =
    503576693;
const $fidl.MethodType
    _kWithAndWithoutRequestResponse_NoRequestNoResponse_Type =
    const $fidl.MethodType(
  request: null,
  response: null,
  name: r"WithAndWithoutRequestResponse.NoRequestNoResponse",
);
// noRequestEmptyResponse: () -> ()
const int _kWithAndWithoutRequestResponse_NoRequestEmptyResponse_Ordinal =
    1308023765;
const $fidl.MethodType
    _kWithAndWithoutRequestResponse_NoRequestEmptyResponse_Type =
    const $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 =
    const $fidl.MethodType(
  request: null,
  response: const <$fidl.MemberType>[
    const $fidl.MemberType<String>(
        type: const $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 =
    const $fidl.MethodType(
  request: const <$fidl.MemberType>[
    const $fidl.MemberType<String>(
        type: const $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 =
    const $fidl.MethodType(
  request: const <$fidl.MemberType>[
    const $fidl.MemberType<String>(
        type: const $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 =
    const $fidl.MethodType(
  request: const <$fidl.MemberType>[
    const $fidl.MemberType<String>(
        type: const $fidl.StringType(maybeElementCount: null, nullable: false),
        offset: 16),
  ],
  response: const <$fidl.MemberType>[
    const $fidl.MemberType<String>(
        type: const $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 =
    const $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 =
    const $fidl.MethodType(
  request: null,
  response: const <$fidl.MemberType>[
    const $fidl.MemberType<String>(
        type: const $fidl.StringType(maybeElementCount: null, nullable: false),
        offset: 16),
  ],
  name: r"WithAndWithoutRequestResponse.OnWithResponse",
);

abstract class WithAndWithoutRequestResponse extends $fidl.Service {
  static const String $serviceName = null;
  @override
  $fidl.ServiceData get $serviceData =>
      const WithAndWithoutRequestResponseData();
  Future<void> noRequestNoResponse();
  Future<void> noRequestEmptyResponse();
  Future<String> noRequestWithResponse();
  Future<void> withRequestNoResponse(String arg);
  Future<void> withRequestEmptyResponse(String arg);
  Future<String> withRequestWithResponse(String arg);
  Stream<void> get onEmptyResponse;
  Stream<String> get onWithResponse;
}

class WithAndWithoutRequestResponseData
    implements $fidl.ServiceData<WithAndWithoutRequestResponse> {
  const WithAndWithoutRequestResponseData();

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

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

class WithAndWithoutRequestResponseProxy
    extends $fidl.AsyncProxy<WithAndWithoutRequestResponse>
    implements WithAndWithoutRequestResponse {
  WithAndWithoutRequestResponseProxy()
      : super(new $fidl.AsyncProxyController<WithAndWithoutRequestResponse>(
            $serviceName: null,
            $interfaceName: r'WithAndWithoutRequestResponse')) {
    ctrl.onResponse = _handleResponse;
    ctrl.whenClosed.then((_) {
      _onEmptyResponseEventStreamController.close();
      _onWithResponseEventStreamController.close();
    }, onError: (_) {});
  }

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

  void _handleEvent($fidl.Message $message) {
    final $fidl.Decoder $decoder = new $fidl.Decoder($message);
    switch ($message.ordinal) {
      case _kWithAndWithoutRequestResponse_OnEmptyResponse_Ordinal:
        final String _name =
            _kWithAndWithoutRequestResponse_OnEmptyResponse_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kWithAndWithoutRequestResponse_OnEmptyResponse_Type.response;
          $decoder.claimMemory(16);
          _onEmptyResponseEventStreamController.add(null);
          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          ctrl.proxyError(
              new $fidl.FidlError('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 List<$fidl.MemberType> $types =
              _kWithAndWithoutRequestResponse_OnWithResponse_Type.response;
          $decoder.claimMemory(32);
          _onWithResponseEventStreamController.add(
            $types[0].decode($decoder, 0),
          );
          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          ctrl.proxyError(
              new $fidl.FidlError('Exception handling event $_name: $_e'));
          ctrl.close();
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      default:
        ctrl.proxyError(new $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 Completer $completer = ctrl.getCompleter($txid);
    if ($completer == null) {
      $message.closeHandles();
      return;
    }
    final $fidl.Decoder $decoder = new $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);
          $completer.complete(null);
          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          ctrl.proxyError(new $fidl.FidlError(
              '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);
          $completer.complete(
            $types[0].decode($decoder, 0),
          );
          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          ctrl.proxyError(new $fidl.FidlError(
              '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);
          $completer.complete(null);
          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          ctrl.proxyError(new $fidl.FidlError(
              '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);
          $completer.complete(
            $types[0].decode($decoder, 0),
          );
          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          ctrl.proxyError(new $fidl.FidlError(
              'Exception handling method response $_name: $_e'));
          ctrl.close();
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      default:
        ctrl.proxyError(new $fidl.FidlError(
            'Unexpected message ordinal: ${$message.ordinal}'));
        ctrl.close();
        break;
    }
  }

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

    final $fidl.Encoder $encoder = new $fidl.Encoder();
    $encoder.encodeMessageHeader(
        _kWithAndWithoutRequestResponse_NoRequestNoResponse_Ordinal, 0);
    return new Future.sync(() {
      ctrl.sendMessage($encoder.message);
    });
  }

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

    final $fidl.Encoder $encoder = new $fidl.Encoder();
    $encoder.encodeMessageHeader(
        _kWithAndWithoutRequestResponse_NoRequestEmptyResponse_Ordinal, 0);
    final $completer = new Completer<void>();
    ctrl.sendMessageWithResponse($encoder.message, $completer);
    return $completer.future;
  }

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

    final $fidl.Encoder $encoder = new $fidl.Encoder();
    $encoder.encodeMessageHeader(
        _kWithAndWithoutRequestResponse_NoRequestWithResponse_Ordinal, 0);
    final $completer = new Completer<String>();
    ctrl.sendMessageWithResponse($encoder.message, $completer);
    return $completer.future;
  }

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

    final $fidl.Encoder $encoder = new $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);
    return new Future.sync(() {
      ctrl.sendMessage($encoder.message);
    });
  }

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

    final $fidl.Encoder $encoder = new $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);
    final $completer = new Completer<void>();
    ctrl.sendMessageWithResponse($encoder.message, $completer);
    return $completer.future;
  }

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

    final $fidl.Encoder $encoder = new $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);
    final $completer = new Completer<String>();
    ctrl.sendMessageWithResponse($encoder.message, $completer);
    return $completer.future;
  }

  final _onEmptyResponseEventStreamController =
      new StreamController<void>.broadcast();
  @override
  Stream<void> get onEmptyResponse =>
      _onEmptyResponseEventStreamController.stream;

  final _onWithResponseEventStreamController =
      new StreamController<String>.broadcast();
  @override
  Stream<String> get onWithResponse =>
      _onWithResponseEventStreamController.stream;
}

class WithAndWithoutRequestResponseBinding
    extends $fidl.AsyncBinding<WithAndWithoutRequestResponse> {
  WithAndWithoutRequestResponseBinding()
      : super(r"WithAndWithoutRequestResponse") {
    final List<StreamSubscription<dynamic>> $subscriptions = [];
    void $unsubscribe() {
      for (final $sub in $subscriptions) {
        $sub.cancel();
      }
      $subscriptions.clear();
    }

    whenBound.then((_) {
      if (impl.onEmptyResponse != null) {
        $subscriptions.add(impl.onEmptyResponse.listen(($response) {
          final $fidl.Encoder $encoder = new $fidl.Encoder();
          $encoder.encodeMessageHeader(
              _kWithAndWithoutRequestResponse_OnEmptyResponse_Ordinal, 0);
          $encoder.alloc(16 - $fidl.kMessageHeaderSize);
          final List<$fidl.MemberType> $types =
              _kWithAndWithoutRequestResponse_OnEmptyResponse_Type.response;

          sendMessage($encoder.message);
        }));
      }
      if (impl.onWithResponse != null) {
        $subscriptions.add(impl.onWithResponse.listen(($response) {
          final $fidl.Encoder $encoder = new $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, $response, 0);
          sendMessage($encoder.message);
        }));
      }
    });
    whenClosed.then((_) => $unsubscribe());
  }

  @override
  void handleMessage($fidl.Message $message, $fidl.MessageSink $respond) {
    final $fidl.Decoder $decoder = new $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);
          final Future<void> $future = 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);
          final Future<void> $future = impl.noRequestEmptyResponse();
          $future.then(($response) {
            final $fidl.Encoder $encoder = new $fidl.Encoder();
            $encoder.encodeMessageHeader(
                _kWithAndWithoutRequestResponse_NoRequestEmptyResponse_Ordinal,
                $message.txid);
            $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 _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);
          final Future<String> $future = impl.noRequestWithResponse();
          $future.then(($response) {
            final $fidl.Encoder $encoder = new $fidl.Encoder();
            $encoder.encodeMessageHeader(
                _kWithAndWithoutRequestResponse_NoRequestWithResponse_Ordinal,
                $message.txid);
            $encoder.alloc(32 - $fidl.kMessageHeaderSize);
            final List<$fidl.MemberType> $types =
                _kWithAndWithoutRequestResponse_NoRequestWithResponse_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 _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);
          final Future<void> $future = 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);
          final Future<void> $future = impl.withRequestEmptyResponse(
            $types[0].decode($decoder, 0),
          );
          $future.then(($response) {
            final $fidl.Encoder $encoder = new $fidl.Encoder();
            $encoder.encodeMessageHeader(
                _kWithAndWithoutRequestResponse_WithRequestEmptyResponse_Ordinal,
                $message.txid);
            $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 _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);
          final Future<String> $future = impl.withRequestWithResponse(
            $types[0].decode($decoder, 0),
          );
          $future.then(($response) {
            final $fidl.Encoder $encoder = new $fidl.Encoder();
            $encoder.encodeMessageHeader(
                _kWithAndWithoutRequestResponse_WithRequestWithResponse_Ordinal,
                $message.txid);
            $encoder.alloc(32 - $fidl.kMessageHeaderSize);
            final List<$fidl.MemberType> $types =
                _kWithAndWithoutRequestResponse_WithRequestWithResponse_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 new $fidl.FidlError(
            'Unexpected message name for WithAndWithoutRequestResponseBinding');
    }
  }
}

// errorAsPrimitive: () -> (WithErrorSyntaxErrorAsPrimitiveResult result)
const int _kWithErrorSyntax_ErrorAsPrimitive_Ordinal = 2069369145;
const $fidl.MethodType _kWithErrorSyntax_ErrorAsPrimitive_Type =
    const $fidl.MethodType(
  request: null,
  response: const <$fidl.MemberType>[
    const $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 =
    const $fidl.MethodType(
  request: null,
  response: const <$fidl.MemberType>[
    const $fidl.MemberType<WithErrorSyntaxErrorAsEnumResult>(
        type: kWithErrorSyntax_ErrorAsEnum_Result_Type, offset: 16),
  ],
  name: r"WithErrorSyntax.ErrorAsEnum",
);

abstract class WithErrorSyntax extends $fidl.Service {
  static const String $serviceName = null;
  @override
  $fidl.ServiceData get $serviceData => const WithErrorSyntaxData();
  Future<WithErrorSyntaxErrorAsPrimitiveResult> errorAsPrimitive();
  Future<WithErrorSyntaxErrorAsEnumResult> errorAsEnum();
}

class WithErrorSyntaxData implements $fidl.ServiceData<WithErrorSyntax> {
  const WithErrorSyntaxData();

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

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

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

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

  void _handleEvent($fidl.Message $message) {
    final $fidl.Decoder $decoder = new $fidl.Decoder($message);
    switch ($message.ordinal) {
      default:
        ctrl.proxyError(new $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 Completer $completer = ctrl.getCompleter($txid);
    if ($completer == null) {
      $message.closeHandles();
      return;
    }
    final $fidl.Decoder $decoder = new $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);
          $completer.complete(
            $types[0].decode($decoder, 0),
          );
          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          ctrl.proxyError(new $fidl.FidlError(
              '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);
          $completer.complete(
            $types[0].decode($decoder, 0),
          );
          // ignore: avoid_catches_without_on_clauses
        } catch (_e) {
          ctrl.proxyError(new $fidl.FidlError(
              'Exception handling method response $_name: $_e'));
          ctrl.close();
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      default:
        ctrl.proxyError(new $fidl.FidlError(
            'Unexpected message ordinal: ${$message.ordinal}'));
        ctrl.close();
        break;
    }
  }

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

    final $fidl.Encoder $encoder = new $fidl.Encoder();
    $encoder.encodeMessageHeader(_kWithErrorSyntax_ErrorAsPrimitive_Ordinal, 0);
    final $completer = new Completer<WithErrorSyntaxErrorAsPrimitiveResult>();
    ctrl.sendMessageWithResponse($encoder.message, $completer);
    return $completer.future;
  }

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

    final $fidl.Encoder $encoder = new $fidl.Encoder();
    $encoder.encodeMessageHeader(_kWithErrorSyntax_ErrorAsEnum_Ordinal, 0);
    final $completer = new Completer<WithErrorSyntaxErrorAsEnumResult>();
    ctrl.sendMessageWithResponse($encoder.message, $completer);
    return $completer.future;
  }
}

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

  @override
  void handleMessage($fidl.Message $message, $fidl.MessageSink $respond) {
    final $fidl.Decoder $decoder = new $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);
          final Future<WithErrorSyntaxErrorAsPrimitiveResult> $future =
              impl.errorAsPrimitive();
          $future.then(($response) {
            final $fidl.Encoder $encoder = new $fidl.Encoder();
            $encoder.encodeMessageHeader(
                _kWithErrorSyntax_ErrorAsPrimitive_Ordinal, $message.txid);
            $encoder.alloc(24 - $fidl.kMessageHeaderSize);
            final List<$fidl.MemberType> $types =
                _kWithErrorSyntax_ErrorAsPrimitive_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 _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);
          final Future<WithErrorSyntaxErrorAsEnumResult> $future =
              impl.errorAsEnum();
          $future.then(($response) {
            final $fidl.Encoder $encoder = new $fidl.Encoder();
            $encoder.encodeMessageHeader(
                _kWithErrorSyntax_ErrorAsEnum_Ordinal, $message.txid);
            $encoder.alloc(24 - $fidl.kMessageHeaderSize);
            final List<$fidl.MemberType> $types =
                _kWithErrorSyntax_ErrorAsEnum_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 new $fidl.FidlError(
            'Unexpected message name for WithErrorSyntaxBinding');
    }
  }
}

// methodA: (int a, int b)
const int _kOvernetInternalProtocol_MethodA_Ordinal = 1993818253;
const $fidl.MethodType _kOvernetInternalProtocol_MethodA_Type =
    const $fidl.MethodType(
  request: const <$fidl.MemberType>[
    const $fidl.MemberType<int>(type: const $fidl.Int64Type(), offset: 16),
    const $fidl.MemberType<int>(type: const $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 =
    const $fidl.MethodType(
  request: null,
  response: const <$fidl.MemberType>[
    const $fidl.MemberType<int>(type: const $fidl.Int64Type(), offset: 16),
    const $fidl.MemberType<int>(type: const $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 =
    const $fidl.MethodType(
  request: const <$fidl.MemberType>[
    const $fidl.MemberType<int>(type: const $fidl.Int64Type(), offset: 16),
    const $fidl.MemberType<int>(type: const $fidl.Int64Type(), offset: 24),
  ],
  response: const <$fidl.MemberType>[
    const $fidl.MemberType<int>(type: const $fidl.Int64Type(), offset: 16),
  ],
  name: r"OvernetInternalProtocol.MethodB",
);

class OvernetInternalProtocol$EventA$Response {
  final int a;
  final int b;
  OvernetInternalProtocol$EventA$Response(
    this.a,
    this.b,
  );
}

abstract class OvernetInternalProtocol extends $fidl.Service {
  static const String $serviceName = null;
  @override
  $fidl.ServiceData get $serviceData => const OvernetInternalProtocolData();
  Future<void> methodA(int a, int b);
  Stream<OvernetInternalProtocol$EventA$Response> get eventA;
  Future<int> methodB(int a, int b);
}

class OvernetInternalProtocolData
    implements $fidl.ServiceData<OvernetInternalProtocol> {
  const OvernetInternalProtocolData();

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

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

class OvernetInternalProtocolProxy extends $fidl
    .AsyncProxy<OvernetInternalProtocol> implements OvernetInternalProtocol {
  OvernetInternalProtocolProxy()
      : super(new $fidl.AsyncProxyController<OvernetInternalProtocol>(
            $serviceName: null, $interfaceName: r'OvernetInternalProtocol')) {
    ctrl.onResponse = _handleResponse;
    ctrl.whenClosed.then((_) {
      _eventAEventStreamController.close();
    }, onError: (_) {});
  }

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

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

  @override
  Future<void> methodA(int a, int b) async {
    if (!ctrl.isBound) {
      return new Future.error(
          new $fidl.FidlStateException(
              'Proxy<${ctrl.$interfaceName}> is closed.'),
          StackTrace.current);
    }

    final $fidl.Encoder $encoder = new $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);
    return new Future.sync(() {
      ctrl.sendMessage($encoder.message);
    });
  }

  final _eventAEventStreamController =
      new StreamController<OvernetInternalProtocol$EventA$Response>.broadcast();
  @override
  Stream<OvernetInternalProtocol$EventA$Response> get eventA =>
      _eventAEventStreamController.stream;

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

    final $fidl.Encoder $encoder = new $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);
    final $completer = new Completer<int>();
    ctrl.sendMessageWithResponse($encoder.message, $completer);
    return $completer.future;
  }
}

class OvernetInternalProtocolBinding
    extends $fidl.AsyncBinding<OvernetInternalProtocol> {
  OvernetInternalProtocolBinding() : super(r"OvernetInternalProtocol") {
    final List<StreamSubscription<dynamic>> $subscriptions = [];
    void $unsubscribe() {
      for (final $sub in $subscriptions) {
        $sub.cancel();
      }
      $subscriptions.clear();
    }

    whenBound.then((_) {
      if (impl.eventA != null) {
        $subscriptions.add(impl.eventA.listen(($response) {
          final $fidl.Encoder $encoder = new $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, $response.a, 0);
          $types[1].encode($encoder, $response.b, 0);
          sendMessage($encoder.message);
        }));
      }
    });
    whenClosed.then((_) => $unsubscribe());
  }

  @override
  void handleMessage($fidl.Message $message, $fidl.MessageSink $respond) {
    final $fidl.Decoder $decoder = new $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);
          final Future<void> $future = 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);
          final Future<int> $future = impl.methodB(
            $types[0].decode($decoder, 0),
            $types[1].decode($decoder, 0),
          );
          $future.then(($response) {
            final $fidl.Encoder $encoder = new $fidl.Encoder();
            $encoder.encodeMessageHeader(
                _kOvernetInternalProtocol_MethodB_Ordinal, $message.txid);
            $encoder.alloc(24 - $fidl.kMessageHeaderSize);
            final List<$fidl.MemberType> $types =
                _kOvernetInternalProtocol_MethodB_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 new $fidl.FidlError(
            'Unexpected message name for OvernetInternalProtocolBinding');
    }
  }
}

// methodA: (int a, int b)
const int _kSocketControlProtocol_MethodA_Ordinal = 1007842318;
const $fidl.MethodType _kSocketControlProtocol_MethodA_Type =
    const $fidl.MethodType(
  request: const <$fidl.MemberType>[
    const $fidl.MemberType<int>(type: const $fidl.Int64Type(), offset: 16),
    const $fidl.MemberType<int>(type: const $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 =
    const $fidl.MethodType(
  request: null,
  response: const <$fidl.MemberType>[
    const $fidl.MemberType<int>(type: const $fidl.Int64Type(), offset: 16),
    const $fidl.MemberType<int>(type: const $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 =
    const $fidl.MethodType(
  request: const <$fidl.MemberType>[
    const $fidl.MemberType<int>(type: const $fidl.Int64Type(), offset: 16),
    const $fidl.MemberType<int>(type: const $fidl.Int64Type(), offset: 24),
  ],
  response: const <$fidl.MemberType>[
    const $fidl.MemberType<int>(type: const $fidl.Int64Type(), offset: 16),
  ],
  name: r"SocketControlProtocol.MethodB",
);

class SocketControlProtocol$EventA$Response {
  final int a;
  final int b;
  SocketControlProtocol$EventA$Response(
    this.a,
    this.b,
  );
}

abstract class SocketControlProtocol extends $fidl.Service {
  static const String $serviceName = null;
  @override
  $fidl.ServiceData get $serviceData => const SocketControlProtocolData();
  Future<void> methodA(int a, int b);
  Stream<SocketControlProtocol$EventA$Response> get eventA;
  Future<int> methodB(int a, int b);
}

class SocketControlProtocolData
    implements $fidl.ServiceData<SocketControlProtocol> {
  const SocketControlProtocolData();

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

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

class SocketControlProtocolProxy extends $fidl.AsyncProxy<SocketControlProtocol>
    implements SocketControlProtocol {
  SocketControlProtocolProxy()
      : super(new $fidl.AsyncProxyController<SocketControlProtocol>(
            $serviceName: null, $interfaceName: r'SocketControlProtocol')) {
    ctrl.onResponse = _handleResponse;
    ctrl.whenClosed.then((_) {
      _eventAEventStreamController.close();
    }, onError: (_) {});
  }

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

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

  @override
  Future<void> methodA(int a, int b) async {
    if (!ctrl.isBound) {
      return new Future.error(
          new $fidl.FidlStateException(
              'Proxy<${ctrl.$interfaceName}> is closed.'),
          StackTrace.current);
    }

    final $fidl.Encoder $encoder = new $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);
    return new Future.sync(() {
      ctrl.sendMessage($encoder.message);
    });
  }

  final _eventAEventStreamController =
      new StreamController<SocketControlProtocol$EventA$Response>.broadcast();
  @override
  Stream<SocketControlProtocol$EventA$Response> get eventA =>
      _eventAEventStreamController.stream;

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

    final $fidl.Encoder $encoder = new $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);
    final $completer = new Completer<int>();
    ctrl.sendMessageWithResponse($encoder.message, $completer);
    return $completer.future;
  }
}

class SocketControlProtocolBinding
    extends $fidl.AsyncBinding<SocketControlProtocol> {
  SocketControlProtocolBinding() : super(r"SocketControlProtocol") {
    final List<StreamSubscription<dynamic>> $subscriptions = [];
    void $unsubscribe() {
      for (final $sub in $subscriptions) {
        $sub.cancel();
      }
      $subscriptions.clear();
    }

    whenBound.then((_) {
      if (impl.eventA != null) {
        $subscriptions.add(impl.eventA.listen(($response) {
          final $fidl.Encoder $encoder = new $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, $response.a, 0);
          $types[1].encode($encoder, $response.b, 0);
          sendMessage($encoder.message);
        }));
      }
    });
    whenClosed.then((_) => $unsubscribe());
  }

  @override
  void handleMessage($fidl.Message $message, $fidl.MessageSink $respond) {
    final $fidl.Decoder $decoder = new $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);
          final Future<void> $future = 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);
          final Future<int> $future = impl.methodB(
            $types[0].decode($decoder, 0),
            $types[1].decode($decoder, 0),
          );
          $future.then(($response) {
            final $fidl.Encoder $encoder = new $fidl.Encoder();
            $encoder.encodeMessageHeader(
                _kSocketControlProtocol_MethodB_Ordinal, $message.txid);
            $encoder.alloc(24 - $fidl.kMessageHeaderSize);
            final List<$fidl.MemberType> $types =
                _kSocketControlProtocol_MethodB_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 new $fidl.FidlError(
            'Unexpected message name for SocketControlProtocolBinding');
    }
  }
}

// methodA: (int a, int b)
const int _kChannelProtocol_MethodA_Ordinal = 1432785874;
const $fidl.MethodType _kChannelProtocol_MethodA_Type = const $fidl.MethodType(
  request: const <$fidl.MemberType>[
    const $fidl.MemberType<int>(type: const $fidl.Int64Type(), offset: 16),
    const $fidl.MemberType<int>(type: const $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 = const $fidl.MethodType(
  request: null,
  response: const <$fidl.MemberType>[
    const $fidl.MemberType<int>(type: const $fidl.Int64Type(), offset: 16),
    const $fidl.MemberType<int>(type: const $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 = const $fidl.MethodType(
  request: const <$fidl.MemberType>[
    const $fidl.MemberType<int>(type: const $fidl.Int64Type(), offset: 16),
    const $fidl.MemberType<int>(type: const $fidl.Int64Type(), offset: 24),
  ],
  response: const <$fidl.MemberType>[
    const $fidl.MemberType<int>(type: const $fidl.Int64Type(), offset: 16),
  ],
  name: r"ChannelProtocol.MethodB",
);

class ChannelProtocol$EventA$Response {
  final int a;
  final int b;
  ChannelProtocol$EventA$Response(
    this.a,
    this.b,
  );
}

abstract class ChannelProtocol extends $fidl.Service {
  static const String $serviceName = null;
  @override
  $fidl.ServiceData get $serviceData => const ChannelProtocolData();
  Future<void> methodA(int a, int b);
  Stream<ChannelProtocol$EventA$Response> get eventA;
  Future<int> methodB(int a, int b);
}

class ChannelProtocolData implements $fidl.ServiceData<ChannelProtocol> {
  const ChannelProtocolData();

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

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

class ChannelProtocolProxy extends $fidl.AsyncProxy<ChannelProtocol>
    implements ChannelProtocol {
  ChannelProtocolProxy()
      : super(new $fidl.AsyncProxyController<ChannelProtocol>(
            $serviceName: null, $interfaceName: r'ChannelProtocol')) {
    ctrl.onResponse = _handleResponse;
    ctrl.whenClosed.then((_) {
      _eventAEventStreamController.close();
    }, onError: (_) {});
  }

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

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

  @override
  Future<void> methodA(int a, int b) async {
    if (!ctrl.isBound) {
      return new Future.error(
          new $fidl.FidlStateException(
              'Proxy<${ctrl.$interfaceName}> is closed.'),
          StackTrace.current);
    }

    final $fidl.Encoder $encoder = new $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);
    return new Future.sync(() {
      ctrl.sendMessage($encoder.message);
    });
  }

  final _eventAEventStreamController =
      new StreamController<ChannelProtocol$EventA$Response>.broadcast();
  @override
  Stream<ChannelProtocol$EventA$Response> get eventA =>
      _eventAEventStreamController.stream;

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

    final $fidl.Encoder $encoder = new $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);
    final $completer = new Completer<int>();
    ctrl.sendMessageWithResponse($encoder.message, $completer);
    return $completer.future;
  }
}

class ChannelProtocolBinding extends $fidl.AsyncBinding<ChannelProtocol> {
  ChannelProtocolBinding() : super(r"ChannelProtocol") {
    final List<StreamSubscription<dynamic>> $subscriptions = [];
    void $unsubscribe() {
      for (final $sub in $subscriptions) {
        $sub.cancel();
      }
      $subscriptions.clear();
    }

    whenBound.then((_) {
      if (impl.eventA != null) {
        $subscriptions.add(impl.eventA.listen(($response) {
          final $fidl.Encoder $encoder = new $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, $response.a, 0);
          $types[1].encode($encoder, $response.b, 0);
          sendMessage($encoder.message);
        }));
      }
    });
    whenClosed.then((_) => $unsubscribe());
  }

  @override
  void handleMessage($fidl.Message $message, $fidl.MessageSink $respond) {
    final $fidl.Decoder $decoder = new $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);
          final Future<void> $future = 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);
          final Future<int> $future = impl.methodB(
            $types[0].decode($decoder, 0),
            $types[1].decode($decoder, 0),
          );
          $future.then(($response) {
            final $fidl.Encoder $encoder = new $fidl.Encoder();
            $encoder.encodeMessageHeader(
                _kChannelProtocol_MethodB_Ordinal, $message.txid);
            $encoder.alloc(24 - $fidl.kMessageHeaderSize);
            final List<$fidl.MemberType> $types =
                _kChannelProtocol_MethodB_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 new $fidl.FidlError(
            'Unexpected message name for ChannelProtocolBinding');
    }
  }
}

// methodA: (int a, int b)
const int _kKitchenSink_MethodA_Ordinal = 450577456;
const $fidl.MethodType _kKitchenSink_MethodA_Type = const $fidl.MethodType(
  request: const <$fidl.MemberType>[
    const $fidl.MemberType<int>(type: const $fidl.Int64Type(), offset: 16),
    const $fidl.MemberType<int>(type: const $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 = const $fidl.MethodType(
  request: null,
  response: const <$fidl.MemberType>[
    const $fidl.MemberType<int>(type: const $fidl.Int64Type(), offset: 16),
    const $fidl.MemberType<int>(type: const $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 = const $fidl.MethodType(
  request: const <$fidl.MemberType>[
    const $fidl.MemberType<int>(type: const $fidl.Int64Type(), offset: 16),
    const $fidl.MemberType<int>(type: const $fidl.Int64Type(), offset: 24),
  ],
  response: const <$fidl.MemberType>[
    const $fidl.MemberType<int>(type: const $fidl.Int64Type(), offset: 16),
  ],
  name: r"KitchenSink.MethodB",
);

class KitchenSink$EventA$Response {
  final int a;
  final int b;
  KitchenSink$EventA$Response(
    this.a,
    this.b,
  );
}

abstract class KitchenSink extends $fidl.Service {
  static const String $serviceName = null;
  @override
  $fidl.ServiceData get $serviceData => const KitchenSinkData();
  Future<void> methodA(int a, int b);
  Stream<KitchenSink$EventA$Response> get eventA;
  Future<int> methodB(int a, int b);
}

class KitchenSinkData implements $fidl.ServiceData<KitchenSink> {
  const KitchenSinkData();

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

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

class KitchenSinkProxy extends $fidl.AsyncProxy<KitchenSink>
    implements KitchenSink {
  KitchenSinkProxy()
      : super(new $fidl.AsyncProxyController<KitchenSink>(
            $serviceName: null, $interfaceName: r'KitchenSink')) {
    ctrl.onResponse = _handleResponse;
    ctrl.whenClosed.then((_) {
      _eventAEventStreamController.close();
    }, onError: (_) {});
  }

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

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

  @override
  Future<void> methodA(int a, int b) async {
    if (!ctrl.isBound) {
      return new Future.error(
          new $fidl.FidlStateException(
              'Proxy<${ctrl.$interfaceName}> is closed.'),
          StackTrace.current);
    }

    final $fidl.Encoder $encoder = new $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);
    return new Future.sync(() {
      ctrl.sendMessage($encoder.message);
    });
  }

  final _eventAEventStreamController =
      new StreamController<KitchenSink$EventA$Response>.broadcast();
  @override
  Stream<KitchenSink$EventA$Response> get eventA =>
      _eventAEventStreamController.stream;

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

    final $fidl.Encoder $encoder = new $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);
    final $completer = new Completer<int>();
    ctrl.sendMessageWithResponse($encoder.message, $completer);
    return $completer.future;
  }
}

class KitchenSinkBinding extends $fidl.AsyncBinding<KitchenSink> {
  KitchenSinkBinding() : super(r"KitchenSink") {
    final List<StreamSubscription<dynamic>> $subscriptions = [];
    void $unsubscribe() {
      for (final $sub in $subscriptions) {
        $sub.cancel();
      }
      $subscriptions.clear();
    }

    whenBound.then((_) {
      if (impl.eventA != null) {
        $subscriptions.add(impl.eventA.listen(($response) {
          final $fidl.Encoder $encoder = new $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, $response.a, 0);
          $types[1].encode($encoder, $response.b, 0);
          sendMessage($encoder.message);
        }));
      }
    });
    whenClosed.then((_) => $unsubscribe());
  }

  @override
  void handleMessage($fidl.Message $message, $fidl.MessageSink $respond) {
    final $fidl.Decoder $decoder = new $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);
          final Future<void> $future = 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);
          final Future<int> $future = impl.methodB(
            $types[0].decode($decoder, 0),
            $types[1].decode($decoder, 0),
          );
          $future.then(($response) {
            final $fidl.Encoder $encoder = new $fidl.Encoder();
            $encoder.encodeMessageHeader(
                _kKitchenSink_MethodB_Ordinal, $message.txid);
            $encoder.alloc(24 - $fidl.kMessageHeaderSize);
            final List<$fidl.MemberType> $types =
                _kKitchenSink_MethodB_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 new $fidl.FidlError(
            'Unexpected message name for KitchenSinkBinding');
    }
  }
}
