Add support for u8string and and u8string_view to absl/hash

PiperOrigin-RevId: 947095930
Change-Id: Ia62d5ccb0a28fef109abd6d2127116f8fc2c734b
diff --git a/absl/container/internal/hash_function_defaults.h b/absl/container/internal/hash_function_defaults.h
index d0fe31c..dcf7dbd 100644
--- a/absl/container/internal/hash_function_defaults.h
+++ b/absl/container/internal/hash_function_defaults.h
@@ -140,7 +140,7 @@
   }
 };
 
-// Supports heterogeneous lookup for w/u16/u32 string + string_view + char*.
+// Supports heterogeneous lookup for w/u8/u16/u32 string + string_view + char*.
 template <typename TChar>
 struct BasicStringHashEq {
   using Hash = BasicStringHash<TChar>;
@@ -151,6 +151,12 @@
 struct HashEq<std::wstring> : BasicStringHashEq<wchar_t> {};
 template <>
 struct HashEq<std::wstring_view> : BasicStringHashEq<wchar_t> {};
+#ifdef __cpp_char8_t
+template <>
+struct HashEq<std::u8string> : BasicStringHashEq<char8_t> {};
+template <>
+struct HashEq<std::u8string_view> : BasicStringHashEq<char8_t> {};
+#endif
 template <>
 struct HashEq<std::u16string> : BasicStringHashEq<char16_t> {};
 template <>
diff --git a/absl/container/internal/hash_function_defaults_test.cc b/absl/container/internal/hash_function_defaults_test.cc
index 4a304a9..67c853c 100644
--- a/absl/container/internal/hash_function_defaults_test.cc
+++ b/absl/container/internal/hash_function_defaults_test.cc
@@ -16,6 +16,7 @@
 
 #include <cstddef>
 #include <functional>
+#include <string>
 #include <string_view>
 #include <type_traits>
 #include <utility>
@@ -134,6 +135,28 @@
   EXPECT_FALSE(eq(L"a", std::wstring(L"b")));
 }
 
+#ifdef __cpp_char8_t
+TEST(BasicStringViewTest, U8StringEqWorks) {
+  hash_default_eq<std::u8string> eq;
+  EXPECT_TRUE(eq(u8"a", u8"a"));
+  EXPECT_TRUE(eq(u8"a", std::u8string_view(u8"a")));
+  EXPECT_TRUE(eq(u8"a", std::u8string(u8"a")));
+  EXPECT_FALSE(eq(u8"a", u8"b"));
+  EXPECT_FALSE(eq(u8"a", std::u8string_view(u8"b")));
+  EXPECT_FALSE(eq(u8"a", std::u8string(u8"b")));
+}
+
+TEST(BasicStringViewTest, U8StringViewEqWorks) {
+  hash_default_eq<std::u8string_view> eq;
+  EXPECT_TRUE(eq(u8"a", u8"a"));
+  EXPECT_TRUE(eq(u8"a", std::u8string_view(u8"a")));
+  EXPECT_TRUE(eq(u8"a", std::u8string(u8"a")));
+  EXPECT_FALSE(eq(u8"a", u8"b"));
+  EXPECT_FALSE(eq(u8"a", std::u8string_view(u8"b")));
+  EXPECT_FALSE(eq(u8"a", std::u8string(u8"b")));
+}
+#endif
+
 TEST(BasicStringViewTest, U16StringEqWorks) {
   hash_default_eq<std::u16string> eq;
   EXPECT_TRUE(eq(u"a", u"a"));
@@ -192,6 +215,26 @@
   EXPECT_NE(h, hash(std::wstring(L"b")));
 }
 
+#ifdef __cpp_char8_t
+TEST(BasicStringViewTest, U8StringHashWorks) {
+  hash_default_hash<std::u8string> hash;
+  auto h = hash(u8"a");
+  EXPECT_EQ(h, hash(std::u8string_view(u8"a")));
+  EXPECT_EQ(h, hash(std::u8string(u8"a")));
+  EXPECT_NE(h, hash(std::u8string_view(u8"b")));
+  EXPECT_NE(h, hash(std::u8string(u8"b")));
+}
+
+TEST(BasicStringViewTest, U8StringViewHashWorks) {
+  hash_default_hash<std::u8string_view> hash;
+  auto h = hash(u8"a");
+  EXPECT_EQ(h, hash(std::u8string_view(u8"a")));
+  EXPECT_EQ(h, hash(std::u8string(u8"a")));
+  EXPECT_NE(h, hash(std::u8string_view(u8"b")));
+  EXPECT_NE(h, hash(std::u8string(u8"b")));
+}
+#endif
+
 TEST(BasicStringViewTest, U16StringHashWorks) {
   hash_default_hash<std::u16string> hash;
   auto h = hash(u"a");
diff --git a/absl/hash/hash.h b/absl/hash/hash.h
index fc791ab..7a76771 100644
--- a/absl/hash/hash.h
+++ b/absl/hash/hash.h
@@ -117,11 +117,11 @@
 //   * All string-like types including:
 //     * absl::Cord
 //     * std::string (as well as any instance of std::basic_string that
-//       uses one of {char, wchar_t, char16_t, char32_t} and its associated
-//       std::char_traits)
+//       uses one of {char, wchar_t, char8_t, char16_t, char32_t} and its
+//       associated std::char_traits)
 //     * std::string_view (as well as any instance of std::basic_string_view
-//       that uses one of {char, wchar_t, char16_t, char32_t} and its associated
-//       std::char_traits)
+//       that uses one of {char, wchar_t, char8_t, char16_t, char32_t} and its
+//       associated std::char_traits)
 //  * All the standard sequence containers (provided the elements are hashable)
 //  * All the standard associative containers (provided the elements are
 //    hashable)
diff --git a/absl/hash/hash_test.cc b/absl/hash/hash_test.cc
index c39031a..c52a524 100644
--- a/absl/hash/hash_test.cc
+++ b/absl/hash/hash_test.cc
@@ -484,6 +484,17 @@
       std::wstring(L"Iñtërnâtiônàlizætiøn"))));
 }
 
