Adopt absl::string_view in rtc_base/string_encode.*

Bug: webrtc:13579
Change-Id: If52108d151a12bde0e8d552ce7940948c08cef3a
Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/256812
Reviewed-by: Mirko Bonadei <mbonadei@webrtc.org>
Reviewed-by: Niels Moller <nisse@webrtc.org>
Reviewed-by: Jakob Ivarsson‎ <jakobi@webrtc.org>
Reviewed-by: Per Kjellander <perkj@webrtc.org>
Commit-Queue: Ali Tofigh <alito@webrtc.org>
Cr-Commit-Position: refs/heads/main@{#36424}
diff --git a/examples/BUILD.gn b/examples/BUILD.gn
index afb410d..0a5ee10 100644
--- a/examples/BUILD.gn
+++ b/examples/BUILD.gn
@@ -67,7 +67,11 @@
     "turnserver/read_auth_file.cc",
     "turnserver/read_auth_file.h",
   ]
-  deps = [ "../rtc_base" ]
+  deps = [
+    "../api:array_view",
+    "../rtc_base",
+  ]
+  absl_deps = [ "//third_party/abseil-cpp/absl/strings:strings" ]
 }
 
 if (rtc_include_tests) {
diff --git a/examples/turnserver/read_auth_file.cc b/examples/turnserver/read_auth_file.cc
index 3ad5c2b..4b0b21b 100644
--- a/examples/turnserver/read_auth_file.cc
+++ b/examples/turnserver/read_auth_file.cc
@@ -12,6 +12,8 @@
 
 #include <stddef.h>
 
+#include "absl/strings/string_view.h"
+#include "api/array_view.h"
 #include "rtc_base/string_encode.h"
 
 namespace webrtc_examples {
@@ -23,8 +25,8 @@
     if (sep == std::string::npos)
       continue;
     char buf[32];
-    size_t len = rtc::hex_decode(buf, sizeof(buf), line.data() + sep + 1,
-                                 line.size() - sep - 1);
+    size_t len = rtc::hex_decode(rtc::ArrayView<char>(buf),
+                                 absl::string_view(line).substr(sep + 1));
     if (len > 0) {
       name_to_key.emplace(line.substr(0, sep), std::string(buf, len));
     }
diff --git a/modules/audio_coding/acm2/audio_coding_module_unittest.cc b/modules/audio_coding/acm2/audio_coding_module_unittest.cc
index c429cc4..1a63fcd 100644
--- a/modules/audio_coding/acm2/audio_coding_module_unittest.cc
+++ b/modules/audio_coding/acm2/audio_coding_module_unittest.cc
@@ -1114,8 +1114,7 @@
     // Extract and verify the payload checksum.
     rtc::Buffer checksum_result(payload_checksum_->Size());
     payload_checksum_->Finish(checksum_result.data(), checksum_result.size());
-    checksum_string =
-        rtc::hex_encode(checksum_result.data<char>(), checksum_result.size());
+    checksum_string = rtc::hex_encode(checksum_result);
     ExpectChecksumEq(payload_checksum_ref, checksum_string);
 
     // Verify number of packets produced.
diff --git a/modules/audio_coding/neteq/test/result_sink.cc b/modules/audio_coding/neteq/test/result_sink.cc
index b700161..0822e00 100644
--- a/modules/audio_coding/neteq/test/result_sink.cc
+++ b/modules/audio_coding/neteq/test/result_sink.cc
@@ -10,8 +10,9 @@
 
 #include "modules/audio_coding/neteq/test/result_sink.h"
 
-#include <vector>
+#include <string>
 
+#include "absl/strings/string_view.h"
 #include "rtc_base/ignore_wundef.h"
 #include "rtc_base/message_digest.h"
 #include "rtc_base/string_encode.h"
@@ -91,10 +92,10 @@
 }
 
 void ResultSink::VerifyChecksum(const std::string& checksum) {
-  std::vector<char> buffer;
+  std::string buffer;
   buffer.resize(digest_->Size());
-  digest_->Finish(&buffer[0], buffer.size());
-  const std::string result = rtc::hex_encode(&buffer[0], digest_->Size());
+  digest_->Finish(buffer.data(), buffer.size());
+  const std::string result = rtc::hex_encode(buffer);
   if (checksum.size() == result.size()) {
     EXPECT_EQ(checksum, result);
   } else {
diff --git a/modules/audio_coding/neteq/tools/audio_checksum.h b/modules/audio_coding/neteq/tools/audio_checksum.h
index 9d6f343..42e3a3a 100644
--- a/modules/audio_coding/neteq/tools/audio_checksum.h
+++ b/modules/audio_coding/neteq/tools/audio_checksum.h
@@ -50,8 +50,7 @@
       finished_ = true;
       checksum_->Finish(checksum_result_.data(), checksum_result_.size());
     }
-    return rtc::hex_encode(checksum_result_.data<char>(),
-                           checksum_result_.size());
+    return rtc::hex_encode(checksum_result_);
   }
 
  private:
diff --git a/p2p/BUILD.gn b/p2p/BUILD.gn
index 9c2d839..f5e05c1 100644
--- a/p2p/BUILD.gn
+++ b/p2p/BUILD.gn
@@ -284,6 +284,7 @@
   ]
   deps = [
     ":rtc_p2p",
+    "../api:array_view",
     "../api:packet_socket_factory",
     "../api:sequence_checker",
     "../api/transport:stun_types",
diff --git a/p2p/base/turn_server.cc b/p2p/base/turn_server.cc
index 863319e..6a5d7a9 100644
--- a/p2p/base/turn_server.cc
+++ b/p2p/base/turn_server.cc
@@ -16,6 +16,7 @@
 
 #include "absl/algorithm/container.h"
 #include "absl/memory/memory.h"
+#include "api/array_view.h"
 #include "api/packet_socket_factory.h"
 #include "api/transport/stun.h"
 #include "p2p/base/async_stun_tcp_socket.h"
@@ -421,7 +422,7 @@
 std::string TurnServer::GenerateNonce(int64_t now) const {
   // Generate a nonce of the form hex(now + HMAC-MD5(nonce_key_, now))
   std::string input(reinterpret_cast<const char*>(&now), sizeof(now));
-  std::string nonce = rtc::hex_encode(input.c_str(), input.size());
+  std::string nonce = rtc::hex_encode(input);
   nonce += rtc::ComputeHmac(rtc::DIGEST_MD5, nonce_key_, input);
   RTC_DCHECK(nonce.size() == kNonceSize);
 
@@ -437,8 +438,8 @@
   // Decode the timestamp.
   int64_t then;
   char* p = reinterpret_cast<char*>(&then);
-  size_t len =
-      rtc::hex_decode(p, sizeof(then), nonce.substr(0, sizeof(then) * 2));
+  size_t len = rtc::hex_decode(rtc::ArrayView<char>(p, sizeof(then)),
+                               nonce.substr(0, sizeof(then) * 2));
   if (len != sizeof(then)) {
     return false;
   }
diff --git a/pc/BUILD.gn b/pc/BUILD.gn
index a905819..964c51e 100644
--- a/pc/BUILD.gn
+++ b/pc/BUILD.gn
@@ -567,7 +567,10 @@
     "../rtc_base/synchronization:mutex",
     "../system_wrappers:metrics",
   ]
-  absl_deps = [ "//third_party/abseil-cpp/absl/base:core_headers" ]
+  absl_deps = [
+    "//third_party/abseil-cpp/absl/base:core_headers",
+    "//third_party/abseil-cpp/absl/strings:strings",
+  ]
   if (rtc_build_libsrtp) {
     deps += [ "//third_party/libsrtp" ]
   }
diff --git a/pc/srtp_session.cc b/pc/srtp_session.cc
index 41c9b46..d01bc38 100644
--- a/pc/srtp_session.cc
+++ b/pc/srtp_session.cc
@@ -17,6 +17,7 @@
 
 #include "absl/base/attributes.h"
 #include "absl/base/const_init.h"
+#include "absl/strings/string_view.h"
 #include "api/array_view.h"
 #include "api/field_trials_view.h"
 #include "modules/rtp_rtcp/source/rtp_util.h"
@@ -471,13 +472,16 @@
   int64_t minutes = (time_of_day / (60 * 1000)) % 60;
   int64_t seconds = (time_of_day / 1000) % 60;
   int64_t millis = time_of_day % 1000;
-  RTC_LOG(LS_VERBOSE) << "\n" << (outbound ? "O" : "I") << " "
-    << std::setfill('0') << std::setw(2) << hours << ":"
-    << std::setfill('0') << std::setw(2) << minutes << ":"
-    << std::setfill('0') << std::setw(2) << seconds << "."
-    << std::setfill('0') << std::setw(3) << millis << " "
-    << "000000 " << rtc::hex_encode_with_delimiter((const char *)buf, len, ' ')
-    << " # RTP_DUMP";
+  RTC_LOG(LS_VERBOSE) << "\n"
+                      << (outbound ? "O" : "I") << " " << std::setfill('0')
+                      << std::setw(2) << hours << ":" << std::setfill('0')
+                      << std::setw(2) << minutes << ":" << std::setfill('0')
+                      << std::setw(2) << seconds << "." << std::setfill('0')
+                      << std::setw(3) << millis << " "
+                      << "000000 "
+                      << rtc::hex_encode_with_delimiter(
+                             absl::string_view((const char*)buf, len), ' ')
+                      << " # RTP_DUMP";
 }
 
 }  // namespace cricket
