// 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' as $zx;

// 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 = {
  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 OlderSimpleUnion._(ordinal, data);
  }
}

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

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

const Map<int, NewerSimpleUnionTag> _NewerSimpleUnionTag_map = {
  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 NewerSimpleUnion._(ordinal, data);
  }
}

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