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

library fidl_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: 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

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

abstract class Child extends $fidl.Service {
  static const String $serviceName = null;
  @override
  $fidl.ServiceData get $serviceData => ChildData();
}

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

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

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

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

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

  void _handleEvent($fidl.Message $message) {
    final $fidl.Decoder $decoder = $fidl.Decoder($message)
      ..claimMemory($fidl.kMessageHeaderSize);
    switch ($message.ordinal) {
      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) {
      default:
        ctrl.proxyError(
            $fidl.FidlError('Unexpected message ordinal: ${$message.ordinal}'));
        ctrl.close();
        break;
    }
  }
}

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

  @override
  void handleMessage($fidl.Message $message, $fidl.MessageSink $respond) {
    final $fidl.Decoder $decoder = $fidl.Decoder($message)
      ..claimMemory($fidl.kMessageHeaderSize);
    switch ($message.ordinal) {
      default:
        throw $fidl.FidlError(r'Unexpected message name for ChildBinding');
    }
  }
}

// getChild: () -> ($fidl.InterfaceHandle<Child> c)
const int _kParent_GetChild_Ordinal = 0x6e0c789be8dbb77e;
const $fidl.MethodType _kParent_GetChild_Type = $fidl.MethodType(
  request: null,
  response: <$fidl.MemberType>[
    $fidl.MemberType<$fidl.InterfaceHandle<Child>>(
        type: $fidl.InterfaceHandleType<Child>(nullable: false), offset: 0),
  ],
  name: r"Parent.GetChild",
  requestInlineSize: 0,
  responseInlineSize: 8,
);
// getChildRequest: () -> ($fidl.InterfaceRequest<Child> r)
const int _kParent_GetChildRequest_Ordinal = 0x193e7d6949a9df98;
const $fidl.MethodType _kParent_GetChildRequest_Type = $fidl.MethodType(
  request: null,
  response: <$fidl.MemberType>[
    $fidl.MemberType<$fidl.InterfaceRequest<Child>>(
        type: $fidl.InterfaceRequestType<Child>(nullable: false), offset: 0),
  ],
  name: r"Parent.GetChildRequest",
  requestInlineSize: 0,
  responseInlineSize: 8,
);
// takeChild: ($fidl.InterfaceHandle<Child> c)
const int _kParent_TakeChild_Ordinal = 0x5311bd7214c0f6e;
const $fidl.MethodType _kParent_TakeChild_Type = $fidl.MethodType(
  request: <$fidl.MemberType>[
    $fidl.MemberType<$fidl.InterfaceHandle<Child>>(
        type: $fidl.InterfaceHandleType<Child>(nullable: false), offset: 0),
  ],
  response: null,
  name: r"Parent.TakeChild",
  requestInlineSize: 8,
  responseInlineSize: 0,
);
// takeChildRequest: ($fidl.InterfaceRequest<Child> r)
const int _kParent_TakeChildRequest_Ordinal = 0x15dae312bad5a9cc;
const $fidl.MethodType _kParent_TakeChildRequest_Type = $fidl.MethodType(
  request: <$fidl.MemberType>[
    $fidl.MemberType<$fidl.InterfaceRequest<Child>>(
        type: $fidl.InterfaceRequestType<Child>(nullable: false), offset: 0),
  ],
  response: null,
  name: r"Parent.TakeChildRequest",
  requestInlineSize: 8,
  responseInlineSize: 0,
);

