// WARNING: This file is machine generated by fidlgen_dart.
// @dart = 2.8

library fidl_fidl_test_emptystruct_async;

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

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

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

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

  final int reserved;

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

  static const $fieldType0 = $fidl.Uint8Type();

  @override
  void $encode($fidl.Encoder $encoder, int $offset) {
    $fieldType0.encode($encoder, reserved, $offset + 0);
  }

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

  static Empty _structDecode($fidl.Decoder $decoder, int $offset) {
    return Empty(reserved: $fieldType0.decode($decoder, $offset + 0));
  }
}

// See fxbug.dev/7644:
// ignore: recursive_compile_time_constant
const $fidl.StructType<Empty> kEmpty_Type = $fidl.StructType<Empty>(
  inlineSize: 1,
  structDecode: Empty._structDecode,
);

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

// send: (Empty e)
const int _kEmptyProtocol_Send_Ordinal = 0x1e4e78d0556b6f28;
const $fidl.MethodType _kEmptyProtocol_Send_Type = $fidl.MethodType(
  request: <$fidl.MemberType>[
    $fidl.MemberType<Empty>(type: kEmpty_Type, offset: 0),
  ],
  response: null,
  name: r"EmptyProtocol.Send",
  requestInlineSize: 8,
  responseInlineSize: 0,
);
// receive:  -> (Empty e)
const int _kEmptyProtocol_Receive_Ordinal = 0x45bd261c537791e0;
const $fidl.MethodType _kEmptyProtocol_Receive_Type = $fidl.MethodType(
  request: null,
  response: <$fidl.MemberType>[
    $fidl.MemberType<Empty>(type: kEmpty_Type, offset: 0),
  ],
  name: r"EmptyProtocol.Receive",
  requestInlineSize: 0,
  responseInlineSize: 8,
);
// sendAndReceive: (Empty e) -> (Empty e)
const int _kEmptyProtocol_SendAndReceive_Ordinal = 0x56ca6bd78bac3571;
const $fidl.MethodType _kEmptyProtocol_SendAndReceive_Type = $fidl.MethodType(
  request: <$fidl.MemberType>[
    $fidl.MemberType<Empty>(type: kEmpty_Type, offset: 0),
  ],
  response: <$fidl.MemberType>[
    $fidl.MemberType<Empty>(type: kEmpty_Type, offset: 0),
  ],
  name: r"EmptyProtocol.SendAndReceive",
  requestInlineSize: 8,
  responseInlineSize: 8,
);

abstract class EmptyProtocol extends $fidl.Service {
  static const String $serviceName = null;
  @override
  $fidl.ServiceData get $serviceData => EmptyProtocolData();
  $async.Future<void> send(Empty e);
  $async.Stream<Empty> get receive;
  $async.Future<Empty> sendAndReceive(Empty e);
}

class EmptyProtocolData implements $fidl.ServiceData<EmptyProtocol> {
  const EmptyProtocolData();

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

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

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

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

  void _handleEvent($fidl.Message $message) {
    final $fidl.Decoder $decoder = $fidl.Decoder($message)
      ..claimMemory($fidl.kMessageHeaderSize);
    switch ($message.ordinal) {
      case _kEmptyProtocol_Receive_Ordinal:
        final String _name = _kEmptyProtocol_Receive_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kEmptyProtocol_Receive_Type.response;
          $decoder.claimMemory(
              _kEmptyProtocol_Receive_Type.decodeResponseInlineSize($decoder));
          _receiveEventStreamController
              .add($types[0].decode($decoder, $fidl.kMessageHeaderSize));
        } catch (_e) {
          ctrl.proxyError(
              $fidl.FidlError('Exception handling event $_name: $_e'));
          ctrl.close();
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      default:
        ctrl.proxyError(
            $fidl.FidlError('Unexpected message ordinal: ${$message.ordinal}'));
        ctrl.close();
        break;
    }
  }

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

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

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

