utils: Add index operators to UniqueVector

And put it into the utils namespace.

Change-Id: Ib4c6fadc63954196d572148d0e96ffec6e3bbb38
Reviewed-on: https://dawn-review.googlesource.com/c/tint/+/68404
Reviewed-by: Antonio Maiorano <amaiorano@google.com>
Kokoro: Kokoro <noreply+kokoro@google.com>
diff --git a/src/inspector/inspector.cc b/src/inspector/inspector.cc
index 19cf595..8fbd078 100644
--- a/src/inspector/inspector.cc
+++ b/src/inspector/inspector.cc
@@ -790,8 +790,8 @@
     return;
   }
 
-  sampler_targets_ = std::make_unique<
-      std::unordered_map<std::string, UniqueVector<SamplerTexturePair>>>();
+  sampler_targets_ = std::make_unique<std::unordered_map<
+      std::string, utils::UniqueVector<SamplerTexturePair>>>();
 
   auto& sem = program_->Sem();
 
@@ -873,7 +873,7 @@
 
   std::array<const sem::GlobalVariable*, N> globals{};
   std::array<const sem::Parameter*, N> parameters{};
-  UniqueVector<const ast::CallExpression*> callsites;
+  utils::UniqueVector<const ast::CallExpression*> callsites;
 
   for (size_t i = 0; i < N; i++) {
     auto*& expr = exprs[i];
diff --git a/src/inspector/inspector.h b/src/inspector/inspector.h
index 3fca877..c84233b 100644
--- a/src/inspector/inspector.h
+++ b/src/inspector/inspector.h
@@ -141,7 +141,7 @@
   const Program* program_;
   diag::List diagnostics_;
   std::unique_ptr<
-      std::unordered_map<std::string, UniqueVector<SamplerTexturePair>>>
+      std::unordered_map<std::string, utils::UniqueVector<SamplerTexturePair>>>
       sampler_targets_;
 
   /// @param name name of the entry point to find
diff --git a/src/reader/spirv/parser_impl.cc b/src/reader/spirv/parser_impl.cc
index b5ff8fc..65a57c9 100644
--- a/src/reader/spirv/parser_impl.cc
+++ b/src/reader/spirv/parser_impl.cc
@@ -876,8 +876,8 @@
     TINT_ASSERT(Reader, !inner_implementation_name.empty());
     TINT_ASSERT(Reader, ep_name != inner_implementation_name);
 
-    tint::UniqueVector<uint32_t> inputs;
-    tint::UniqueVector<uint32_t> outputs;
+    utils::UniqueVector<uint32_t> inputs;
+    utils::UniqueVector<uint32_t> outputs;
     for (unsigned iarg = 3; iarg < entry_point.NumInOperands(); iarg++) {
       const uint32_t var_id = entry_point.GetSingleWordInOperand(iarg);
       if (const auto* var_inst = def_use_mgr_->GetDef(var_id)) {
diff --git a/src/resolver/resolver.h b/src/resolver/resolver.h
index 212360b..edd8759 100644
--- a/src/resolver/resolver.h
+++ b/src/resolver/resolver.h
@@ -135,8 +135,8 @@
 
     const ast::Function* const declaration;
     std::vector<VariableInfo*> parameters;
-    UniqueVector<VariableInfo*> referenced_module_vars;
-    UniqueVector<VariableInfo*> local_referenced_module_vars;
+    utils::UniqueVector<VariableInfo*> referenced_module_vars;
+    utils::UniqueVector<VariableInfo*> local_referenced_module_vars;
     std::vector<const ast::ReturnStatement*> return_statements;
     std::vector<const ast::CallExpression*> callsites;
     sem::Type* return_type = nullptr;
@@ -145,10 +145,10 @@
     std::vector<IntrinsicCallInfo> intrinsic_calls;
 
     // List of transitive calls this function makes
-    UniqueVector<FunctionInfo*> transitive_calls;
+    utils::UniqueVector<FunctionInfo*> transitive_calls;
 
     // List of entry point functions that transitively call this function
-    UniqueVector<FunctionInfo*> ancestor_entry_points;
+    utils::UniqueVector<FunctionInfo*> ancestor_entry_points;
   };
 
   /// Structure holding semantic information about an expression.
diff --git a/src/transform/zero_init_workgroup_memory.cc b/src/transform/zero_init_workgroup_memory.cc
index f5948f6..46fc32c 100644
--- a/src/transform/zero_init_workgroup_memory.cc
+++ b/src/transform/zero_init_workgroup_memory.cc
@@ -74,7 +74,7 @@
   };
 
   /// A list of unique ArrayIndex
-  using ArrayIndices = UniqueVector<ArrayIndex, ArrayIndex::Hasher>;
+  using ArrayIndices = utils::UniqueVector<ArrayIndex, ArrayIndex::Hasher>;
 
   /// Expression holds information about an expression that is being built for a
   /// statement will zero workgroup values.
diff --git a/src/utils/unique_vector.h b/src/utils/unique_vector.h
index 1ae751a..8d92bea 100644
--- a/src/utils/unique_vector.h
+++ b/src/utils/unique_vector.h
@@ -19,6 +19,7 @@
 #include <vector>
 
 namespace tint {
+namespace utils {
 
 /// UniqueVector is an ordered container that only contains unique items.
 /// Attempting to add a duplicate is a no-op.
@@ -27,6 +28,18 @@
   /// The iterator returned by begin() and end()
   using ConstIterator = typename std::vector<T>::const_iterator;
 
+  /// Constructor
+  UniqueVector() = default;
+
+  /// Constructor
+  /// @param v the vector to construct this UniqueVector with. Duplicate
+  /// elements will be removed.
+  explicit UniqueVector(std::vector<T>&& v) {
+    for (auto& el : v) {
+      add(el);
+    }
+  }
+
   /// add appends the item to the end of the vector, if the vector does not
   /// already contain the given item.
   /// @param item the item to append to the end of the vector
@@ -41,6 +54,14 @@
   /// @param item the item
   bool contains(const T& item) const { return set.count(item); }
 
+  /// @param i the index of the element to retrieve
+  /// @returns the element at the index `i`
+  T& operator[](size_t i) { return vector[i]; }
+
+  /// @param i the index of the element to retrieve
+  /// @returns the element at the index `i`
+  const T& operator[](size_t i) const { return vector[i]; }
+
   /// @returns the number of items in the vector
   size_t size() const { return vector.size(); }
 
@@ -58,6 +79,7 @@
   std::unordered_set<T, HASH> set;
 };
 
+}  // namespace utils
 }  // namespace tint
 
 #endif  //  SRC_UTILS_UNIQUE_VECTOR_H_