diff --git a/rtc_base/buffer.h b/rtc_base/buffer.h
index c9bf2cc..be8e22b 100644
--- a/rtc_base/buffer.h
+++ b/rtc_base/buffer.h
@@ -19,6 +19,7 @@
 #include <type_traits>
 #include <utility>
 
+#include "absl/strings/string_view.h"
 #include "api/array_view.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/type_traits.h"
@@ -117,6 +118,13 @@
 
   ~BufferT() { MaybeZeroCompleteBuffer(); }
 
+  // Implicit conversion to absl::string_view if T is compatible with char.
+  template <typename U = T>
+  operator typename std::enable_if<internal::BufferCompat<U, char>::value,
+                                   absl::string_view>::type() const {
+    return absl::string_view(data<char>(), size());
+  }
+
   // Get a pointer to the data. Just .data() will give you a (const) T*, but if
   // T is a byte-sized integer, you may also use .data<U>() for any other
   // byte-sized integer U.
diff --git a/rtc_base/buffer_unittest.cc b/rtc_base/buffer_unittest.cc
index 8beae43..b56118a 100644
--- a/rtc_base/buffer_unittest.cc
+++ b/rtc_base/buffer_unittest.cc
@@ -13,6 +13,7 @@
 #include <cstdint>
 #include <utility>
 
