// 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
