// WARNING: This file is machine generated by fidlgen.

library fidl_test_name_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 $zx;

// 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: 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);
    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);
    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);
    switch ($message.ordinal) {
      default:
        throw $fidl.FidlError(r'Unexpected message name for ChildBinding');
    }
  }
}

// getChild: () -> ($fidl.InterfaceHandle<Child> c)
const int _kParent_GetChild_Ordinal = 0x3692bc6900000000;
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: 16),
  ],
  name: r"Parent.GetChild",
);
// getChildRequest: () -> ($fidl.InterfaceRequest<Child> r)
const int _kParent_GetChildRequest_Ordinal = 0x3faacc7e00000000;
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: 16),
  ],
  name: r"Parent.GetChildRequest",
);
// takeChild: ($fidl.InterfaceHandle<Child> c)
const int _kParent_TakeChild_Ordinal = 0x4c0642f900000000;
const $fidl.MethodType _kParent_TakeChild_Type = $fidl.MethodType(
  request: <$fidl.MemberType>[
    $fidl.MemberType<$fidl.InterfaceHandle<Child>>(
        type: $fidl.InterfaceHandleType<Child>(nullable: false), offset: 16),
  ],
  response: null,
  name: r"Parent.TakeChild",
);
// takeChildRequest: ($fidl.InterfaceRequest<Child> r)
const int _kParent_TakeChildRequest_Ordinal = 0x5ec3867a00000000;
const $fidl.MethodType _kParent_TakeChildRequest_Type = $fidl.MethodType(
  request: <$fidl.MemberType>[
    $fidl.MemberType<$fidl.InterfaceRequest<Child>>(
        type: $fidl.InterfaceRequestType<Child>(nullable: false), offset: 16),
  ],
  response: null,
  name: r"Parent.TakeChildRequest",
);

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);
    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);
    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(24);
          // ignore: prefer_const_declarations
          final $response = $types[0].decode($decoder, 0);

          $completer.complete($response);

          // ignore: avoid_catches_without_on_clauses
        } 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(24);
          // ignore: prefer_const_declarations
          final $response = $types[0].decode($decoder, 0);

          $completer.complete($response);

          // ignore: avoid_catches_without_on_clauses
        } 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(24 - $fidl.kMessageHeaderSize);
    final List<$fidl.MemberType> $types = _kParent_TakeChild_Type.request;
    $types[0].encode($encoder, c, 0);
    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(24 - $fidl.kMessageHeaderSize);
    final List<$fidl.MemberType> $types =
        _kParent_TakeChildRequest_Type.request;
    $types[0].encode($encoder, r, 0);
    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);
    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(16);
          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(24 - $fidl.kMessageHeaderSize);
            final List<$fidl.MemberType> $types =
                _kParent_GetChild_Type.response;
            $types[0].encode($encoder, $response, 0);
            $respond($encoder.message);
          }, onError: (_e) {
            close();
            print('Exception handling method call $_name: $_e');
          });
          // ignore: avoid_catches_without_on_clauses
        } 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(16);
          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(24 - $fidl.kMessageHeaderSize);
            final List<$fidl.MemberType> $types =
                _kParent_GetChildRequest_Type.response;
            $types[0].encode($encoder, $response, 0);
            $respond($encoder.message);
          }, onError: (_e) {
            close();
            print('Exception handling method call $_name: $_e');
          });
          // ignore: avoid_catches_without_on_clauses
        } 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(24);
          final $async.Future<void> $future = impl.takeChild(
            $types[0].decode($decoder, 0),
          );
          // ignore: avoid_catches_without_on_clauses
        } 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(24);
          final $async.Future<void> $future = impl.takeChildRequest(
            $types[0].decode($decoder, 0),
          );
          // ignore: avoid_catches_without_on_clauses
        } 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');
    }
  }
}
