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

#pragma once

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

//
// Domain objects declarations (i.e. "natural types" in unified bindings).
//
namespace fidl {
namespace test {
namespace consts {

enum class EnumType : int32_t {

  VALUE = 1u,

  true_ = 2u,
};

inline zx_status_t Clone(::fidl::test::consts::EnumType value,
                         ::fidl::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 ::fidl::test::consts::BitsType operator|(
    ::fidl::test::consts::BitsType _lhs, ::fidl::test::consts::BitsType _rhs) {
  return static_cast<::fidl::test::consts::BitsType>(
      static_cast<uint32_t>(_lhs) | static_cast<uint32_t>(_rhs));
}

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

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

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

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

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

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

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

extern const char* USERNAME;

constexpr uint32_t POPULATION_USA_2018 = 330000000u;

constexpr int8_t OFFSET = -33;

constexpr float MIN_TEMP = -273.15f;

constexpr uint64_t FUCHSIA = 4054509061583223046u;

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

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

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

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

constexpr bool ENABLED_FLAG = true;

constexpr uint64_t DIAMOND = 1746410393481133080u;

constexpr double CONVERSION_FACTOR = 1.41421;

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

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

constexpr int32_t bitsPrimitiveVal = ::fidl::test::consts::BitsType::VALUE;

constexpr int32_t bitsPrimitiveTrue = ::fidl::test::consts::BitsType::true_;

constexpr uint16_t ANSWER_IN_BINARY = 42u;

constexpr uint16_t ANSWER = 42u;

}  // namespace consts
}  // namespace test
template <>
struct CodingTraits<::fidl::test::consts::EnumType> {
  static constexpr size_t inline_size_old =
      sizeof(::fidl::test::consts::EnumType);
  static constexpr size_t inline_size_v1_no_ee =
      sizeof(::fidl::test::consts::EnumType);
  static void Encode(
      Encoder* encoder, ::fidl::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, ::fidl::test::consts::EnumType* value,
                     size_t offset) {
    int32_t underlying = {};
    ::fidl::Decode(decoder, &underlying, offset);
    *value = static_cast<::fidl::test::consts::EnumType>(underlying);
  }
};

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

template <>
struct CodingTraits<::fidl::test::consts::BitsType> {
  static constexpr size_t inline_size_old =
      sizeof(::fidl::test::consts::BitsType);
  static constexpr size_t inline_size_v1_no_ee =
      sizeof(::fidl::test::consts::BitsType);
  static void Encode(
      Encoder* encoder, ::fidl::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, ::fidl::test::consts::BitsType* value,
                     size_t offset) {
    uint32_t underlying = {};
    ::fidl::Decode(decoder, &underlying, offset);
    *value = static_cast<::fidl::test::consts::BitsType>(underlying);
  }
};

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

template <>
struct Equality<::fidl::test::consts::BitsType> {
  bool operator()(const ::fidl::test::consts::BitsType& _lhs,
                  const ::fidl::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);
  }
};

}  // namespace fidl
