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

library fidl_fidl_test_placementofattributes_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;

import 'package:fidl_exampleusing/fidl_async.dart' as lib$exampleusing;
// 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

const int exampleConst = 0x0;

class ExampleEnum extends $fidl.Enum {
  factory ExampleEnum(int _v) {
    switch (_v) {
      case 0x1:
        return member;
      default:
        throw $fidl.FidlError('Invalid strict enum value: $_v',
            $fidl.FidlErrorCode.fidlInvalidEnumValue);
    }
  }
  static const ExampleEnum member = ExampleEnum._(0x1);

  const ExampleEnum._(this.$value);

  @override
  final int $value;

  static const Map<String, ExampleEnum> $valuesMap = {
    r'member': member,
  };

  static const List<ExampleEnum> $values = [
    member,
  ];

  static ExampleEnum? $valueOf(String name) => $valuesMap[name];

  @override
  bool isUnknown() {
    return false;
  }

  @override
  String toString() {
    switch ($value) {
      case 0x1:
        return r'ExampleEnum.member';
      default:
        return r'ExampleEnum.' '${$value}';
    }
  }

  static ExampleEnum _ctor(int v) => ExampleEnum(v);
}

const $fidl.EnumType<ExampleEnum> kExampleEnum_Type =
    $fidl.EnumType<ExampleEnum>(
        type: $fidl.Uint32Type(), values: {0x1: null}, ctor: ExampleEnum._ctor);

class ExampleBits extends $fidl.Bits {
  factory ExampleBits(int _v) {
    if ((_v & ~$mask.$value) != 0) {
      throw $fidl.FidlError('Bits value contains unknown bit(s): $_v',
          $fidl.FidlErrorCode.fidlInvalidBit);
    }
    return ExampleBits._(_v);
  }
  static const ExampleBits member = ExampleBits._(0x1);
  static const ExampleBits $none = ExampleBits._(0);
  static const ExampleBits $mask = ExampleBits._(0x1);

  const ExampleBits._(this.$value);

  ExampleBits operator |(ExampleBits other) {
    return ExampleBits._($value | other.$value);
  }

  ExampleBits operator &(ExampleBits other) {
    return ExampleBits._($value & other.$value);
  }

  ExampleBits operator ~() {
    return ExampleBits._(~$value & $mask.$value);
  }

  @override
  final int $value;

  @override
  bool hasUnknownBits() {
    return getUnknownBits() != 0;
  }

  @override
  int getUnknownBits() {
    return $value & ~$mask.$value;
  }

  @override
  String toString() {
    List<String> parts = [];
    if ($value & 0x1 != 0) {
      parts.add(r'ExampleBits.member');
    }
    if (parts.isEmpty) {
      return r'ExampleBits.$none';
    } else {
      return parts.join(" | ");
    }
  }

  static ExampleBits _ctor(int v) => ExampleBits(v);
}

const $fidl.BitsType<ExampleBits> kExampleBits_Type =
    $fidl.BitsType<ExampleBits>(
        type: $fidl.Uint32Type(), ctor: ExampleBits._ctor);

enum ExampleUnionTag {
  variant, // 0x1
}

const Map<int, ExampleUnionTag> _ExampleUnionTag_map = {
  1: ExampleUnionTag.variant,
};

class ExampleUnion extends $fidl.XUnion {
  const ExampleUnion.withVariant(int value)
      : _ordinal = 1,
        _data = value;

  ExampleUnion._(int ordinal, Object data)
      : _ordinal = ordinal,
        _data = data;

  final int _ordinal;
  final _data;

  ExampleUnionTag get $tag => _ExampleUnionTag_map[_ordinal]!;

  int? get variant {
    if (_ordinal != 1) {
      return null;
    }
    return _data;
  }

  $fidl.UnknownRawData? get $unknownData {
    switch (_ordinal) {
      case 1:
        return null;
      default:
        return _data;
    }
  }

  @override
  String toString() {
    switch (_ordinal) {
      case 1:
        return r'ExampleUnion.variant(' + variant.toString() + ')';
      default:
        return r'ExampleUnion.<UNKNOWN>';
    }
  }

