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

library fidl_test_protocolrequest_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: directives_ordering
// 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

abstract class Child {
  $fidl.ServiceData? get $serviceData => ChildData();
} // TODO: Remove ServiceData for non-service

class ChildData implements $fidl.ServiceData<Child> {
  const ChildData();

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

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

class ChildProxy extends $fidl.AsyncProxy<Child> implements Child {
  ChildProxy()
      : super($fidl.AsyncProxyController<Child>($interfaceName: r'Child')) {
    ctrl.onResponse = _handleResponse;
  }
  @override
  Null get $serviceData => null;

  void _handleEvent($fidl.IncomingMessage $message) {
    switch ($message.ordinal) {
      default:
        ctrl.proxyError(
            $fidl.FidlError('Unexpected message ordinal: ${$message.ordinal}'));
        break;
    }
  }

  void _handleResponse($fidl.IncomingMessage $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) {
      default:
        ctrl.proxyError(
            $fidl.FidlError('Unexpected message ordinal: ${$message.ordinal}'));
        break;
    }
  }
}

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

  @override
  void handleMessage(
      $fidl.IncomingMessage $message, $fidl.OutgoingMessageSink $respond) {
    switch ($message.ordinal) {
      default:
        throw $fidl.FidlError(r'Unexpected message name for ChildBinding');
    }
  }
}

// getChild: () -> ($fidl.InterfaceHandle<Child> c)
const int _kParent_GetChild_Ordinal = 0xc3cd963aafc873b;
const $fidl.MethodType _kParent_GetChild_Type = $fidl.MethodType(
  request: [],
  response: <$fidl.MemberType>[
    $fidl.MemberType<$fidl.InterfaceHandle<Child>>(
        type: $fidl.InterfaceHandleType<Child>(), offset: 0),
  ],
  name: r"Parent.GetChild",
  requestInlineSizeV2: 0,
  responseInlineSizeV2: 4,
);
// getChildRequest: () -> ($fidl.InterfaceRequest<Child> r)
const int _kParent_GetChildRequest_Ordinal = 0xf38d08d64f71c79;
const $fidl.MethodType _kParent_GetChildRequest_Type = $fidl.MethodType(
  request: [],
  response: <$fidl.MemberType>[
    $fidl.MemberType<$fidl.InterfaceRequest<Child>>(
        type: $fidl.InterfaceRequestType<Child>(), offset: 0),
  ],
  name: r"Parent.GetChildRequest",
  requestInlineSizeV2: 0,
  responseInlineSizeV2: 4,
);
// takeChild: ($fidl.InterfaceHandle<Child> c)
const int _kParent_TakeChild_Ordinal = 0x3e08fd7ca04b2290;
const $fidl.MethodType _kParent_TakeChild_Type = $fidl.MethodType(
  request: <$fidl.MemberType>[
    $fidl.MemberType<$fidl.InterfaceHandle<Child>>(
        type: $fidl.InterfaceHandleType<Child>(), offset: 0),
  ],
  response: [],
  name: r"Parent.TakeChild",
  requestInlineSizeV2: 4,
  responseInlineSizeV2: 0,
);
// takeChildRequest: ($fidl.InterfaceRequest<Child> r)
const int _kParent_TakeChildRequest_Ordinal = 0x2063f76b1bb45f87;
const $fidl.MethodType _kParent_TakeChildRequest_Type = $fidl.MethodType(
  request: <$fidl.MemberType>[
    $fidl.MemberType<$fidl.InterfaceRequest<Child>>(
        type: $fidl.InterfaceRequestType<Child>(), offset: 0),
  ],
  response: [],
  name: r"Parent.TakeChildRequest",
  requestInlineSizeV2: 4,
  responseInlineSizeV2: 0,
);

abstract class Parent {
  $fidl.ServiceData? get $serviceData => ParentData();
  $async.Future<$fidl.InterfaceHandle<Child>> getChild();
  $async.Future<$fidl.InterfaceRequest<Child>> getChildRequest();
  $async.Future<void> takeChild($fidl.InterfaceHandle<Child> c);
  $async.Future<void> takeChildRequest($fidl.InterfaceRequest<Child> r);
} // TODO: Remove ServiceData for non-service