+#ifdef __cpp_char8_t
+TEST(HashValueTest, U8String) {
+  EXPECT_TRUE((is_hashable<std::u8string>::value));
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(std::make_tuple(
+      std::u8string(), std::u8string(u8"ABC"), std::u8string(u8"ABC"),
+      std::u8string(u8"Some other different string"),
+      std::u8string(u8"Iñtërnâtiônàlizætiøn"))));
+}
+#endif
+
 TEST(HashValueTest, U16String) {
   EXPECT_TRUE((is_hashable<std::u16string>::value));
 
@@ -511,6 +522,18 @@
       std::wstring_view(L"Iñtërnâtiônàlizætiøn"))));
 }
 
+#ifdef __cpp_char8_t
+TEST(HashValueTest, U8StringView) {
+  EXPECT_TRUE((is_hashable<std::u8string_view>::value));
+
+  EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly(
+      std::make_tuple(std::u8string_view(), std::u8string_view(u8"ABC"),
+                      std::u8string_view(u8"ABC"),
+                      std::u8string_view(u8"Some other different string_view"),
+                      std::u8string_view(u8"Iñtërnâtiônàlizætiøn"))));
+}
+#endif
+
 TEST(HashValueTest, U16StringView) {
   EXPECT_TRUE((is_hashable<std::u16string_view>::value));
 
diff --git a/absl/hash/internal/hash.h b/absl/hash/internal/hash.h
index 972e9bd..db6e059 100644
--- a/absl/hash/internal/hash.h
+++ b/absl/hash/internal/hash.h
@@ -645,22 +645,27 @@
 //
 //  - `absl::Cord`
 //  - `std::string` (and std::basic_string<T, std::char_traits<T>, A> for
-//      any allocator A and any T in {char, wchar_t, char16_t, char32_t})
+//      any allocator A and any T in {char, wchar_t, char8_t, char16_t,
+//      char32_t})
 //  - `absl::string_view`, `std::string_view`, `std::wstring_view`,
-//    `std::u16string_view`, and `std::u32_string_view`.
+//    `std::u8string_view`, `std::u16string_view`, and `std::u32_string_view`.
 //
 // For simplicity, we currently support only strings built on `char`, `wchar_t`,
-// `char16_t`, or `char32_t`. This support may be broadened, if necessary, but
-// with some caution - this overload would misbehave in cases where the traits'
-// `eq()` member isn't equivalent to `==` on the underlying character type.
+// `char8_t`, `char16_t`, or `char32_t`. This support may be broadened, if
+// necessary, but with some caution - this overload would misbehave in cases
+// where the traits' `eq()` member isn't equivalent to `==` on the underlying
+// character type.
 template <typename H>
 H AbslHashValue(H hash_state, absl::string_view str) {
   return H::combine_contiguous(std::move(hash_state), str.data(), str.size());
 }
 
-// Support std::wstring, std::u16string and std::u32string.
+// Support std::wstring, std::u8string, std::u16string and std::u32string.
 template <typename Char, typename Alloc, typename H,
           typename = std::enable_if_t<std::is_same_v<Char, wchar_t> ||
+#ifdef __cpp_char8_t
+                                      std::is_same_v<Char, char8_t> ||
+#endif
                                       std::is_same_v<Char, char16_t> ||
                                       std::is_same_v<Char, char32_t>>>
 H AbslHashValue(
@@ -669,9 +674,13 @@
   return H::combine_contiguous(std::move(hash_state), str.data(), str.size());
 }
 
-// Support std::wstring_view, std::u16string_view and std::u32string_view.
+// Support std::wstring_view, std::u8string_view, std::u16string_view and
+// std::u32string_view.
 template <typename Char, typename H,
           typename = std::enable_if_t<std::is_same_v<Char, wchar_t> ||
+#ifdef __cpp_char8_t
+                                      std::is_same_v<Char, char8_t> ||
+#endif
                                       std::is_same_v<Char, char16_t> ||
                                       std::is_same_v<Char, char32_t>>>
 H AbslHashValue(H hash_state, std::basic_string_view<Char> str) {