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

import 'dart:async';
import 'dart:developer';
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_async.dart' as $strongly_connect_async;

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

enum OlderSimpleUnionTag {
  i, // 0x3d32b1d7
  f, // 0x5136cf7e
}

const Map<int, OlderSimpleUnionTag> _OlderSimpleUnionTag_map = const {
  1026732503: OlderSimpleUnionTag.i,
  1362546558: OlderSimpleUnionTag.f,
};

class OlderSimpleUnion extends $fidl.XUnion {
  const OlderSimpleUnion.withI(int value)
      : _ordinal = 1026732503,
        _data = value;

  const OlderSimpleUnion.withF(double value)
      : _ordinal = 1362546558,
        _data = value;

  OlderSimpleUnion._(int ordinal, Object data)
      : _ordinal = ordinal,
        _data = data;

  final int _ordinal;
  final _data;

  OlderSimpleUnionTag get tag => _OlderSimpleUnionTag_map[_ordinal];

  int get i {
    if (_ordinal != 1026732503) {
      return null;
    }
    return _data;
  }

  double get f {
    if (_ordinal != 1362546558) {
      return null;
    }
    return _data;
  }

  @override
  String toString() {
    switch (_ordinal) {
      case 1026732503:
        return 'OlderSimpleUnion.i($i)';
      case 1362546558:
        return 'OlderSimpleUnion.f($f)';
      default:
        return null;
    }
  }

  @override
  int get $ordinal => _ordinal;

  @override
  Object get $data => _data;

  static OlderSimpleUnion _ctor(int ordinal, Object data) {
    return new OlderSimpleUnion._(ordinal, data);
  }
}

// See FIDL-308:
// ignore: recursive_compile_time_constant
const $fidl.XUnionType<OlderSimpleUnion> kOlderSimpleUnion_Type =
    const $fidl.XUnionType<OlderSimpleUnion>(
  encodedSize: 24,
  members: const <int, $fidl.FidlType>{
    1026732503: const $fidl.Int64Type(),
    1362546558: const $fidl.Float32Type(),
  },
  ctor: OlderSimpleUnion._ctor,
);
const $fidl.XUnionType<OlderSimpleUnion> kOlderSimpleUnion_OptType =
    const $fidl.XUnionType<OlderSimpleUnion>(
  encodedSize: 24,
  members: const <int, $fidl.FidlType>{
    1026732503: const $fidl.Int64Type(),
    1362546558: const $fidl.Float32Type(),
  },
  ctor: OlderSimpleUnion._ctor,
  nullable: true,
);

enum NewerSimpleUnionTag {
  i, // 0x295cbfde
  s, // 0x1c3b9247
  v, // 0x6c38b28f
}

const Map<int, NewerSimpleUnionTag> _NewerSimpleUnionTag_map = const {
  693944286: NewerSimpleUnionTag.i,
  473666119: NewerSimpleUnionTag.s,
  1815655055: NewerSimpleUnionTag.v,
};

class NewerSimpleUnion extends $fidl.XUnion {
  const NewerSimpleUnion.withI(int value)
      : _ordinal = 693944286,
        _data = value;

  const NewerSimpleUnion.withS(String value)
      : _ordinal = 473666119,
        _data = value;

  const NewerSimpleUnion.withV(List<String> value)
      : _ordinal = 1815655055,
        _data = value;

  NewerSimpleUnion._(int ordinal, Object data)
      : _ordinal = ordinal,
        _data = data;

  final int _ordinal;
  final _data;

  NewerSimpleUnionTag get tag => _NewerSimpleUnionTag_map[_ordinal];

  int get i {
    if (_ordinal != 693944286) {
      return null;
    }
    return _data;
  }

  String get s {
    if (_ordinal != 473666119) {
      return null;
    }
    return _data;
  }

  List<String> get v {
    if (_ordinal != 1815655055) {
      return null;
    }
    return _data;
  }

  @override
  String toString() {
    switch (_ordinal) {
      case 693944286:
        return 'NewerSimpleUnion.i($i)';
      case 473666119:
        return 'NewerSimpleUnion.s($s)';
      case 1815655055:
        return 'NewerSimpleUnion.v($v)';
      default:
        return null;
    }
  }

  @override
  int get $ordinal => _ordinal;

  @override
  Object get $data => _data;

  static NewerSimpleUnion _ctor(int ordinal, Object data) {
    return new NewerSimpleUnion._(ordinal, data);
  }
}

// See FIDL-308:
// ignore: recursive_compile_time_constant
const $fidl.XUnionType<NewerSimpleUnion> kNewerSimpleUnion_Type =
    const $fidl.XUnionType<NewerSimpleUnion>(
  encodedSize: 24,
  members: const <int, $fidl.FidlType>{
    693944286: const $fidl.Int64Type(),
    473666119: const $fidl.StringType(maybeElementCount: null, nullable: false),
    1815655055: const $fidl.VectorType<List<String>>(
        element:
            const $fidl.StringType(maybeElementCount: null, nullable: false),
        maybeElementCount: null,
        nullable: false),
  },
  ctor: NewerSimpleUnion._ctor,
);
const $fidl.XUnionType<NewerSimpleUnion> kNewerSimpleUnion_OptType =
    const $fidl.XUnionType<NewerSimpleUnion>(
  encodedSize: 24,
  members: const <int, $fidl.FidlType>{
    693944286: const $fidl.Int64Type(),
    473666119: const $fidl.StringType(maybeElementCount: null, nullable: false),
    1815655055: const $fidl.VectorType<List<String>>(
        element:
            const $fidl.StringType(maybeElementCount: null, nullable: false),
        maybeElementCount: null,
        nullable: false),
  },
  ctor: NewerSimpleUnion._ctor,
  nullable: true,
);
