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

library fidl_fidl_test_bits_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 MyBits extends $fidl.Bits {
  factory MyBits(int _v) {
    if ((_v & ~$mask.$value) != 0) {
      throw $fidl.FidlError('Bits value contains unknown bit(s): $_v',
          $fidl.FidlErrorCode.fidlInvalidBit);
    }
    return MyBits._(_v);
  }
  static const MyBits myFirstBit = MyBits._(0x1);
  static const MyBits myOtherBit = MyBits._(0x2);
  static const MyBits mask = MyBits._(0x4);
  static const MyBits $none = MyBits._(0);
  static const MyBits $mask = MyBits._(0x7);

  const MyBits._(this.$value);

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

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

  MyBits operator ~() {
    return MyBits._(~$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'MyBits.myFirstBit');
    }
    if ($value & 0x2 != 0) {
      parts.add(r'MyBits.myOtherBit');
    }
    if ($value & 0x4 != 0) {
      parts.add(r'MyBits.mask');
    }
    if (parts.isEmpty) {
      return r'MyBits.$none';
    } else {
      return parts.join(" | ");
    }
  }

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

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

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

  const StrictBits._(this.$value);

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

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

  StrictBits operator ~() {
    return StrictBits._(~$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'StrictBits.smallest');
    }
    if ($value & 0x8000000000000000 != 0) {
      parts.add(r'StrictBits.biggest');
    }
    if (parts.isEmpty) {
      return r'StrictBits.$none';
    } else {
      return parts.join(" | ");
    }
  }

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

const $fidl.BitsType<StrictBits> kStrictBits_Type = $fidl.BitsType<StrictBits>(
    type: $fidl.Uint64Type(), ctor: StrictBits._ctor);

class FlexibleBits extends $fidl.Bits {
  factory FlexibleBits(int _v) {
    return FlexibleBits._(_v);
  }
  static const FlexibleBits smallest = FlexibleBits._(0x1);
  static const FlexibleBits biggest = FlexibleBits._(0x8000000000000000);
  static const FlexibleBits $none = FlexibleBits._(0);
  static const FlexibleBits $mask = FlexibleBits._(0x8000000000000001);

  const FlexibleBits._(this.$value);

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

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

  FlexibleBits operator ~() {
    return FlexibleBits._(~$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'FlexibleBits.smallest');
    }
    if ($value & 0x8000000000000000 != 0) {
      parts.add(r'FlexibleBits.biggest');
    }
    if (hasUnknownBits()) {
      parts.add('0x${getUnknownBits().toRadixString(16)}');
    }
    if (parts.isEmpty) {
      return r'FlexibleBits.$none';
    } else {
      return parts.join(" | ");
    }
  }

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

const $fidl.BitsType<FlexibleBits> kFlexibleBits_Type =
    $fidl.BitsType<FlexibleBits>(
        type: $fidl.Uint64Type(), ctor: FlexibleBits._ctor);

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