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

#pragma once

#include "lib/fidl/cpp/internal/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);
  }
};

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