namespace dawn_native {

    static_assert(static_cast<uint32_t>(dawn::ShaderStage::Vertex) < kNumStages, "");
    static_assert(static_cast<uint32_t>(dawn::ShaderStage::Fragment) < kNumStages, "");
    static_assert(static_cast<uint32_t>(dawn::ShaderStage::Compute) < kNumStages, "");

    static_assert(static_cast<uint32_t>(dawn::ShaderStageBit::Vertex) ==
                      (1 << static_cast<uint32_t>(dawn::ShaderStage::Vertex)),
                  "");
    static_assert(static_cast<uint32_t>(dawn::ShaderStageBit::Fragment) ==
                      (1 << static_cast<uint32_t>(dawn::ShaderStage::Fragment)),
                  "");
    static_assert(static_cast<uint32_t>(dawn::ShaderStageBit::Compute) ==
                      (1 << static_cast<uint32_t>(dawn::ShaderStage::Compute)),
                  "");

    BitSetIterator<kNumStages, dawn::ShaderStage> IterateStages(dawn::ShaderStageBit stages);
    dawn::ShaderStageBit StageBit(dawn::ShaderStage stage);

    static constexpr dawn::ShaderStageBit kAllStages =
        static_cast<dawn::ShaderStageBit>((1 << kNumStages) - 1);

    template <typename T>
    class PerStage {
      public:
        PerStage() = default;
        PerStage(const T& initialValue) {
            mData.fill(initialValue);
        }

        T& operator[](dawn::ShaderStage stage) {
            DAWN_ASSERT(static_cast<uint32_t>(stage) < kNumStages);
            return mData[static_cast<uint32_t>(stage)];
        }
        const T& operator[](dawn::ShaderStage stage) const {
            DAWN_ASSERT(static_cast<uint32_t>(stage) < kNumStages);
            return mData[static_cast<uint32_t>(stage)];
        }

        T& operator[](dawn::ShaderStageBit stageBit) {
            uint32_t bit = static_cast<uint32_t>(stageBit);
            DAWN_ASSERT(bit != 0 && IsPowerOfTwo(bit) && bit <= (1 << kNumStages));
            return mData[Log2(bit)];
        }
        const T& operator[](dawn::ShaderStageBit stageBit) const {
            uint32_t bit = static_cast<uint32_t>(stageBit);
            DAWN_ASSERT(bit != 0 && IsPowerOfTwo(bit) && bit <= (1 << kNumStages));
            return mData[Log2(bit)];
        }

      private:
        std::array<T, kNumStages> mData;
    };

}  // namespace dawn_native

#endif  // DAWNNATIVE_PERSTAGE_H_