  @override
  int get $ordinal => _ordinal;

  @override
  Object get $data => _data;

  static ExampleUnion _ctor(int ordinal, Object data) {
    return ExampleUnion._(ordinal, data);
  }
}

// See fxbug.dev/7644:
// ignore: recursive_compile_time_constant
const $fidl.UnionType<ExampleUnion> kExampleUnion_Type =
    $fidl.UnionType<ExampleUnion>(
  members: <int, $fidl.FidlType>{
    1: $fidl.Uint32Type(),
  },
  ctor: ExampleUnion._ctor,
  flexible: false,
  resource: false,
);
// See fxbug.dev/7644:
// ignore: recursive_compile_time_constant
const $fidl.NullableUnionType<ExampleUnion> kExampleUnion_OptType =
    $fidl.NullableUnionType<ExampleUnion>(
  members: <int, $fidl.FidlType>{
    1: $fidl.Uint32Type(),
  },
  ctor: ExampleUnion._ctor,
  flexible: false,
  resource: false,
);

enum ExampleXUnionTag {
  $unknown,
  variant, // 0x1
}

const Map<int, ExampleXUnionTag> _ExampleXUnionTag_map = {
  1: ExampleXUnionTag.variant,
};

class ExampleXUnion extends $fidl.XUnion {
  const ExampleXUnion.withVariant(int value)
      : _ordinal = 1,
        _data = value;
  const ExampleXUnion.with$UnknownData(this._ordinal, $fidl.UnknownRawData data)
      : _data = data;

  ExampleXUnion._(int ordinal, Object data)
      : _ordinal = ordinal,
        _data = data;

  final int _ordinal;
  final _data;

  ExampleXUnionTag get $tag =>
      _ExampleXUnionTag_map[_ordinal] ?? ExampleXUnionTag.$unknown;

  int? get variant {
    if (_ordinal != 1) {
      return null;
    }
    return _data;
  }

  $fidl.UnknownRawData? get $unknownData {
    switch (_ordinal) {
      case 1:
        return null;
      default:
        return _data;
    }
  }

  @override
  String toString() {
    switch (_ordinal) {
      case 1:
        return r'ExampleXUnion.variant(' + variant.toString() + ')';
      default:
        return r'ExampleXUnion.<UNKNOWN>';
    }
  }

  @override
  int get $ordinal => _ordinal;

  @override
  Object get $data => _data;

  static ExampleXUnion _ctor(int ordinal, Object data) {
    return ExampleXUnion._(ordinal, data);
  }
}

// See fxbug.dev/7644:
// ignore: recursive_compile_time_constant
const $fidl.UnionType<ExampleXUnion> kExampleXUnion_Type =
    $fidl.UnionType<ExampleXUnion>(
  members: <int, $fidl.FidlType>{
    1: $fidl.Uint32Type(),
  },
  ctor: ExampleXUnion._ctor,
  flexible: true,
  resource: false,
);
// See fxbug.dev/7644:
// ignore: recursive_compile_time_constant
const $fidl.NullableUnionType<ExampleXUnion> kExampleXUnion_OptType =
    $fidl.NullableUnionType<ExampleXUnion>(
  members: <int, $fidl.FidlType>{
    1: $fidl.Uint32Type(),
  },
  ctor: ExampleXUnion._ctor,
  flexible: true,
  resource: false,
);

class ExampleStruct extends $fidl.Struct {
  const ExampleStruct({
    required this.member,
  });
  ExampleStruct.clone(
    ExampleStruct $orig, {
    int? member,
  }) : this(
          member: member ?? $orig.member,
        );

  final int member;

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

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

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

  @override
  String toString() {
    return r'ExampleStruct' r'(member: ' + member.toString() + r')';
  }

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

// See fxbug.dev/7644:
// ignore: recursive_compile_time_constant
const $fidl.StructType<ExampleStruct> kExampleStruct_Type =
    $fidl.StructType<ExampleStruct>(
  inlineSize: 4,
  structDecode: ExampleStruct._structDecode,
);

class ExampleTable extends $fidl.Table {
  const ExampleTable({
    this.$unknownData,
    this.member,
  });

