// WARNING: This file is machine generated by fidlgen.

// fidl_experiment = output_index_json

#pragma once

#include "lib/fidl/cpp/internal/header.h"

namespace test {
namespace consts {

//
// Domain objects declarations
//

enum class EnumType : int32_t {

  VALUE = 1u,

  true_ = 2u,
};

inline zx_status_t Clone(::test::consts::EnumType value,
                         ::test::consts::EnumType* result) {
  *result = value;
  return ZX_OK;
}

enum class BitsType : uint32_t {

  VALUE = 1u,

  true_ = 2u,
};

const static BitsType BitsTypeMask = static_cast<BitsType>(3u);

constexpr inline ::test::consts::BitsType operator|(::test::consts::BitsType _lhs, ::test::consts::BitsType _rhs) {
  return static_cast<::test::consts::BitsType>(
      static_cast<uint32_t>(_lhs) | static_cast<uint32_t>(_rhs));
}

constexpr inline ::test::consts::BitsType& operator|=(::test::consts::BitsType& _lhs,
                                                      ::test::consts::BitsType _rhs) {
  _lhs = _lhs | _rhs;
  return _lhs;
}

constexpr inline ::test::consts::BitsType operator&(::test::consts::BitsType _lhs,
                                                    ::test::consts::BitsType _rhs) {
  return static_cast<::test::consts::BitsType>(
      static_cast<uint32_t>(_lhs) & static_cast<uint32_t>(_rhs));
}

constexpr inline ::test::consts::BitsType& operator&=(::test::consts::BitsType& _lhs,
                                                      ::test::consts::BitsType _rhs) {
  _lhs = _lhs & _rhs;
  return _lhs;
}

constexpr inline ::test::consts::BitsType operator^(::test::consts::BitsType _lhs,
                                                    ::test::consts::BitsType _rhs) {
  return static_cast<::test::consts::BitsType>(
      static_cast<uint32_t>(_lhs) ^ static_cast<uint32_t>(_rhs));
}

constexpr inline ::test::consts::BitsType& operator^=(::test::consts::BitsType& _lhs,
                                                      ::test::consts::BitsType _rhs) {
  _lhs = _lhs ^ _rhs;
  return _lhs;
}

constexpr inline ::test::consts::BitsType operator~(::test::consts::BitsType _value) {
  return static_cast<::test::consts::BitsType>(
      ~static_cast<uint32_t>(_value) & static_cast<uint32_t>(::test::consts::BitsTypeMask));
}

inline zx_status_t Clone(::test::consts::BitsType value,
                         ::test::consts::BitsType* result) {
  *result = value;
  return ZX_OK;
}

constexpr bool ENABLED_FLAG = true;

constexpr int8_t OFFSET = -33;

constexpr uint16_t ANSWER = 42u;

constexpr uint8_t ANSWER_NARROWED = ::test::consts::ANSWER;

constexpr uint16_t ANSWER_IN_BINARY = 42u;

constexpr uint32_t POPULATION_USA_2018 = 330000000u;

constexpr uint64_t DIAMOND = 1746410393481133080u;

constexpr uint64_t FUCHSIA = 4054509061583223046u;

extern const char* USERNAME;

constexpr float MIN_TEMP = -273.15f;

constexpr double CONVERSION_FACTOR = 1.41421;

constexpr zx_obj_type_t ZX_OBJ_VAL = ZX_OBJ_TYPE_CHANNEL;

constexpr zx_rights_t ZX_RIGHTS_VAL = ZX_RIGHT_READ;

constexpr uint64_t ZX_CONST = ZX_CHANNEL_MAX_MSG_BYTES;

constexpr ::test::consts::EnumType enumVal = ::test::consts::EnumType::VALUE;

constexpr int32_t enumPrimitiveVal = ::test::consts::EnumType::VALUE;

constexpr int8_t enumPrimitiveValNarrowed = ::test::consts::EnumType::VALUE;

constexpr ::test::consts::EnumType enumTrue = ::test::consts::EnumType::true_;

constexpr int32_t enumPrimitiveTrue = ::test::consts::EnumType::true_;

constexpr ::test::consts::BitsType bitsVal = ::test::consts::BitsType::VALUE;

constexpr uint32_t bitsPrimitiveVal = ::test::consts::BitsType::VALUE;

constexpr uint8_t bitsPrimitiveValNarrowed = ::test::consts::BitsType::VALUE;

constexpr ::test::consts::BitsType bitsTrue = ::test::consts::BitsType::true_;

constexpr uint32_t bitsPrimitiveTrue = ::test::consts::BitsType::true_;

}  // namespace consts
}  // namespace test
namespace fidl {

template <>
struct CodingTraits<::test::consts::EnumType> {
  static constexpr size_t kInlineSize = sizeof(::test::consts::EnumType);
  static void Encode(Encoder* encoder, ::test::consts::EnumType* value, size_t offset,
                     cpp17::optional<::fidl::HandleInformation> maybe_handle_info) {
    ZX_DEBUG_ASSERT(!maybe_handle_info);
    int32_t underlying = static_cast<int32_t>(*value);
    ::fidl::Encode(encoder, &underlying, offset);
  }
  static void Decode(Decoder* decoder, ::test::consts::EnumType* value, size_t offset) {
    int32_t underlying = {};
    ::fidl::Decode(decoder, &underlying, offset);
    *value = static_cast<::test::consts::EnumType>(underlying);
  }
};

inline zx_status_t Clone(::test::consts::EnumType value,
                         ::test::consts::EnumType* result) {
  return ::test::consts::Clone(value, result);
}
template <>
struct Equality<::test::consts::EnumType> {
  bool operator()(const ::test::consts::EnumType& _lhs, const ::test::consts::EnumType& _rhs) const {
    return _lhs == _rhs;
  }
};

template <>
struct CodingTraits<::test::consts::BitsType> {
  static constexpr size_t kInlineSize = sizeof(::test::consts::BitsType);
  static void Encode(Encoder* encoder, ::test::consts::BitsType* value, size_t offset,
                     cpp17::optional<::fidl::HandleInformation> maybe_handle_info) {
    ZX_DEBUG_ASSERT(!maybe_handle_info);
    uint32_t underlying = static_cast<uint32_t>(*value);
    ::fidl::Encode(encoder, &underlying, offset);
  }
  static void Decode(Decoder* decoder, ::test::consts::BitsType* value, size_t offset) {
    uint32_t underlying = {};
    ::fidl::Decode(decoder, &underlying, offset);
    *value = static_cast<::test::consts::BitsType>(underlying);
  }
};

inline zx_status_t Clone(::test::consts::BitsType value,
                         ::test::consts::BitsType* result) {
  return ::test::consts::Clone(value, result);
}

template <>
struct Equality<::test::consts::BitsType> {
  bool operator()(const ::test::consts::BitsType& _lhs, const ::test::consts::BitsType& _rhs) const {
    uint32_t _lhs_underlying = static_cast<uint32_t>(_lhs);
    uint32_t _rhs_underlying = static_cast<uint32_t>(_rhs);
    return ::fidl::Equals(_lhs_underlying, _rhs_underlying);
  }
};

//
// Proxies and stubs declarations
//
}  // namespace fidl