    final $fidl.Encoder $encoder = $fidl.Encoder();
    $encoder.encodeMessageHeader(_kEmptyProtocol_Send_Ordinal, 0);
    $encoder
        .alloc(_kEmptyProtocol_Send_Type.encodingRequestInlineSize($encoder));
    final List<$fidl.MemberType> $types = _kEmptyProtocol_Send_Type.request;
    $types[0].encode($encoder, e, $fidl.kMessageHeaderSize);
    return $async.Future.sync(() {
      ctrl.sendMessage($encoder.message);
    });
  }

  final _receiveEventStreamController =
      $async.StreamController<Empty>.broadcast();
  @override
  $async.Stream<Empty> get receive => _receiveEventStreamController.stream;

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

    final $fidl.Encoder $encoder = $fidl.Encoder();
    $encoder.encodeMessageHeader(_kEmptyProtocol_SendAndReceive_Ordinal, 0);
    $encoder.alloc(_kEmptyProtocol_SendAndReceive_Type
        .encodingRequestInlineSize($encoder));
    final List<$fidl.MemberType> $types =
        _kEmptyProtocol_SendAndReceive_Type.request;
    $types[0].encode($encoder, e, $fidl.kMessageHeaderSize);
    final $completer = $async.Completer<Empty>();
    ctrl.sendMessageWithResponse($encoder.message, $completer);
    return $completer.future;
  }
}

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

    whenBound.then((_) {
      if (impl.receive != null) {
        $subscriptions.add(impl.receive.listen(($response) {
          final $fidl.Encoder $encoder = $fidl.Encoder();
          $encoder.encodeMessageHeader(_kEmptyProtocol_Receive_Ordinal, 0);
          $encoder.alloc(_kEmptyProtocol_Receive_Type
              .encodingResponseInlineSize($encoder));
          final List<$fidl.MemberType> $types =
              _kEmptyProtocol_Receive_Type.response;
          $types[0].encode($encoder, $response, $fidl.kMessageHeaderSize);
          sendMessage($encoder.message);
        }));
      }
    });
    whenClosed.then((_) => $unsubscribe());
  }

  @override
  void handleMessage($fidl.Message $message, $fidl.MessageSink $respond) {
    final $fidl.Decoder $decoder = $fidl.Decoder($message)
      ..claimMemory($fidl.kMessageHeaderSize);
    switch ($message.ordinal) {
      case _kEmptyProtocol_Send_Ordinal:
        final String _name = _kEmptyProtocol_Send_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kEmptyProtocol_Send_Type.request;
          $decoder.claimMemory(
              _kEmptyProtocol_Send_Type.decodeRequestInlineSize($decoder));
          final $async.Future<void> $future = impl.send(
            $types[0].decode($decoder, $fidl.kMessageHeaderSize),
          );
        } catch (_e) {
          close();
          print('Exception handling method call $_name: $_e');
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      case _kEmptyProtocol_SendAndReceive_Ordinal:
        final String _name = _kEmptyProtocol_SendAndReceive_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kEmptyProtocol_SendAndReceive_Type.request;
          $decoder.claimMemory(_kEmptyProtocol_SendAndReceive_Type
              .decodeRequestInlineSize($decoder));
          final $async.Future<Empty> $future = impl.sendAndReceive(
            $types[0].decode($decoder, $fidl.kMessageHeaderSize),
          );
          $future.then(($response) {
            final $fidl.Encoder $encoder = $fidl.Encoder();
            $encoder.encodeMessageHeader(
                _kEmptyProtocol_SendAndReceive_Ordinal, $message.txid);
            $encoder.alloc(_kEmptyProtocol_SendAndReceive_Type
                .encodingResponseInlineSize($encoder));
            final List<$fidl.MemberType> $types =
                _kEmptyProtocol_SendAndReceive_Type.response;
            $types[0].encode($encoder, $response, $fidl.kMessageHeaderSize);
            $respond($encoder.message);
          }, onError: (_e) {
            close();
            print('Exception handling method call $_name: $_e');
          });
        } catch (_e) {
          close();
          print('Exception handling method call $_name: $_e');
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      default:
        throw $fidl.FidlError(
            r'Unexpected message name for EmptyProtocolBinding');
    }
  }
}