+#include "absl/strings/string_view.h"
 #include "api/array_view.h"
 #include "test/gmock.h"
 #include "test/gtest.h"
@@ -73,6 +74,13 @@
   EXPECT_EQ(0, memcmp(buf.data(), kTestData, 16));
 }
 
+TEST(BufferTest, TestStringViewConversion) {
+  Buffer buf(kTestData);
+  absl::string_view view = buf;
+  EXPECT_EQ(view,
+            absl::string_view(reinterpret_cast<const char*>(kTestData), 16u));
+}
+
 TEST(BufferTest, TestSetData) {
   Buffer buf(kTestData + 4, 7);
   buf.SetData(kTestData, 9);
diff --git a/rtc_base/message_digest.cc b/rtc_base/message_digest.cc
index 3b39cf9..56abcd2 100644
--- a/rtc_base/message_digest.cc
+++ b/rtc_base/message_digest.cc
@@ -74,7 +74,7 @@
   std::unique_ptr<char[]> output(new char[digest->Size()]);
   ComputeDigest(digest, input.data(), input.size(), output.get(),
                 digest->Size());
-  return hex_encode(output.get(), digest->Size());
+  return hex_encode(absl::string_view(output.get(), digest->Size()));
 }
 
 bool ComputeDigest(absl::string_view alg,
@@ -157,7 +157,7 @@
   std::unique_ptr<char[]> output(new char[digest->Size()]);
   ComputeHmac(digest, key.data(), key.size(), input.data(), input.size(),
               output.get(), digest->Size());
-  return hex_encode(output.get(), digest->Size());
+  return hex_encode(absl::string_view(output.get(), digest->Size()));
 }
 
 bool ComputeHmac(absl::string_view alg,
diff --git a/rtc_base/message_digest_unittest.cc b/rtc_base/message_digest_unittest.cc
index 85e9bbd..b296783 100644
--- a/rtc_base/message_digest_unittest.cc
+++ b/rtc_base/message_digest_unittest.cc
@@ -10,6 +10,7 @@
 
 #include "rtc_base/message_digest.h"
 
+#include "absl/strings/string_view.h"
 #include "rtc_base/string_encode.h"
 #include "test/gtest.h"
 
@@ -29,7 +30,7 @@
   EXPECT_EQ(sizeof(output),
             ComputeDigest(DIGEST_MD5, "abc", 3, output, sizeof(output)));
   EXPECT_EQ("900150983cd24fb0d6963f7d28e17f72",
-            hex_encode(output, sizeof(output)));
+            hex_encode(absl::string_view(output, sizeof(output))));
   EXPECT_EQ(0U,
             ComputeDigest(DIGEST_MD5, "abc", 3, output, sizeof(output) - 1));
 }