class ParentData implements $fidl.ServiceData<Parent> {
  const ParentData();

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

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

class ParentProxy extends $fidl.AsyncProxy<Parent> implements Parent {
  ParentProxy()
      : super($fidl.AsyncProxyController<Parent>($interfaceName: r'Parent')) {
    ctrl.onResponse = _handleResponse;
  }
  @override
  Null get $serviceData => null;

  void _handleEvent($fidl.IncomingMessage $message) {
    switch ($message.ordinal) {
      default:
        ctrl.proxyError(
            $fidl.FidlError('Unexpected message ordinal: ${$message.ordinal}'));
        break;
    }
  }

  void _handleResponse($fidl.IncomingMessage $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 _kParent_GetChild_Ordinal:
        final String _name = _kParent_GetChild_Type.name;
        $fidl.performCtrlWithExceptionHandling(
            _name, ctrl, 'method response', $completer.completeError, () {
          final List<$fidl.MemberType> $types =
              _kParent_GetChild_Type.response!;
          // ignore: prefer_const_declarations
          final $response = $fidl.decodeMessage(
              $message,
              _kParent_GetChild_Type.responseInlineSize($message.wireFormat),
              $types[0]);

          $completer.complete($response);
        });
        break;
      case _kParent_GetChildRequest_Ordinal:
        final String _name = _kParent_GetChildRequest_Type.name;
        $fidl.performCtrlWithExceptionHandling(
            _name, ctrl, 'method response', $completer.completeError, () {
          final List<$fidl.MemberType> $types =
              _kParent_GetChildRequest_Type.response!;
          // ignore: prefer_const_declarations
          final $response = $fidl.decodeMessage(
              $message,
              _kParent_GetChildRequest_Type
                  .responseInlineSize($message.wireFormat),
              $types[0]);

          $completer.complete($response);
        });
        break;
      default:
        ctrl.proxyError(
            $fidl.FidlError('Unexpected message ordinal: ${$message.ordinal}'));
        break;
    }
  }

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