abstract class Parent extends $fidl.Service {
  static const String $serviceName = null;
  @override
  $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);
}

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

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

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

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

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

  void _handleEvent($fidl.Message $message) {
    final $fidl.Decoder $decoder = $fidl.Decoder($message)
      ..claimMemory($fidl.kMessageHeaderSize);
    switch ($message.ordinal) {
      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 _kParent_GetChild_Ordinal:
        final String _name = _kParent_GetChild_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types = _kParent_GetChild_Type.response;
          $decoder.claimMemory(
              _kParent_GetChild_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;
      case _kParent_GetChildRequest_Ordinal:
        final String _name = _kParent_GetChildRequest_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kParent_GetChildRequest_Type.response;
          $decoder.claimMemory(
              _kParent_GetChildRequest_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<$fidl.InterfaceHandle<Child>> getChild() 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(_kParent_GetChild_Ordinal, 0);
    final $completer = $async.Completer<$fidl.InterfaceHandle<Child>>();
    ctrl.sendMessageWithResponse($encoder.message, $completer);
    return $completer.future;
  }

  @override
  $async.Future<$fidl.InterfaceRequest<Child>> getChildRequest() 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(_kParent_GetChildRequest_Ordinal, 0);
    final $completer = $async.Completer<$fidl.InterfaceRequest<Child>>();
    ctrl.sendMessageWithResponse($encoder.message, $completer);
    return $completer.future;
  }

  @override
  $async.Future<void> takeChild($fidl.InterfaceHandle<Child> c) 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(_kParent_TakeChild_Ordinal, 0);
    $encoder.alloc(_kParent_TakeChild_Type.encodingRequestInlineSize($encoder));
    final List<$fidl.MemberType> $types = _kParent_TakeChild_Type.request;
    $types[0].encode($encoder, c, $fidl.kMessageHeaderSize);
    return $async.Future.sync(() {
      ctrl.sendMessage($encoder.message);
    });
  }

  @override
  $async.Future<void> takeChildRequest($fidl.InterfaceRequest<Child> r) 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(_kParent_TakeChildRequest_Ordinal, 0);
    $encoder.alloc(
        _kParent_TakeChildRequest_Type.encodingRequestInlineSize($encoder));
    final List<$fidl.MemberType> $types =
        _kParent_TakeChildRequest_Type.request;
    $types[0].encode($encoder, r, $fidl.kMessageHeaderSize);
    return $async.Future.sync(() {
      ctrl.sendMessage($encoder.message);
    });
  }
}

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

  @override
  void handleMessage($fidl.Message $message, $fidl.MessageSink $respond) {
    final $fidl.Decoder $decoder = $fidl.Decoder($message)
      ..claimMemory($fidl.kMessageHeaderSize);
    switch ($message.ordinal) {
      case _kParent_GetChild_Ordinal:
        final String _name = _kParent_GetChild_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types = _kParent_GetChild_Type.request;
          $decoder.claimMemory(
              _kParent_GetChild_Type.decodeRequestInlineSize($decoder));
          final $async.Future<$fidl.InterfaceHandle<Child>> $future =
              impl.getChild();
          $future.then(($response) {
            final $fidl.Encoder $encoder = $fidl.Encoder();
            $encoder.encodeMessageHeader(
                _kParent_GetChild_Ordinal, $message.txid);
            $encoder.alloc(
                _kParent_GetChild_Type.encodingResponseInlineSize($encoder));
            final List<$fidl.MemberType> $types =
                _kParent_GetChild_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;
      case _kParent_GetChildRequest_Ordinal:
        final String _name = _kParent_GetChildRequest_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kParent_GetChildRequest_Type.request;
          $decoder.claimMemory(
              _kParent_GetChildRequest_Type.decodeRequestInlineSize($decoder));
          final $async.Future<$fidl.InterfaceRequest<Child>> $future =
              impl.getChildRequest();
          $future.then(($response) {
            final $fidl.Encoder $encoder = $fidl.Encoder();
            $encoder.encodeMessageHeader(
                _kParent_GetChildRequest_Ordinal, $message.txid);
            $encoder.alloc(_kParent_GetChildRequest_Type
                .encodingResponseInlineSize($encoder));
            final List<$fidl.MemberType> $types =
                _kParent_GetChildRequest_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;
      case _kParent_TakeChild_Ordinal:
        final String _name = _kParent_TakeChild_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types = _kParent_TakeChild_Type.request;
          $decoder.claimMemory(
              _kParent_TakeChild_Type.decodeRequestInlineSize($decoder));
          final $async.Future<void> $future = impl.takeChild(
            $types[0].decode($decoder, $fidl.kMessageHeaderSize),
          );
        } catch (_e) {
          close();
          print('Exception handling method call $_name: $_e');
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      case _kParent_TakeChildRequest_Ordinal:
        final String _name = _kParent_TakeChildRequest_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kParent_TakeChildRequest_Type.request;
          $decoder.claimMemory(
              _kParent_TakeChildRequest_Type.decodeRequestInlineSize($decoder));
          final $async.Future<void> $future = impl.takeChildRequest(
            $types[0].decode($decoder, $fidl.kMessageHeaderSize),
          );
        } catch (_e) {
          close();
          print('Exception handling method call $_name: $_e');
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      default:
        throw $fidl.FidlError(r'Unexpected message name for ParentBinding');
    }
  }
}
