|  | // Copyright 2022 The Dawn & Tint Authors | 
|  | // | 
|  | // Redistribution and use in source and binary forms, with or without | 
|  | // modification, are permitted provided that the following conditions are met: | 
|  | // | 
|  | // 1. Redistributions of source code must retain the above copyright notice, this | 
|  | //    list of conditions and the following disclaimer. | 
|  | // | 
|  | // 2. Redistributions in binary form must reproduce the above copyright notice, | 
|  | //    this list of conditions and the following disclaimer in the documentation | 
|  | //    and/or other materials provided with the distribution. | 
|  | // | 
|  | // 3. Neither the name of the copyright holder nor the names of its | 
|  | //    contributors may be used to endorse or promote products derived from | 
|  | //    this software without specific prior written permission. | 
|  | // | 
|  | // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" | 
|  | // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE | 
|  | // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE | 
|  | // DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE | 
|  | // FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | 
|  | // DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR | 
|  | // SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER | 
|  | // CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, | 
|  | // OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE | 
|  | // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | 
|  |  | 
|  | #ifndef SRC_TINT_UTILS_CONTAINERS_HASHSET_H_ | 
|  | #define SRC_TINT_UTILS_CONTAINERS_HASHSET_H_ | 
|  |  | 
|  | #include <stddef.h> | 
|  | #include <algorithm> | 
|  | #include <functional> | 
|  | #include <optional> | 
|  | #include <tuple> | 
|  | #include <utility> | 
|  |  | 
|  | #include "src/tint/utils/containers/hashmap.h" | 
|  | #include "src/tint/utils/containers/vector.h" | 
|  |  | 
|  | namespace tint { | 
|  |  | 
|  | /// An unordered hashset, with a fixed-size capacity that avoids heap allocations. | 
|  | template <typename KEY, size_t N, typename HASH = Hasher<KEY>, typename EQUAL = std::equal_to<KEY>> | 
|  | class Hashset : public HashmapBase<HashmapKey<KEY, HASH, EQUAL>, N> { | 
|  | using Base = HashmapBase<HashmapKey<KEY, HASH, EQUAL>, N>; | 
|  |  | 
|  | public: | 
|  | using Base::Base; | 
|  |  | 
|  | /// Constructor with initializer list of items | 
|  | /// @param items the items to place into the set | 
|  | Hashset(std::initializer_list<KEY> items) { | 
|  | this->Reserve(items.size()); | 
|  | for (auto item : items) { | 
|  | this->Add(item); | 
|  | } | 
|  | } | 
|  |  | 
|  | /// Adds a value to the set, if the set does not already contain an entry equal to `value`. | 
|  | /// @param value the value to add to the set. | 
|  | /// @returns true if the value was added, false if there was an existing value in the set. | 
|  | template <typename V> | 
|  | bool Add(V&& value) { | 
|  | auto idx = this->EditAt(value); | 
|  | if (idx.entry) { | 
|  | return false;  // Entry already exists | 
|  | } | 
|  | idx.Insert(std::forward<V>(value)); | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /// @returns the set entries of the map as a vector | 
|  | /// @note the order of the returned vector is non-deterministic between compilers. | 
|  | template <size_t N2 = N> | 
|  | tint::Vector<KEY, N2> Vector() const { | 
|  | tint::Vector<KEY, N2> out; | 
|  | out.Reserve(this->Count()); | 
|  | for (auto& key : *this) { | 
|  | out.Push(key.Value()); | 
|  | } | 
|  | return out; | 
|  | } | 
|  |  | 
|  | /// @returns true if the predicate function returns true for any of the elements of the set | 
|  | /// @param pred a function-like with the signature `bool(T)` | 
|  | template <typename PREDICATE> | 
|  | bool Any(PREDICATE&& pred) const { | 
|  | for (const auto& key : *this) { | 
|  | if (pred(key.Value())) { | 
|  | return true; | 
|  | } | 
|  | } | 
|  | return false; | 
|  | } | 
|  |  | 
|  | /// @returns false if the predicate function returns false for any of the elements of the set | 
|  | /// @param pred a function-like with the signature `bool(T)` | 
|  | template <typename PREDICATE> | 
|  | bool All(PREDICATE&& pred) const { | 
|  | for (const auto& key : *this) { | 
|  | if (!pred(key.Value())) { | 
|  | return false; | 
|  | } | 
|  | } | 
|  | return true; | 
|  | } | 
|  |  | 
|  | /// Looks up an entry in the set that is equal to @p key | 
|  | /// @param key the key to search for. | 
|  | /// @returns the entry that is equal to @p key | 
|  | std::optional<KEY> Get(const KEY& key) const { | 
|  | if (auto [found, index] = this->IndexOf(key); found) { | 
|  | return this->slots_[index].entry; | 
|  | } | 
|  | return std::nullopt; | 
|  | } | 
|  | }; | 
|  |  | 
|  | }  // namespace tint | 
|  |  | 
|  | #endif  // SRC_TINT_UTILS_CONTAINERS_HASHSET_H_ |