@@ -51,7 +52,7 @@
   EXPECT_EQ(sizeof(output),
             ComputeDigest(DIGEST_SHA_1, "abc", 3, output, sizeof(output)));
   EXPECT_EQ("a9993e364706816aba3e25717850c26c9cd0d89d",
-            hex_encode(output, sizeof(output)));
+            hex_encode(absl::string_view(output, sizeof(output))));
   EXPECT_EQ(0U,
             ComputeDigest(DIGEST_SHA_1, "abc", 3, output, sizeof(output) - 1));
 }
@@ -99,7 +100,7 @@
             ComputeHmac(DIGEST_MD5, key.c_str(), key.size(), input.c_str(),
                         input.size(), output, sizeof(output)));
   EXPECT_EQ("9294727a3638bb1c13f48ef8158bfc9d",
-            hex_encode(output, sizeof(output)));
+            hex_encode(absl::string_view(output, sizeof(output))));
   EXPECT_EQ(0U, ComputeHmac(DIGEST_MD5, key.c_str(), key.size(), input.c_str(),
                             input.size(), output, sizeof(output) - 1));
 }
@@ -140,7 +141,7 @@
             ComputeHmac(DIGEST_SHA_1, key.c_str(), key.size(), input.c_str(),
                         input.size(), output, sizeof(output)));
   EXPECT_EQ("b617318655057264e28bc0b6fb378c8ef146be00",
-            hex_encode(output, sizeof(output)));
+            hex_encode(absl::string_view(output, sizeof(output))));
   EXPECT_EQ(0U,
             ComputeHmac(DIGEST_SHA_1, key.c_str(), key.size(), input.c_str(),
                         input.size(), output, sizeof(output) - 1));
diff --git a/rtc_base/ssl_fingerprint.cc b/rtc_base/ssl_fingerprint.cc
index a85b7a0..a43bb15 100644
--- a/rtc_base/ssl_fingerprint.cc
+++ b/rtc_base/ssl_fingerprint.cc
@@ -18,6 +18,7 @@
 
 #include "absl/algorithm/container.h"
 #include "absl/strings/string_view.h"
+#include "api/array_view.h"
 #include "rtc_base/logging.h"
 #include "rtc_base/message_digest.h"
 #include "rtc_base/rtc_certificate.h"
@@ -68,8 +69,8 @@
     return nullptr;
 
   char value[rtc::MessageDigest::kMaxSize];
-  size_t value_len = rtc::hex_decode_with_delimiter(
-      value, sizeof(value), fingerprint.data(), fingerprint.length(), ':');
+  size_t value_len =
+      rtc::hex_decode_with_delimiter(ArrayView<char>(value), fingerprint, ':');
   if (!value_len)
     return nullptr;
 
