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

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: [],
  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: [],
  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 {
  $fidl.ServiceData? get $serviceData => EmptyProtocolData();
  $async.Future<void> send(Empty e);
  $async.Stream<Empty>? get receive;
  $async.Future<Empty> sendAndReceive(Empty e);
}

// TODO: Remove ServiceData for non-service
class EmptyProtocolData implements $fidl.ServiceData<EmptyProtocol> {
  const EmptyProtocolData();

  @override
  String getName() {
    return "";
  }

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

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

  void _handleEvent($fidl.Message $message) {
    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!;
          _receiveEventStreamController.add($fidl.decodeMessage(
              $message,
              _kEmptyProtocol_Receive_Type.decodeResponseInlineSize(),
              $types[0]));
        } 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;
    }
    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!;
          // ignore: prefer_const_declarations
          final $response = $fidl.decodeMessage(
              $message,
              _kEmptyProtocol_SendAndReceive_Type.decodeResponseInlineSize(),
              $types[0]);

          $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);
    final List<$fidl.MemberType> $types = _kEmptyProtocol_Send_Type.request!;
    $fidl.encodeMessageWithCallback(
        $encoder, _kEmptyProtocol_Send_Type.encodingRequestInlineSize(), () {
      $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);
    final List<$fidl.MemberType> $types =
        _kEmptyProtocol_SendAndReceive_Type.request!;
    $fidl.encodeMessageWithCallback($encoder,
        _kEmptyProtocol_SendAndReceive_Type.encodingRequestInlineSize(), () {
      $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((_) {
      final impl = this.impl;
      if (impl != null) {
        final _receive_stream = impl.receive;
        if (_receive_stream != null) {
          $subscriptions.add(_receive_stream.listen(($response) {
            final $fidl.Encoder $encoder = $fidl.Encoder();
            $encoder.encodeMessageHeader(_kEmptyProtocol_Receive_Ordinal, 0);
            final List<$fidl.MemberType> $types =
                _kEmptyProtocol_Receive_Type.response!;
            $fidl.encodeMessage(
                $encoder,
                _kEmptyProtocol_Receive_Type.encodingResponseInlineSize(),
                $types[0],
                $response);
            sendMessage($encoder.message);
          }));
        }
      }
    });
    whenClosed.then((_) => $unsubscribe());
  }

  @override
  void handleMessage($fidl.Message $message, $fidl.MessageSink $respond) {
    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!;
          // ignore: prefer_const_declarations
          final _impl = impl!;
          final $async.Future<void> $future = $fidl
              .decodeMessageWithCallback<$async.Future<void>>(
                  $message, _kEmptyProtocol_Send_Type.decodeRequestInlineSize(),
                  ($fidl.Decoder decoder) {
            return _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!;
          // ignore: prefer_const_declarations
          final _impl = impl!;
          final $async.Future<Empty> $future = $fidl
              .decodeMessageWithCallback<$async.Future<Empty>>($message,
                  _kEmptyProtocol_SendAndReceive_Type.decodeRequestInlineSize(),
                  ($fidl.Decoder decoder) {
            return _impl.sendAndReceive(
              $types[0].decode(decoder, $fidl.kMessageHeaderSize),
            );
          });
          $future.then(($response) {
            final $fidl.Encoder $encoder = $fidl.Encoder();
            $encoder.encodeMessageHeader(
                _kEmptyProtocol_SendAndReceive_Ordinal, $message.txid);
            final List<$fidl.MemberType> $types =
                _kEmptyProtocol_SendAndReceive_Type.response!;
            $fidl.encodeMessage(
                $encoder,
                _kEmptyProtocol_SendAndReceive_Type
                    .encodingResponseInlineSize(),
                $types[0],
                $response);
            $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');
    }
  }
}
