Take std::to_array<>() equivalent from chromium base.

to_array<>() helps clean up std::array<> initialization, however it
can not be used until C++20, and we are holding the line at C++17.

The code differs from base in that we need to suppress both
UNSAFE_BUFFER usage and narowing via a static_cast<> to run
under stricter compiler flags.

-- Demonstrate its use in one place.

Change-Id: Iddaf1fa936f107562049a54733c657c2184a872b
Reviewed-on: https://pdfium-review.googlesource.com/c/pdfium/+/119512
Reviewed-by: Lei Zhang <thestig@chromium.org>
Reviewed-by: Thomas Sepez <tsepez@google.com>
Commit-Queue: Tom Sepez <tsepez@chromium.org>
diff --git a/core/fpdfdoc/cpdf_dest.cpp b/core/fpdfdoc/cpdf_dest.cpp
index e89ea7a..8026a75 100644
--- a/core/fpdfdoc/cpdf_dest.cpp
+++ b/core/fpdfdoc/cpdf_dest.cpp
@@ -15,17 +15,18 @@
 #include "core/fpdfapi/parser/cpdf_name.h"
 #include "core/fpdfapi/parser/cpdf_number.h"
 #include "core/fpdfdoc/cpdf_nametree.h"
+#include "core/fxcrt/stl_util.h"
 
 namespace {
 
 // These arrays are indexed by the PDFDEST_VIEW_* constants.
 
-constexpr std::array<const char*, 9> kZoomModes = {{"Unknown", "XYZ", "Fit",
-                                                    "FitH", "FitV", "FitR",
-                                                    "FitB", "FitBH", "FitBV"}};
+constexpr auto kZoomModes =
+    fxcrt::ToArray<const char*>({"Unknown", "XYZ", "Fit", "FitH", "FitV",
+                                 "FitR", "FitB", "FitBH", "FitBV"});
 
-constexpr std::array<uint8_t, 9> kZoomModeMaxParamCount = {
-    {0, 3, 0, 1, 1, 4, 0, 1, 1}};
+constexpr auto kZoomModeMaxParamCount =
+    fxcrt::ToArray<const uint8_t>({0, 3, 0, 1, 1, 4, 0, 1, 1});
 
 }  // namespace
 
diff --git a/core/fxcrt/stl_util.h b/core/fxcrt/stl_util.h
index 8fe1639..363f36b 100644
--- a/core/fxcrt/stl_util.h
+++ b/core/fxcrt/stl_util.h
@@ -8,6 +8,7 @@
 #include <algorithm>
 #include <memory>
 
+#include "core/fxcrt/compiler_specific.h"
 #include "core/fxcrt/numerics/safe_conversions.h"
 
 namespace fxcrt {
@@ -47,6 +48,29 @@
   std::fill(std::begin(container), std::end(container), value);
 }
 
+// ToArray<>() implementation as taken from chromium /base. Replace with
+// std::to_array<>() when C++20 becomes available.
+//
+// Helper inspired by C++20's std::to_array to convert a C-style array to a
+// std::array. As opposed to the C++20 version this implementation does not
+// provide an overload for rvalues and does not strip cv qualifers from the
+// returned std::array::value_type. The returned value_type needs to be
+// specified explicitly, allowing the construction of std::arrays with const
+// elements.
+//
+// Reference: https://en.cppreference.com/w/cpp/container/array/to_array
+template <typename U, typename T, size_t N, size_t... I>
+constexpr std::array<U, N> ToArrayImpl(const T (&data)[N],
+                                       std::index_sequence<I...>) {
+  // SAFETY: compiler-deduced size `N`.
+  return UNSAFE_BUFFERS({{static_cast<U>(data[I])...}});
+}
+
+template <typename U, typename T, size_t N>
+constexpr std::array<U, N> ToArray(const T (&data)[N]) {
+  return ToArrayImpl<U>(data, std::make_index_sequence<N>());
+}
+
 }  // namespace fxcrt
 
 #endif  // CORE_FXCRT_STL_UTIL_H_