@@ -110,8 +111,8 @@
 }
 
 std::string SSLFingerprint::GetRfc4572Fingerprint() const {
-  std::string fingerprint =
-      rtc::hex_encode_with_delimiter(digest.data<char>(), digest.size(), ':');
+  std::string fingerprint = rtc::hex_encode_with_delimiter(
+      absl::string_view(digest.data<char>(), digest.size()), ':');
   absl::c_transform(fingerprint, fingerprint.begin(), ::toupper);
   return fingerprint;
 }
diff --git a/rtc_base/string_encode.cc b/rtc_base/string_encode.cc
index fa99c7a..136b853 100644
--- a/rtc_base/string_encode.cc
+++ b/rtc_base/string_encode.cc
@@ -13,6 +13,7 @@
 #include <cstdio>
 
 #include "absl/strings/string_view.h"
+#include "api/array_view.h"
 #include "rtc_base/arraysize.h"
 #include "rtc_base/checks.h"
 
@@ -52,16 +53,16 @@
 // hex_encode shows the hex representation of binary data in ascii, with
 // `delimiter` between bytes, or none if `delimiter` == 0.
 void hex_encode_with_delimiter(char* buffer,
-                               const char* csource,
-                               size_t srclen,
+                               absl::string_view source,
                                char delimiter) {
   RTC_DCHECK(buffer);
 
   // Init and check bounds.
   const unsigned char* bsource =
-      reinterpret_cast<const unsigned char*>(csource);
+      reinterpret_cast<const unsigned char*>(source.data());
   size_t srcpos = 0, bufpos = 0;
 
+  size_t srclen = source.length();
   while (srcpos < srclen) {
     unsigned char ch = bsource[srcpos++];
     buffer[bufpos] = hex_encode((ch >> 4) & 0xF);
@@ -79,42 +80,29 @@
 }  // namespace
 
 std::string hex_encode(absl::string_view str) {
-  return hex_encode(str.data(), str.size());
+  return hex_encode_with_delimiter(str, 0);
 }
 
-std::string hex_encode(const char* source, size_t srclen) {
-  return hex_encode_with_delimiter(source, srclen, 0);
-}
-
-std::string hex_encode_with_delimiter(const char* source,
-                                      size_t srclen,
+std::string hex_encode_with_delimiter(absl::string_view source,
                                       char delimiter) {
-  std::string s(hex_encode_output_length(srclen, delimiter), 0);
-  hex_encode_with_delimiter(&s[0], source, srclen, delimiter);
+  std::string s(hex_encode_output_length(source.length(), delimiter), 0);
+  hex_encode_with_delimiter(&s[0], source, delimiter);
   return s;
 }
 
-size_t hex_decode(char* cbuffer,
-                  size_t buflen,
-                  const char* source,
-                  size_t srclen) {
-  return hex_decode_with_delimiter(cbuffer, buflen, source, srclen, 0);
-}
-
-size_t hex_decode_with_delimiter(char* cbuffer,
-                                 size_t buflen,
-                                 const char* source,
-                                 size_t srclen,
+size_t hex_decode_with_delimiter(ArrayView<char> cbuffer,
+                                 absl::string_view source,
                                  char delimiter) {
-  RTC_DCHECK(cbuffer);  // TODO(kwiberg): estimate output size
-  if (buflen == 0)
+  if (cbuffer.empty())
     return 0;
 
   // Init and bounds check.
-  unsigned char* bbuffer = reinterpret_cast<unsigned char*>(cbuffer);
+  unsigned char* bbuffer = reinterpret_cast<unsigned char*>(cbuffer.data());
   size_t srcpos = 0, bufpos = 0;
+  size_t srclen = source.length();
+
   size_t needed = (delimiter) ? (srclen + 1) / 3 : srclen / 2;
-  if (buflen < needed)
+  if (cbuffer.size() < needed)
     return 0;
 
   while (srcpos < srclen) {
@@ -142,15 +130,16 @@
   return bufpos;
 }
 
-size_t hex_decode(char* buffer, size_t buflen, absl::string_view source) {
-  return hex_decode_with_delimiter(buffer, buflen, source, 0);
-}
 size_t hex_decode_with_delimiter(char* buffer,
                                  size_t buflen,
                                  absl::string_view source,
                                  char delimiter) {
-  return hex_decode_with_delimiter(buffer, buflen, source.data(),
-                                   source.length(), delimiter);
+  return hex_decode_with_delimiter(ArrayView<char>(buffer, buflen), source,
+                                   delimiter);
+}
+
+size_t hex_decode(ArrayView<char> buffer, absl::string_view source) {
+  return hex_decode_with_delimiter(buffer, source, 0);
 }
 
 size_t tokenize(absl::string_view source,
@@ -243,11 +232,11 @@
   return b ? "true" : "false";
 }
 
-std::string ToString(const char* const s) {
+std::string ToString(absl::string_view s) {
   return std::string(s);
 }
 
-std::string ToString(absl::string_view s) {
+std::string ToString(const char* s) {
   return std::string(s);
 }
 
@@ -321,7 +310,7 @@
   return std::string(&buf[0], len);
 }
 
-bool FromString(const std::string& s, bool* b) {
+bool FromString(absl::string_view s, bool* b) {
   if (s == "false") {
     *b = false;
     return true;
diff --git a/rtc_base/string_encode.h b/rtc_base/string_encode.h
index 87c5bc8..1901505 100644
--- a/rtc_base/string_encode.h
+++ b/rtc_base/string_encode.h
@@ -19,6 +19,7 @@
 
 #include "absl/strings/string_view.h"
 #include "absl/types/optional.h"
+#include "api/array_view.h"
 #include "rtc_base/checks.h"
 #include "rtc_base/string_to_number.h"
 
@@ -29,29 +30,18 @@
 //////////////////////////////////////////////////////////////////////
 
 std::string hex_encode(absl::string_view str);
-std::string hex_encode(const char* source, size_t srclen);
-std::string hex_encode_with_delimiter(const char* source,
-                                      size_t srclen,
-                                      char delimiter);
+std::string hex_encode_with_delimiter(absl::string_view source, char delimiter);
 
 // hex_decode converts ascii hex to binary.
-size_t hex_decode(char* buffer,
-                  size_t buflen,
-                  const char* source,
-                  size_t srclen);
+size_t hex_decode(ArrayView<char> buffer, absl::string_view source);
 
 // hex_decode, assuming that there is a delimiter between every byte
 // pair.
 // `delimiter` == 0 means no delimiter
 // If the buffer is too short or the data is invalid, we return 0.
-size_t hex_decode_with_delimiter(char* buffer,
-                                 size_t buflen,
-                                 const char* source,
-                                 size_t srclen,
+size_t hex_decode_with_delimiter(ArrayView<char> buffer,
+                                 absl::string_view source,
                                  char delimiter);
-
-// Helper functions for hex_decode.
-size_t hex_decode(char* buffer, size_t buflen, absl::string_view source);
 size_t hex_decode_with_delimiter(char* buffer,
                                  size_t buflen,
                                  absl::string_view source,
@@ -88,8 +78,10 @@
 // TODO(jonasolsson): Remove these when absl::StrCat becomes available.
 std::string ToString(bool b);
 
-std::string ToString(const char* s);
 std::string ToString(absl::string_view s);
+// The const char* overload is needed for correct overload resolution because of
+// the const void* version of ToString() below.
+std::string ToString(const char* s);
 
 std::string ToString(short s);
 std::string ToString(unsigned short s);
@@ -109,7 +101,7 @@
           typename std::enable_if<std::is_arithmetic<T>::value &&
                                       !std::is_same<T, bool>::value,
                                   int>::type = 0>
-static bool FromString(const std::string& s, T* t) {
+static bool FromString(absl::string_view s, T* t) {
   RTC_DCHECK(t);
   absl::optional<T> result = StringToNumber<T>(s);
 
@@ -119,10 +111,10 @@
   return result.has_value();
 }
 
-bool FromString(const std::string& s, bool* b);
+bool FromString(absl::string_view s, bool* b);
 
 template <typename T>
-static inline T FromString(const std::string& str) {
+static inline T FromString(absl::string_view str) {
   T val;
   FromString(str, &val);
   return val;
diff --git a/rtc_base/string_encode_unittest.cc b/rtc_base/string_encode_unittest.cc
index 3dd79c9..4afed3f 100644
--- a/rtc_base/string_encode_unittest.cc
+++ b/rtc_base/string_encode_unittest.cc
@@ -14,6 +14,7 @@
 
 #include <sstream>  // no-presubmit-check TODO(webrtc:8982)
 
+#include "api/array_view.h"
 #include "test/gtest.h"
 
 namespace rtc {
@@ -28,109 +29,106 @@
   }
 
   char data_[10];
+  absl::string_view data_view_{data_, sizeof(data_)};
   char decoded_[11];
   size_t dec_res_;
 };
 
 // Test that we can convert to/from hex with no delimiter.
 TEST_F(HexEncodeTest, TestWithNoDelimiter) {
-  std::string encoded = hex_encode(data_, sizeof(data_));
+  std::string encoded = hex_encode(data_view_);
   EXPECT_EQ("80818283848586878889", encoded);
-  dec_res_ =
-      hex_decode(decoded_, sizeof(decoded_), encoded.data(), encoded.size());
+  dec_res_ = hex_decode(ArrayView<char>(decoded_), encoded);
   ASSERT_EQ(sizeof(data_), dec_res_);
   ASSERT_EQ(0, memcmp(data_, decoded_, dec_res_));
 }
 
 // Test that we can convert to/from hex with a colon delimiter.
 TEST_F(HexEncodeTest, TestWithDelimiter) {
-  std::string encoded = hex_encode_with_delimiter(data_, sizeof(data_), ':');
+  std::string encoded = hex_encode_with_delimiter(data_view_, ':');
   EXPECT_EQ("80:81:82:83:84:85:86:87:88:89", encoded);
-  dec_res_ = hex_decode_with_delimiter(decoded_, sizeof(decoded_),
-                                       encoded.data(), encoded.size(), ':');
+  dec_res_ = hex_decode_with_delimiter(ArrayView<char>(decoded_), encoded, ':');
   ASSERT_EQ(sizeof(data_), dec_res_);
   ASSERT_EQ(0, memcmp(data_, decoded_, dec_res_));
 }
 
 // Test that encoding with one delimiter and decoding with another fails.
 TEST_F(HexEncodeTest, TestWithWrongDelimiter) {
-  std::string encoded = hex_encode_with_delimiter(data_, sizeof(data_), ':');
-  dec_res_ = hex_decode_with_delimiter(decoded_, sizeof(decoded_),
-                                       encoded.data(), encoded.size(), '/');
+  std::string encoded = hex_encode_with_delimiter(data_view_, ':');
+  dec_res_ = hex_decode_with_delimiter(ArrayView<char>(decoded_), encoded, '/');
   ASSERT_EQ(0U, dec_res_);
 }
 
 // Test that encoding without a delimiter and decoding with one fails.
 TEST_F(HexEncodeTest, TestExpectedDelimiter) {
-  std::string encoded = hex_encode(data_, sizeof(data_));
+  std::string encoded = hex_encode(data_view_);
   EXPECT_EQ(sizeof(data_) * 2, encoded.size());
-  dec_res_ = hex_decode_with_delimiter(decoded_, sizeof(decoded_),
-                                       encoded.data(), encoded.size(), ':');
+  dec_res_ = hex_decode_with_delimiter(ArrayView<char>(decoded_), encoded, ':');
   ASSERT_EQ(0U, dec_res_);
 }
 
 // Test that encoding with a delimiter and decoding without one fails.
 TEST_F(HexEncodeTest, TestExpectedNoDelimiter) {
-  std::string encoded = hex_encode_with_delimiter(data_, sizeof(data_), ':');
+  std::string encoded = hex_encode_with_delimiter(data_view_, ':');
   EXPECT_EQ(sizeof(data_) * 3 - 1, encoded.size());
-  dec_res_ =
-      hex_decode(decoded_, sizeof(decoded_), encoded.data(), encoded.size());
+  dec_res_ = hex_decode(ArrayView<char>(decoded_), encoded);
   ASSERT_EQ(0U, dec_res_);
 }
 
 // Test that we handle a zero-length buffer with no delimiter.
 TEST_F(HexEncodeTest, TestZeroLengthNoDelimiter) {
-  std::string encoded = hex_encode("", 0);
+  std::string encoded = hex_encode("");
   EXPECT_TRUE(encoded.empty());
-  dec_res_ =
-      hex_decode(decoded_, sizeof(decoded_), encoded.data(), encoded.size());
+  dec_res_ = hex_decode(ArrayView<char>(decoded_), encoded);
   ASSERT_EQ(0U, dec_res_);
 }
 
 // Test that we handle a zero-length buffer with a delimiter.
 TEST_F(HexEncodeTest, TestZeroLengthWithDelimiter) {
-  std::string encoded = hex_encode_with_delimiter("", 0, ':');
+  std::string encoded = hex_encode_with_delimiter("", ':');
   EXPECT_TRUE(encoded.empty());
-  dec_res_ = hex_decode_with_delimiter(decoded_, sizeof(decoded_),
-                                       encoded.data(), encoded.size(), ':');
+  dec_res_ = hex_decode_with_delimiter(ArrayView<char>(decoded_), encoded, ':');
   ASSERT_EQ(0U, dec_res_);
 }
 
 // Test that decoding into a too-small output buffer fails.
 TEST_F(HexEncodeTest, TestDecodeTooShort) {
-  dec_res_ = hex_decode_with_delimiter(decoded_, 4, "0123456789", 10, 0);
+  dec_res_ =
+      hex_decode_with_delimiter(ArrayView<char>(decoded_, 4), "0123456789", 0);
   ASSERT_EQ(0U, dec_res_);
   ASSERT_EQ(0x7f, decoded_[4]);
 }
 
 // Test that decoding non-hex data fails.
 TEST_F(HexEncodeTest, TestDecodeBogusData) {
-  dec_res_ =
-      hex_decode_with_delimiter(decoded_, sizeof(decoded_), "axyz", 4, 0);
+  dec_res_ = hex_decode_with_delimiter(ArrayView<char>(decoded_), "axyz", 0);
   ASSERT_EQ(0U, dec_res_);
 }
 
 // Test that decoding an odd number of hex characters fails.
 TEST_F(HexEncodeTest, TestDecodeOddHexDigits) {
-  dec_res_ = hex_decode_with_delimiter(decoded_, sizeof(decoded_), "012", 3, 0);
+  dec_res_ = hex_decode_with_delimiter(ArrayView<char>(decoded_), "012", 0);
   ASSERT_EQ(0U, dec_res_);
 }
 
 // Test that decoding a string with too many delimiters fails.
 TEST_F(HexEncodeTest, TestDecodeWithDelimiterTooManyDelimiters) {
-  dec_res_ = hex_decode_with_delimiter(decoded_, 4, "01::23::45::67", 14, ':');
+  dec_res_ = hex_decode_with_delimiter(ArrayView<char>(decoded_, 4),
+                                       "01::23::45::67", ':');
   ASSERT_EQ(0U, dec_res_);
 }
 
 // Test that decoding a string with a leading delimiter fails.
 TEST_F(HexEncodeTest, TestDecodeWithDelimiterLeadingDelimiter) {
-  dec_res_ = hex_decode_with_delimiter(decoded_, 4, ":01:23:45:67", 12, ':');
+  dec_res_ = hex_decode_with_delimiter(ArrayView<char>(decoded_, 4),
+                                       ":01:23:45:67", ':');
   ASSERT_EQ(0U, dec_res_);
 }
 
 // Test that decoding a string with a trailing delimiter fails.
 TEST_F(HexEncodeTest, TestDecodeWithDelimiterTrailingDelimiter) {
-  dec_res_ = hex_decode_with_delimiter(decoded_, 4, "01:23:45:67:", 12, ':');
+  dec_res_ = hex_decode_with_delimiter(ArrayView<char>(decoded_, 4),
+                                       "01:23:45:67:", ':');
   ASSERT_EQ(0U, dec_res_);
 }