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

library fidl_fidl_test_enum_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 MyStrictEnum extends $fidl.Enum {
  factory MyStrictEnum(int _v) {
    switch (_v) {
      case 0x1:
        return foo;
      case 0x2:
        return bar;
      default:
        throw $fidl.FidlError('Invalid strict enum value: $_v',
            $fidl.FidlErrorCode.fidlInvalidEnumValue);
    }
  }
  static const MyStrictEnum foo = MyStrictEnum._(0x1);
  static const MyStrictEnum bar = MyStrictEnum._(0x2);

  const MyStrictEnum._(this.$value);

  @override
  final int $value;

  static const Map<String, MyStrictEnum> $valuesMap = {
    r'foo': foo,
    r'bar': bar,
  };

  static const List<MyStrictEnum> $values = [
    foo,
    bar,
  ];

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

  @override
  bool isUnknown() {
    return false;
  }

  @override
  String toString() {
    switch ($value) {
      case 0x1:
        return r'MyStrictEnum.foo';
      case 0x2:
        return r'MyStrictEnum.bar';
      default:
        return r'MyStrictEnum.' '${$value}';
    }
  }

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

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

class MyFlexibleEnum extends $fidl.Enum {
  static final Map<int, MyFlexibleEnum> _internedValues = {
    0x1: foo,
    0x2: bar,
  };
  factory MyFlexibleEnum(int _v) {
    if (!_internedValues.containsKey(_v)) {
      _internedValues[_v] = MyFlexibleEnum._(_v, true);
    }
    return _internedValues[_v];
  }
  static const MyFlexibleEnum foo = MyFlexibleEnum._(0x1, false);
  static const MyFlexibleEnum bar = MyFlexibleEnum._(0x2, false);

  /// Default unknown placeholder.
  static const MyFlexibleEnum $unknown = MyFlexibleEnum._(0xffffffff, true);

  const MyFlexibleEnum._(this.$value, this._isUnknown);

  @override
  final int $value;

  final bool _isUnknown;

  static const Map<String, MyFlexibleEnum> $valuesMap = {
    r'foo': foo,
    r'bar': bar,
  };

  static const List<MyFlexibleEnum> $values = [
    foo,
    bar,
  ];

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

  @override
  bool isUnknown() {
    return _isUnknown;
  }

  @override
  String toString() {
    switch ($value) {
      case 0x1:
        return r'MyFlexibleEnum.foo';
      case 0x2:
        return r'MyFlexibleEnum.bar';
      default:
        return r'MyFlexibleEnum.' '${$value}';
    }
  }

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

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

class MyFlexibleEnumWithCustomUnknown extends $fidl.Enum {
  static final Map<int, MyFlexibleEnumWithCustomUnknown> _internedValues = {
    0x1: foo,
    0x2: bar,
    0x3: customUnknown,
  };
  factory MyFlexibleEnumWithCustomUnknown(int _v) {
    if (!_internedValues.containsKey(_v)) {
      _internedValues[_v] = MyFlexibleEnumWithCustomUnknown._(_v, true);
    }
    return _internedValues[_v];
  }
  static const MyFlexibleEnumWithCustomUnknown foo =
      MyFlexibleEnumWithCustomUnknown._(0x1, false);
  static const MyFlexibleEnumWithCustomUnknown bar =
      MyFlexibleEnumWithCustomUnknown._(0x2, false);
  static const MyFlexibleEnumWithCustomUnknown customUnknown =
      MyFlexibleEnumWithCustomUnknown._(0x3, true);

  /// Default unknown placeholder.
  static const MyFlexibleEnumWithCustomUnknown $unknown =
      MyFlexibleEnumWithCustomUnknown._(0x3, true);

  const MyFlexibleEnumWithCustomUnknown._(this.$value, this._isUnknown);

  @override
  final int $value;

  final bool _isUnknown;

  static const Map<String, MyFlexibleEnumWithCustomUnknown> $valuesMap = {
    r'foo': foo,
    r'bar': bar,
    r'customUnknown': customUnknown,
  };

  static const List<MyFlexibleEnumWithCustomUnknown> $values = [
    foo,
    bar,
    customUnknown,
  ];

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

  @override
  bool isUnknown() {
    return _isUnknown;
  }

  @override
  String toString() {
    switch ($value) {
      case 0x1:
        return r'MyFlexibleEnumWithCustomUnknown.foo';
      case 0x2:
        return r'MyFlexibleEnumWithCustomUnknown.bar';
      case 0x3:
        return r'MyFlexibleEnumWithCustomUnknown.customUnknown';
      default:
        return r'MyFlexibleEnumWithCustomUnknown.' '${$value}';
    }
  }

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

const $fidl.EnumType<MyFlexibleEnumWithCustomUnknown>
    kMyFlexibleEnumWithCustomUnknown_Type =
    $fidl.EnumType<MyFlexibleEnumWithCustomUnknown>(
        type: $fidl.Uint32Type(),
        values: {0x1: null, 0x2: null, 0x3: null},
        ctor: MyFlexibleEnumWithCustomUnknown._ctor);

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