    final $fidl.Encoder $encoder = $fidl.Encoder($fidl.kWireFormatDefault);
    $encoder.encodeMessageHeader(
        _kParent_GetChild_Ordinal, 0, $fidl.CallStrictness.strict);
    final $completer = $async.Completer<$fidl.InterfaceHandle<Child>>();
    ctrl.sendMessageWithResponse($encoder.message, $completer);
    return $completer.future;
  }

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

    final $fidl.Encoder $encoder = $fidl.Encoder($fidl.kWireFormatDefault);
    $encoder.encodeMessageHeader(
        _kParent_GetChildRequest_Ordinal, 0, $fidl.CallStrictness.strict);
    final $completer = $async.Completer<$fidl.InterfaceRequest<Child>>();
    ctrl.sendMessageWithResponse($encoder.message, $completer);
    return $completer.future;
  }

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

    final $fidl.Encoder $encoder = $fidl.Encoder($fidl.kWireFormatDefault);
    $encoder.encodeMessageHeader(
        _kParent_TakeChild_Ordinal, 0, $fidl.CallStrictness.strict);
    final List<$fidl.MemberType> $types = _kParent_TakeChild_Type.request!;
    $fidl.encodeMessageWithCallback($encoder,
        _kParent_TakeChild_Type.requestInlineSize($encoder.wireFormat), () {
      $types[0].encode($encoder, c, $fidl.kMessageHeaderSize, 1);
    });
    return $async.Future.sync(() {
      ctrl.sendMessage($encoder.message);
    });
  }

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

    final $fidl.Encoder $encoder = $fidl.Encoder($fidl.kWireFormatDefault);
    $encoder.encodeMessageHeader(
        _kParent_TakeChildRequest_Ordinal, 0, $fidl.CallStrictness.strict);
    final List<$fidl.MemberType> $types =
        _kParent_TakeChildRequest_Type.request!;
    $fidl.encodeMessageWithCallback($encoder,
        _kParent_TakeChildRequest_Type.requestInlineSize($encoder.wireFormat),
        () {
      $types[0].encode($encoder, r, $fidl.kMessageHeaderSize, 1);
    });
    return $async.Future.sync(() {
      ctrl.sendMessage($encoder.message);
    });
  }
}

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

  @override
  void handleMessage(
      $fidl.IncomingMessage $message, $fidl.OutgoingMessageSink $respond) {
    switch ($message.ordinal) {
      case _kParent_GetChild_Ordinal:
        final String _name = _kParent_GetChild_Type.name;
        $fidl.performWithExceptionHandling(_name, () {
          final List<$fidl.MemberType> $types = _kParent_GetChild_Type.request!;
          // ignore: prefer_const_declarations
          final _impl = impl!;
          final $async.Future<$fidl.InterfaceHandle<Child>> $future = $fidl
              .decodeMessageWithCallback<
                      $async.Future<$fidl.InterfaceHandle<Child>>>($message,
                  _kParent_GetChild_Type.requestInlineSize($message.wireFormat),
                  ($fidl.Decoder decoder) {
            return _impl.getChild();
          });
          $future.then(($response) {
            final $fidl.Encoder $encoder =
                $fidl.Encoder($fidl.kWireFormatDefault);
            $encoder.encodeMessageHeader(_kParent_GetChild_Ordinal,
                $message.txid, $fidl.CallStrictness.strict);
            final List<$fidl.MemberType> $types =
                _kParent_GetChild_Type.response!;
            $fidl.encodeMessage(
                $encoder,
                _kParent_GetChild_Type.responseInlineSize($encoder.wireFormat),
                $types[0],
                $response);
            $respond($encoder.message);
          }, onError: (_e) {
            $fidl.handleException(_name, _e, close);
          });
        }, close);
        break;
      case _kParent_GetChildRequest_Ordinal:
        final String _name = _kParent_GetChildRequest_Type.name;
        $fidl.performWithExceptionHandling(_name, () {
          final List<$fidl.MemberType> $types =
              _kParent_GetChildRequest_Type.request!;
          // ignore: prefer_const_declarations
          final _impl = impl!;
          final $async.Future<$fidl.InterfaceRequest<Child>> $future = $fidl
              .decodeMessageWithCallback<
                      $async.Future<$fidl.InterfaceRequest<Child>>>(
                  $message,
                  _kParent_GetChildRequest_Type.requestInlineSize(
                      $message.wireFormat), ($fidl.Decoder decoder) {
            return _impl.getChildRequest();
          });
          $future.then(($response) {
            final $fidl.Encoder $encoder =
                $fidl.Encoder($fidl.kWireFormatDefault);
            $encoder.encodeMessageHeader(_kParent_GetChildRequest_Ordinal,
                $message.txid, $fidl.CallStrictness.strict);
            final List<$fidl.MemberType> $types =
                _kParent_GetChildRequest_Type.response!;
            $fidl.encodeMessage(
                $encoder,
                _kParent_GetChildRequest_Type
                    .responseInlineSize($encoder.wireFormat),
                $types[0],
                $response);
            $respond($encoder.message);
          }, onError: (_e) {
            $fidl.handleException(_name, _e, close);
          });
        }, close);
        break;
      case _kParent_TakeChild_Ordinal:
        final String _name = _kParent_TakeChild_Type.name;
        $fidl.performWithExceptionHandling(_name, () {
          final List<$fidl.MemberType> $types =
              _kParent_TakeChild_Type.request!;
          // ignore: prefer_const_declarations
          final _impl = impl!;
          final $async.Future<void> $future = $fidl
              .decodeMessageWithCallback<$async.Future<void>>(
                  $message,
                  _kParent_TakeChild_Type.requestInlineSize(
                      $message.wireFormat), ($fidl.Decoder decoder) {
            return _impl.takeChild(
              $types[0].decode(decoder, $fidl.kMessageHeaderSize, 1),
            );
          });
        }, close);
        break;
      case _kParent_TakeChildRequest_Ordinal:
        final String _name = _kParent_TakeChildRequest_Type.name;
        $fidl.performWithExceptionHandling(_name, () {
          final List<$fidl.MemberType> $types =
              _kParent_TakeChildRequest_Type.request!;
          // ignore: prefer_const_declarations
          final _impl = impl!;
          final $async.Future<void> $future = $fidl
              .decodeMessageWithCallback<$async.Future<void>>(
                  $message,
                  _kParent_TakeChildRequest_Type.requestInlineSize(
                      $message.wireFormat), ($fidl.Decoder decoder) {
            return _impl.takeChildRequest(
              $types[0].decode(decoder, $fidl.kMessageHeaderSize, 1),
            );
          });
        }, close);
        break;
      default:
        throw $fidl.FidlError(r'Unexpected message name for ParentBinding');
    }
  }
}
