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

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() {
    if ($value == null) {
      return null;
    }
    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() {
    if ($value == null) {
      return null;
    }
    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() {
    if ($value == null) {
      return null;
    }
    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();
