@@ -56,6 +56,51 @@ T ConsumeAndDestroy(T& object) {
5656
5757} // namespace
5858
59+ ByteString ByteString::Concat (const ByteString& lhs, const ByteString& rhs,
60+ absl::Nonnull<google::protobuf::Arena*> arena) {
61+ ABSL_DCHECK (arena != nullptr );
62+
63+ if (lhs.empty ()) {
64+ return rhs;
65+ }
66+ if (rhs.empty ()) {
67+ return lhs;
68+ }
69+
70+ if (lhs.GetKind () == ByteStringKind::kLarge ||
71+ rhs.GetKind () == ByteStringKind::kLarge ) {
72+ // If either the left or right are absl::Cord, use absl::Cord.
73+ absl::Cord result;
74+ result.Append (lhs.ToCord ());
75+ result.Append (rhs.ToCord ());
76+ return ByteString (std::move (result));
77+ }
78+
79+ const size_t lhs_size = lhs.size ();
80+ const size_t rhs_size = rhs.size ();
81+ const size_t result_size = lhs_size + rhs_size;
82+ ByteString result;
83+ if (result_size <= kSmallByteStringCapacity ) {
84+ // If the resulting string fits in inline storage, do it.
85+ result.rep_ .small .size = result_size;
86+ result.rep_ .small .arena = arena;
87+ lhs.CopyToArray (result.rep_ .small .data );
88+ rhs.CopyToArray (result.rep_ .small .data + lhs_size);
89+ } else {
90+ // Otherwise allocate on the arena.
91+ char * result_data =
92+ reinterpret_cast <char *>(arena->AllocateAligned (result_size));
93+ lhs.CopyToArray (result_data);
94+ rhs.CopyToArray (result_data + lhs_size);
95+ result.rep_ .medium .data = result_data;
96+ result.rep_ .medium .size = result_size;
97+ result.rep_ .medium .owner =
98+ reinterpret_cast <uintptr_t >(arena) | kMetadataOwnerArenaBit ;
99+ result.rep_ .medium .kind = ByteStringKind::kMedium ;
100+ }
101+ return result;
102+ }
103+
59104ByteString::ByteString (Allocator<> allocator, absl::string_view string) {
60105 ABSL_DCHECK_LE (string.size (), max_size ());
61106 auto * arena = allocator.arena ();
@@ -249,6 +294,25 @@ void ByteString::RemoveSuffix(size_t n) {
249294 }
250295}
251296
297+ void ByteString::CopyToArray (absl::Nonnull<char *> out) const {
298+ ABSL_DCHECK (out != nullptr );
299+
300+ switch (GetKind ()) {
301+ case ByteStringKind::kSmall : {
302+ absl::string_view small = GetSmall ();
303+ std::memcpy (out, small.data (), small.size ());
304+ } break ;
305+ case ByteStringKind::kMedium : {
306+ absl::string_view medium = GetMedium ();
307+ std::memcpy (out, medium.data (), medium.size ());
308+ } break ;
309+ case ByteStringKind::kLarge : {
310+ const absl::Cord& large = GetLarge ();
311+ (CopyCordToArray)(large, out);
312+ } break ;
313+ }
314+ }
315+
252316std::string ByteString::ToString () const {
253317 switch (GetKind ()) {
254318 case ByteStringKind::kSmall :
0 commit comments