tint/utils: Add Hashmap::Keys(), Hashmap::Values()

Change-Id: If51cb3f42e50db842ecd006bcfbbbd060957e650
Reviewed-on: https://dawn-review.googlesource.com/c/dawn/+/112281
Commit-Queue: Ben Clayton <bclayton@google.com>
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
Kokoro: Ben Clayton <bclayton@google.com>
diff --git a/src/tint/utils/hashmap.h b/src/tint/utils/hashmap.h
index 19a5abe..a37eab9 100644
--- a/src/tint/utils/hashmap.h
+++ b/src/tint/utils/hashmap.h
@@ -182,6 +182,30 @@
     /// @returns a reference to the entry that is equal to the given value.
     ConstReference Find(const Key& key) const { return ConstReference(*this, key); }
 
+    /// @returns the keys of the map as a vector.
+    /// @note the order of the returned vector is non-deterministic between compilers.
+    template <size_t N2 = N>
+    Vector<Key, N2> Keys() const {
+        Vector<Key, N2> out;
+        out.Reserve(this->Count());
+        for (auto it : *this) {
+            out.Push(it.key);
+        }
+        return out;
+    }
+
+    /// @returns the values of the map as a vector
+    /// @note the order of the returned vector is non-deterministic between compilers.
+    template <size_t N2 = N>
+    Vector<Value, N2> Values() const {
+        Vector<Value, N2> out;
+        out.Reserve(this->Count());
+        for (auto it : *this) {
+            out.Push(it.value);
+        }
+        return out;
+    }
+
   private:
     Value* Lookup(const Key& key) {
         if (auto [found, index] = this->IndexOf(key); found) {
diff --git a/src/tint/utils/hashmap_test.cc b/src/tint/utils/hashmap_test.cc
index 6226967..3991eb2 100644
--- a/src/tint/utils/hashmap_test.cc
+++ b/src/tint/utils/hashmap_test.cc
@@ -182,6 +182,17 @@
                                                    Entry{3, "three!"}, Entry{4, "four!"}));
 }
 
+TEST(Hashmap, KeysValues) {
+    using Map = Hashmap<int, std::string, 8>;
+    Map map;
+    map.Add(1, "one");
+    map.Add(4, "four");
+    map.Add(3, "three");
+    map.Add(2, "two");
+    EXPECT_THAT(map.Keys(), testing::UnorderedElementsAre(1, 2, 3, 4));
+    EXPECT_THAT(map.Values(), testing::UnorderedElementsAre("one", "two", "three", "four"));
+}
+
 TEST(Hashmap, AddMany) {
     Hashmap<int, std::string, 8> map;
     for (size_t i = 0; i < kPrimes.size(); i++) {