diff --git a/src/utils/unique_vector_test.cc b/src/utils/unique_vector_test.cc
index 83f19e5..8d22525 100644
--- a/src/utils/unique_vector_test.cc
+++ b/src/utils/unique_vector_test.cc
@@ -17,6 +17,7 @@
 #include "gtest/gtest.h"
 
 namespace tint {
+namespace utils {
 namespace {
 
 TEST(UniqueVectorTest, Empty) {
@@ -25,6 +26,15 @@
   EXPECT_EQ(unique_vec.begin(), unique_vec.end());
 }
 
+TEST(UniqueVectorTest, MoveConstructor) {
+  UniqueVector<int> unique_vec(std::vector<int>{0, 3, 2, 1, 2});
+  EXPECT_EQ(unique_vec.size(), 4u);
+  EXPECT_EQ(unique_vec[0], 0);
+  EXPECT_EQ(unique_vec[1], 3);
+  EXPECT_EQ(unique_vec[2], 2);
+  EXPECT_EQ(unique_vec[3], 1);
+}
+
 TEST(UniqueVectorTest, AddUnique) {
   UniqueVector<int> unique_vec;
   unique_vec.add(0);
@@ -36,6 +46,9 @@
     EXPECT_EQ(n, i);
     i++;
   }
+  EXPECT_EQ(unique_vec[0], 0);
+  EXPECT_EQ(unique_vec[1], 1);
+  EXPECT_EQ(unique_vec[2], 2);
 }
 
 TEST(UniqueVectorTest, AddDuplicates) {
@@ -52,6 +65,9 @@
     EXPECT_EQ(n, i);
     i++;
   }
+  EXPECT_EQ(unique_vec[0], 0);
+  EXPECT_EQ(unique_vec[1], 1);
+  EXPECT_EQ(unique_vec[2], 2);
 }
 
 TEST(UniqueVectorTest, AsVector) {
@@ -73,4 +89,5 @@
 }
 
 }  // namespace
+}  // namespace utils
 }  // namespace tint