// Copyright 2018 The Fuchsia Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
// WARNING: This file is machine generated by fidlgen.

library fidl_test_name_async;

import 'dart:async';
import 'dart:typed_data';

import 'package:fidl/fidl.dart' as $fidl;
import 'package:meta/meta.dart';
import 'package:zircon/zircon.dart';

// These imports improve deduplication by making uses of {fidl.dart},
// {fidl_async.dart} and {fidl.dart, fidl_async.dart} generate equivalent
// packages. In AOT, the dead code will be removed by tree shaking.
// ignore: unused_import
import 'fidl.dart' as $strongly_connect_sync;

// 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


class EmptyTable extends $fidl.Table {
  const EmptyTable({
  });

  EmptyTable._(Map<int, dynamic> argv)
    :;

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

  static EmptyTable _ctor(Map<int, dynamic> argv) => new EmptyTable._(argv);
}

// See FIDL-308:
// ignore: recursive_compile_time_constant
const $fidl.TableType<EmptyTable> kEmptyTable_Type = const $fidl.TableType<EmptyTable>(
  encodedSize: 16,
  members: const <int, $fidl.FidlType>{},
  ctor: EmptyTable._ctor,
);


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

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

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

  static SimpleTable _ctor(Map<int, dynamic> argv) => new SimpleTable._(argv);
}

// See FIDL-308:
// ignore: recursive_compile_time_constant
const $fidl.TableType<SimpleTable> kSimpleTable_Type = const $fidl.TableType<SimpleTable>(
  encodedSize: 16,
  members: const <int, $fidl.FidlType>{
    1: const $fidl.Int64Type(),
    5: const $fidl.Int64Type(),
  },
  ctor: SimpleTable._ctor,
);


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

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

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

  static OlderSimpleTable _ctor(Map<int, dynamic> argv) => new OlderSimpleTable._(argv);
}

// See FIDL-308:
// ignore: recursive_compile_time_constant
const $fidl.TableType<OlderSimpleTable> kOlderSimpleTable_Type = const $fidl.TableType<OlderSimpleTable>(
  encodedSize: 16,
  members: const <int, $fidl.FidlType>{
    1: const $fidl.Int64Type(),
  },
  ctor: OlderSimpleTable._ctor,
);


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

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

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

  static NewerSimpleTable _ctor(Map<int, dynamic> argv) => new NewerSimpleTable._(argv);
}

// See FIDL-308:
// ignore: recursive_compile_time_constant
const $fidl.TableType<NewerSimpleTable> kNewerSimpleTable_Type = const $fidl.TableType<NewerSimpleTable>(
  encodedSize: 16,
  members: const <int, $fidl.FidlType>{
    1: const $fidl.Int64Type(),
    5: const $fidl.Int64Type(),
    6: const $fidl.Int64Type(),
  },
  ctor: NewerSimpleTable._ctor,
);

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

