Faster copy from inline Cords to inline Strings

PiperOrigin-RevId: 714061397
Change-Id: Iad41d5033d7a0f87a54cd97d636aa450e0d6b8b4
diff --git a/absl/strings/BUILD.bazel b/absl/strings/BUILD.bazel
index dd2cf05..81b8d89 100644
--- a/absl/strings/BUILD.bazel
+++ b/absl/strings/BUILD.bazel
@@ -441,15 +441,13 @@
         "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:endian",
+        "//absl/base:nullability",
         "//absl/base:raw_logging_internal",
-        "//absl/base:throw_delegate",
         "//absl/container:compressed_tuple",
         "//absl/container:container_memory",
         "//absl/container:inlined_vector",
-        "//absl/container:layout",
         "//absl/crc:crc_cord_state",
         "//absl/functional:function_ref",
-        "//absl/meta:type_traits",
         "//absl/types:span",
     ],
 )
@@ -580,14 +578,11 @@
     linkopts = ABSL_DEFAULT_LINKOPTS,
     deps = [
         ":cord_internal",
-        ":cordz_functions",
         ":cordz_info",
-        ":cordz_statistics",
         ":cordz_update_scope",
         ":cordz_update_tracker",
         ":internal",
         ":strings",
-        "//absl/base",
         "//absl/base:config",
         "//absl/base:core_headers",
         "//absl/base:endian",
diff --git a/absl/strings/cord.h b/absl/strings/cord.h
index 1d8fcd3..1f8aafb 100644
--- a/absl/strings/cord.h
+++ b/absl/strings/cord.h
@@ -61,6 +61,7 @@
 #define ABSL_STRINGS_CORD_H_
 
 #include <algorithm>
+#include <cassert>
 #include <cstddef>
 #include <cstdint>
 #include <cstring>
@@ -68,16 +69,14 @@
 #include <iterator>
 #include <string>
 #include <type_traits>
+#include <utility>
 
 #include "absl/base/attributes.h"
 #include "absl/base/config.h"
 #include "absl/base/internal/endian.h"
-#include "absl/base/internal/per_thread_tls.h"
 #include "absl/base/macros.h"
 #include "absl/base/nullability.h"
 #include "absl/base/optimization.h"
-#include "absl/base/port.h"
-#include "absl/container/inlined_vector.h"
 #include "absl/crc/internal/crc_cord_state.h"
 #include "absl/functional/function_ref.h"
 #include "absl/meta/type_traits.h"
@@ -88,12 +87,10 @@
 #include "absl/strings/internal/cord_rep_btree.h"
 #include "absl/strings/internal/cord_rep_btree_reader.h"
 #include "absl/strings/internal/cord_rep_crc.h"
-#include "absl/strings/internal/cordz_functions.h"
+#include "absl/strings/internal/cord_rep_flat.h"
 #include "absl/strings/internal/cordz_info.h"
-#include "absl/strings/internal/cordz_statistics.h"
 #include "absl/strings/internal/cordz_update_scope.h"
 #include "absl/strings/internal/cordz_update_tracker.h"
-#include "absl/strings/internal/resize_uninitialized.h"
 #include "absl/strings/internal/string_constant.h"
 #include "absl/strings/string_view.h"
 #include "absl/types/compare.h"
@@ -978,15 +975,9 @@
 
     bool IsSame(const InlineRep& other) const { return data_ == other.data_; }
 
+    // Copies the inline contents into `dst`. Assumes the cord is not empty.
     void CopyTo(absl::Nonnull<std::string*> dst) const {
-      // memcpy is much faster when operating on a known size. On most supported
-      // platforms, the small string optimization is large enough that resizing
-      // to 15 bytes does not cause a memory allocation.
-      absl::strings_internal::STLStringResizeUninitialized(dst, kMaxInline);
-      data_.copy_max_inline_to(&(*dst)[0]);
-      // erase is faster than resize because the logic for memory allocation is
-      // not needed.
-      dst->erase(inline_size());
+      data_.CopyInlineToString(dst);
     }
 
     // Copies the inline contents into `dst`. Assumes the cord is not empty.
diff --git a/absl/strings/internal/cord_internal.h b/absl/strings/internal/cord_internal.h
index d33b09e..b68ec2b 100644
--- a/absl/strings/internal/cord_internal.h
+++ b/absl/strings/internal/cord_internal.h
@@ -19,16 +19,18 @@
 #include <cassert>
 #include <cstddef>
 #include <cstdint>
-#include <type_traits>
+#include <cstring>
+#include <string>
 
 #include "absl/base/attributes.h"
 #include "absl/base/config.h"
 #include "absl/base/internal/endian.h"
 #include "absl/base/internal/invoke.h"
+#include "absl/base/macros.h"
+#include "absl/base/nullability.h"
 #include "absl/base/optimization.h"
 #include "absl/container/internal/compressed_tuple.h"
 #include "absl/container/internal/container_memory.h"
-#include "absl/meta/type_traits.h"
 #include "absl/strings/string_view.h"
 
 // We can only add poisoning if we can detect consteval executions.
@@ -635,6 +637,19 @@
     poison();
   }
 
+  void CopyInlineToString(absl::Nonnull<std::string*> dst) const {
+    assert(!is_tree());
+    // As Cord can store only 15 bytes it is smaller than std::string's
+    // small string optimization buffer size. Therefore we will always trigger
+    // the fast assign short path.
+    //
+    // Copying with a size equal to the maximum allows more efficient, wider
+    // stores to be used and no branching.
+    dst->assign(rep_.SanitizerSafeCopy().as_chars(), kMaxInline);
+    // After the copy we then change the size and put in a 0 byte.
+    dst->erase(inline_size());
+  }
+
   void copy_max_inline_to(char* dst) const {
     assert(!is_tree());
     memcpy(dst, rep_.SanitizerSafeCopy().as_chars(), kMaxInline);