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

library fidl_fidl_test_table_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 EmptyTable extends $fidl.Table {
  const EmptyTable({
    this.$unknownData,
  });

  EmptyTable._(Map<int, dynamic> argv, this.$unknownData);

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

  @override
  dynamic $field(int index) {
    switch (index) {
    }
    return null;
  }

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

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

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

class SimpleTable extends $fidl.Table {
  const SimpleTable({
    this.$unknownData,
    this.x,
    this.y,
  });

  SimpleTable._(Map<int, dynamic> argv, this.$unknownData)
      : x = argv[1],
        y = argv[5];

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

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

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

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

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

class OlderSimpleTable extends $fidl.Table {
  const OlderSimpleTable({
    this.$unknownData,
    this.x,
  });

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

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

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

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

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

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

class NewerSimpleTable extends $fidl.Table {
  const NewerSimpleTable({
    this.$unknownData,
    this.x,
    this.y,
    this.z,
  });

  NewerSimpleTable._(Map<int, dynamic> argv, this.$unknownData)
      : x = argv[1],
        y = argv[5],
        z = argv[6];

  @override
  final Map<int, $fidl.UnknownRawData>? $unknownData;
  final int? x;
  final int? y;
  final int? z;

  @override
  dynamic $field(int index) {
    switch (index) {
      case 0:
        return x;
      case 4:
        return y;
      case 5:
        return z;
    }
    return null;
  }

  @override
  Map<int, dynamic> get $fields {
    return {
      1: x,
      5: y,
      6: z,
    };
  }

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

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

class ReverseOrdinalTable extends $fidl.Table {
  const ReverseOrdinalTable({
    this.$unknownData,
    this.z,
    this.y,
    this.x,
  });

  ReverseOrdinalTable._(Map<int, dynamic> argv, this.$unknownData)
      : z = argv[1],
        y = argv[2],
        x = argv[3];

  @override
  final Map<int, $fidl.UnknownRawData>? $unknownData;
  final int? z;
  final int? y;
  final int? x;

  @override
  dynamic $field(int index) {
    switch (index) {
      case 0:
        return z;
      case 1:
        return y;
      case 2:
        return x;
    }
    return null;
  }

  @override
  Map<int, dynamic> get $fields {
    return {
      1: z,
      2: y,
      3: x,
    };
  }

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

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

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