  ExampleTable._(Map<int, dynamic> argv, this.$unknownData) : member = argv[1];

  @override
  final Map<int, $fidl.UnknownRawData>? $unknownData;
  final int? member;

  @override
  dynamic $field(int index) {
    switch (index) {
      case 0:
        return member;
    }
    return null;
  }

  @override
  Map<int, dynamic> get $fields {
    return {
      1: member,
    };
  }

  static ExampleTable _ctor(Map<int, dynamic> argv,
          [Map<int, $fidl.UnknownRawData>? unknownData]) =>
      ExampleTable._(argv, unknownData);
}

// See fxbug.dev/7644:
// ignore: recursive_compile_time_constant
const $fidl.TableType<ExampleTable> kExampleTable_Type =
    $fidl.TableType<ExampleTable>(
  inlineSize: 16,
  members: [
    $fidl.Uint32Type(),
  ],
  ctor: ExampleTable._ctor,
  resource: false,
);

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

// method: (lib$exampleusing.Empty arg)
const int _kExampleProtocol_Method_Ordinal = 0x207d2f81c0ddb184;
const $fidl.MethodType _kExampleProtocol_Method_Type = $fidl.MethodType(
  request: <$fidl.MemberType>[
    $fidl.MemberType<lib$exampleusing.Empty>(
        type: lib$exampleusing.kEmpty_Type, offset: 0),
  ],
  response: [],
  name: r"ExampleProtocol.Method",
  requestInlineSize: 8,
  responseInlineSize: 0,
);

abstract class ExampleProtocol {
  $fidl.ServiceData? get $serviceData => ExampleProtocolData();
  $async.Future<void> method(lib$exampleusing.Empty arg);
}

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

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

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

class ExampleProtocolProxy extends $fidl.AsyncProxy<ExampleProtocol>
    implements ExampleProtocol {
  ExampleProtocolProxy()
      : super($fidl.AsyncProxyController<ExampleProtocol>(
            $interfaceName: r'ExampleProtocol')) {
    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}'));
        ctrl.close();
        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}'));
        ctrl.close();
        break;
    }
  }

  @override
  $async.Future<void> method(lib$exampleusing.Empty arg) 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(_kExampleProtocol_Method_Ordinal, 0);
    final List<$fidl.MemberType> $types =
        _kExampleProtocol_Method_Type.request!;
    $fidl.encodeMessageWithCallback(
        $encoder, _kExampleProtocol_Method_Type.encodingRequestInlineSize(),
        () {
      $types[0].encode($encoder, arg, $fidl.kMessageHeaderSize, 1);
    });
    return $async.Future.sync(() {
      ctrl.sendMessage($encoder.message);
    });
  }
}

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

  @override
  void handleMessage(
      $fidl.IncomingMessage $message, $fidl.OutgoingMessageSink $respond) {
    switch ($message.ordinal) {
      case _kExampleProtocol_Method_Ordinal:
        final String _name = _kExampleProtocol_Method_Type.name;
        try {
          Timeline.startSync(_name);
          final List<$fidl.MemberType> $types =
              _kExampleProtocol_Method_Type.request!;
          // ignore: prefer_const_declarations
          final _impl = impl!;
          final $async.Future<void> $future = $fidl
              .decodeMessageWithCallback<$async.Future<void>>($message,
                  _kExampleProtocol_Method_Type.decodeRequestInlineSize(),
                  ($fidl.Decoder decoder) {
            return _impl.method(
              $types[0].decode(decoder, $fidl.kMessageHeaderSize, 1),
            );
          });
        } catch (_e) {
          close();
          print('Exception handling method call $_name: $_e');
          rethrow;
        } finally {
          Timeline.finishSync();
        }
        break;
      default:
        throw $fidl.FidlError(
            r'Unexpected message name for ExampleProtocolBinding');
    }
  }
}
