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

#pragma once

#include <lib/fidl/llcpp/internal/display_error.h>
#include <lib/fidl/llcpp/traits.h>
#include <lib/stdcompat/optional.h>

#include <cinttypes>

namespace test_versions {
// |Bits| is flexible, hence may contain unknown members not
// defined in the FIDL schema.
class Bits final {
 public:
  constexpr Bits() = default;

  // Constructs an instance of |Bits| from an underlying primitive value,
  // preserving any bit member not defined in the FIDL schema.
  explicit constexpr Bits(uint32_t value) : value_(value) {}
  const static Bits kA;
  const static Bits kMask;

  explicit constexpr inline operator uint32_t() const { return value_; }
  explicit constexpr inline operator bool() const { return static_cast<bool>(value_); }
  constexpr inline bool operator==(const Bits& other) const { return value_ == other.value_; }
  constexpr inline bool operator!=(const Bits& other) const { return value_ != other.value_; }
  constexpr inline Bits operator~() const;
  constexpr inline Bits operator|(const Bits& other) const;
  constexpr inline Bits operator&(const Bits& other) const;
  constexpr inline Bits operator^(const Bits& other) const;
  constexpr inline void operator|=(const Bits& other);
  constexpr inline void operator&=(const Bits& other);
  constexpr inline void operator^=(const Bits& other);

  // Constructs an instance of |Bits| from an underlying primitive value
  // if the primitive does not contain any unknown members not defined in the
  // FIDL schema. Otherwise, returns |std::nullopt|.
  constexpr inline static std::optional<Bits> TryFrom(uint32_t value) {
    if (value & ~kMask.value_) {
      return std::nullopt;
    }
    return Bits(value & Bits::kMask.value_);
  }

  // Constructs an instance of |Bits| from an underlying primitive value,
  // clearing any bit member not defined in the FIDL schema.
  constexpr inline static Bits TruncatingUnknown(uint32_t value) {
    return Bits(value & Bits::kMask.value_);
  }
  constexpr inline Bits unknown_bits() const {
    return *this & Bits(~kMask.value_);
  }
  constexpr inline bool has_unknown_bits() const { return static_cast<bool>(unknown_bits()); }

 private:
  uint32_t value_ = 0;
};
constexpr const ::test_versions::Bits Bits::kA =
    ::test_versions::Bits(1u);
constexpr const ::test_versions::Bits Bits::kMask = ::test_versions::Bits(1u);

constexpr inline ::test_versions::Bits Bits::operator~() const {
  return ::test_versions::Bits(static_cast<uint32_t>(~this->value_ & kMask.value_));
}

constexpr inline ::test_versions::Bits Bits::operator|(
    const ::test_versions::Bits& other) const {
  return ::test_versions::Bits(static_cast<uint32_t>(this->value_ | other.value_));
}

constexpr inline ::test_versions::Bits Bits::operator&(
    const ::test_versions::Bits& other) const {
  return ::test_versions::Bits(static_cast<uint32_t>(this->value_ & other.value_));
}

constexpr inline ::test_versions::Bits Bits::operator^(
    const ::test_versions::Bits& other) const {
  return ::test_versions::Bits(static_cast<uint32_t>(this->value_ ^ other.value_));
}

constexpr inline void Bits::operator|=(
    const ::test_versions::Bits& other) {
  this->value_ |= other.value_;
}

constexpr inline void Bits::operator&=(
    const ::test_versions::Bits& other) {
  this->value_ &= other.value_;
}

constexpr inline void Bits::operator^=(
    const ::test_versions::Bits& other) {
  this->value_ ^= other.value_;
}

class Enum final {
 public:
  constexpr Enum() : value_(0) {}
  constexpr explicit Enum(uint32_t value) : value_(value) {}
  constexpr operator uint32_t() const { return value_; }

  constexpr bool IsUnknown() const {
    switch (value_) {
      case 1u:

        return false;
    }
    return true;
  }

  constexpr static Enum Unknown() {
    return Enum(0xffffffff);
  }

  static const Enum kA;

 private:
  uint32_t value_;
};
constexpr const ::test_versions::Enum Enum::kA =
    ::test_versions::Enum(1u);

}  // namespace test_versions
template <>
struct fidl::internal::DisplayError<::test_versions::Enum> {
  static size_t Format(const ::test_versions::Enum& value, char* destination, size_t capacity);
};

namespace fidl {

template <>
struct IsFidlType<::test_versions::Bits> : public std::true_type {};
template <>
struct ContainsHandle<::test_versions::Bits> : public std::false_type {};
static_assert(std::is_standard_layout_v<::test_versions::Bits>);
static_assert(sizeof(::test_versions::Bits) == sizeof(uint32_t));

template <>
struct IsFidlType<::test_versions::Enum> : public std::true_type {};
template <>
struct ContainsHandle<::test_versions::Enum> : public std::false_type {};

}  // namespace fidl
