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

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


// 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:
        try {
          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) {
          final String _name = _kOvernetInternalProtocol_EventA_Type.name;
          ctrl.proxyError(new $fidl.FidlError('Exception handling event $_name: $_e'));
          ctrl.close();
          rethrow;
        }
        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:
        try {
          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) {
          final String _name = _kOvernetInternalProtocol_MethodB_Type.name;
          ctrl.proxyError(new $fidl.FidlError('Exception handling method response $_name: $_e'));
          ctrl.close();
          rethrow;
        }
        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('The proxy is closed.'));
      }

      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('The proxy is closed.'));
      }

      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:
            try {
              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();
              final String _name = _kOvernetInternalProtocol_MethodA_Type.name;
              print('Exception handling method call $_name: $_e');
              rethrow;
            }
            break;
          case _kOvernetInternalProtocol_MethodB_Ordinal:
            try {
              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();
                  final String _name = _kOvernetInternalProtocol_MethodB_Type.name;
                  print('Exception handling method call $_name: $_e');
                });
            // ignore: avoid_catches_without_on_clauses
            } catch(_e) {
              close();
              final String _name = _kOvernetInternalProtocol_MethodB_Type.name;
              print('Exception handling method call $_name: $_e');
              rethrow;
            }
            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:
        try {
          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) {
          final String _name = _kSocketControlProtocol_EventA_Type.name;
          ctrl.proxyError(new $fidl.FidlError('Exception handling event $_name: $_e'));
          ctrl.close();
          rethrow;
        }
        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:
        try {
          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) {
          final String _name = _kSocketControlProtocol_MethodB_Type.name;
          ctrl.proxyError(new $fidl.FidlError('Exception handling method response $_name: $_e'));
          ctrl.close();
          rethrow;
        }
        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('The proxy is closed.'));
      }

      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('The proxy is closed.'));
      }

      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:
            try {
              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();
              final String _name = _kSocketControlProtocol_MethodA_Type.name;
              print('Exception handling method call $_name: $_e');
              rethrow;
            }
            break;
          case _kSocketControlProtocol_MethodB_Ordinal:
            try {
              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();
                  final String _name = _kSocketControlProtocol_MethodB_Type.name;
                  print('Exception handling method call $_name: $_e');
                });
            // ignore: avoid_catches_without_on_clauses
            } catch(_e) {
              close();
              final String _name = _kSocketControlProtocol_MethodB_Type.name;
              print('Exception handling method call $_name: $_e');
              rethrow;
            }
            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:
        try {
          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) {
          final String _name = _kChannelProtocol_EventA_Type.name;
          ctrl.proxyError(new $fidl.FidlError('Exception handling event $_name: $_e'));
          ctrl.close();
          rethrow;
        }
        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:
        try {
          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) {
          final String _name = _kChannelProtocol_MethodB_Type.name;
          ctrl.proxyError(new $fidl.FidlError('Exception handling method response $_name: $_e'));
          ctrl.close();
          rethrow;
        }
        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('The proxy is closed.'));
      }

      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('The proxy is closed.'));
      }

      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:
            try {
              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();
              final String _name = _kChannelProtocol_MethodA_Type.name;
              print('Exception handling method call $_name: $_e');
              rethrow;
            }
            break;
          case _kChannelProtocol_MethodB_Ordinal:
            try {
              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();
                  final String _name = _kChannelProtocol_MethodB_Type.name;
                  print('Exception handling method call $_name: $_e');
                });
            // ignore: avoid_catches_without_on_clauses
            } catch(_e) {
              close();
              final String _name = _kChannelProtocol_MethodB_Type.name;
              print('Exception handling method call $_name: $_e');
              rethrow;
            }
            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:
        try {
          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) {
          final String _name = _kKitchenSink_EventA_Type.name;
          ctrl.proxyError(new $fidl.FidlError('Exception handling event $_name: $_e'));
          ctrl.close();
          rethrow;
        }
        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:
        try {
          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) {
          final String _name = _kKitchenSink_MethodB_Type.name;
          ctrl.proxyError(new $fidl.FidlError('Exception handling method response $_name: $_e'));
          ctrl.close();
          rethrow;
        }
        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('The proxy is closed.'));
      }

      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('The proxy is closed.'));
      }

      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:
            try {
              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();
              final String _name = _kKitchenSink_MethodA_Type.name;
              print('Exception handling method call $_name: $_e');
              rethrow;
            }
            break;
          case _kKitchenSink_MethodB_Ordinal:
            try {
              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();
                  final String _name = _kKitchenSink_MethodB_Type.name;
                  print('Exception handling method call $_name: $_e');
                });
            // ignore: avoid_catches_without_on_clauses
            } catch(_e) {
              close();
              final String _name = _kKitchenSink_MethodB_Type.name;
              print('Exception handling method call $_name: $_e');
              rethrow;
            }
            break;
      default:
        throw new $fidl.FidlError('Unexpected message name for KitchenSinkBinding');
    }
  }
}


