6464#include " google/protobuf/map.h"
6565#include " google/protobuf/map_field.h"
6666#include " google/protobuf/message_lite.h"
67+ #include " google/protobuf/micro_string.h"
6768#include " google/protobuf/port.h"
6869#include " google/protobuf/repeated_field.h"
6970#include " google/protobuf/unknown_field_set.h"
@@ -79,6 +80,7 @@ using internal::ExtensionSet;
7980
8081
8182using internal::ArenaStringPtr;
83+ using internal::MicroString;
8284
8385// ===================================================================
8486// Some helper tables and functions...
@@ -242,6 +244,10 @@ int FieldSpaceUsed(const FieldDescriptor* field) {
242244 case FieldDescriptor::CppStringType::kCord :
243245 return sizeof (absl::Cord);
244246 case FieldDescriptor::CppStringType::kView :
247+ if (internal::EnableExperimentalMicroString ()) {
248+ return sizeof (MicroString);
249+ }
250+ [[fallthrough]];
245251 case FieldDescriptor::CppStringType::kString :
246252 return sizeof (ArenaStringPtr);
247253 }
@@ -253,6 +259,17 @@ int FieldSpaceUsed(const FieldDescriptor* field) {
253259 return 0 ;
254260}
255261
262+ uint32_t FieldFlags (const FieldDescriptor* field) {
263+ if (internal::EnableExperimentalMicroString () && //
264+ !field->is_repeated () && //
265+ !field->is_extension () && //
266+ field->cpp_type () == field->CPPTYPE_STRING && //
267+ field->cpp_string_type () == FieldDescriptor::CppStringType::kView ) {
268+ return internal::kMicroStringMask ;
269+ }
270+ return 0 ;
271+ }
272+
256273inline int DivideRoundingUp (int i, int j) { return (i + (j - 1 )) / j; }
257274
258275static const int kSafeAlignment = sizeof (uint64_t );
@@ -326,7 +343,11 @@ class DynamicMessage final : public Message {
326343 static void * NewImpl (const void * prototype, void * mem, Arena* arena);
327344 static void DestroyImpl (MessageLite& ptr);
328345
329- void * MutableRaw (int i);
346+ // If `T` is not `void`, it will mask bits off the offset via alignment.
347+ // Used to remove feature masks that are part of the reflection
348+ // implementation.
349+ template <typename T = void >
350+ T* MutableRaw (int i);
330351 void * MutableExtensionsRaw ();
331352 void * MutableWeakFieldMapRaw ();
332353 void * MutableOneofCaseRaw (int i);
@@ -416,8 +437,13 @@ DynamicMessage::DynamicMessage(DynamicMessageFactory::TypeInfo* type_info,
416437 SharedCtor (lock_factory);
417438}
418439
419- inline void * DynamicMessage::MutableRaw (int i) {
420- return OffsetToPointer (type_info_->offsets [i]);
440+ template <typename T>
441+ inline T* DynamicMessage::MutableRaw (int i) {
442+ uint32_t mask = ~uint32_t {};
443+ if constexpr (!std::is_void_v<T>) {
444+ mask = ~(uint32_t {alignof (T)} - 1 );
445+ }
446+ return reinterpret_cast <T*>(OffsetToPointer (type_info_->offsets [i] & mask));
421447}
422448inline void * DynamicMessage::MutableExtensionsRaw () {
423449 return OffsetToPointer (type_info_->extensions_offset );
@@ -513,6 +539,16 @@ void DynamicMessage::SharedCtor(bool lock_factory) {
513539 }
514540 break ;
515541 case FieldDescriptor::CppStringType::kView :
542+ if (internal::EnableExperimentalMicroString () &&
543+ !field->is_repeated ()) {
544+ auto * str = ::new (MutableRaw<MicroString>(i)) MicroString ();
545+ if (field->has_default_value ()) {
546+ // TODO: Use an unowned block instead.
547+ str->Set (field->default_value_string (), arena);
548+ }
549+ break ;
550+ }
551+ [[fallthrough]];
516552 case FieldDescriptor::CppStringType::kString :
517553 if (!field->is_repeated ()) {
518554 ArenaStringPtr* asp = new (field_ptr) ArenaStringPtr ();
@@ -600,6 +636,11 @@ DynamicMessage::~DynamicMessage() {
600636 delete *reinterpret_cast <absl::Cord**>(field_ptr);
601637 break ;
602638 case FieldDescriptor::CppStringType::kView :
639+ if (internal::EnableExperimentalMicroString ()) {
640+ reinterpret_cast <MicroString*>(field_ptr)->Destroy ();
641+ break ;
642+ }
643+ [[fallthrough]];
603644 case FieldDescriptor::CppStringType::kString : {
604645 reinterpret_cast <ArenaStringPtr*>(field_ptr)->Destroy ();
605646 break ;
@@ -661,6 +702,11 @@ DynamicMessage::~DynamicMessage() {
661702 reinterpret_cast <absl::Cord*>(field_ptr)->~Cord ();
662703 break ;
663704 case FieldDescriptor::CppStringType::kView :
705+ if (internal::EnableExperimentalMicroString ()) {
706+ MutableRaw<MicroString>(i)->Destroy ();
707+ break ;
708+ }
709+ [[fallthrough]];
664710 case FieldDescriptor::CppStringType::kString : {
665711 reinterpret_cast <ArenaStringPtr*>(field_ptr)->Destroy ();
666712 break ;
@@ -868,7 +914,7 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock(
868914 if (!InRealOneof (type->field (i))) {
869915 int field_size = FieldSpaceUsed (type->field (i));
870916 size = AlignTo (size, std::min (kSafeAlignment , field_size));
871- offsets[i] = size;
917+ offsets[i] = size | FieldFlags (type-> field (i)) ;
872918 size += field_size;
873919 }
874920 }
@@ -893,11 +939,11 @@ const Message* DynamicMessageFactory::GetPrototypeNoLock(
893939 for (int j = 0 ; j < type->real_oneof_decl (i)->field_count (); j++) {
894940 const FieldDescriptor* field = type->real_oneof_decl (i)->field (j);
895941 // oneof fields are not accessed through offsets, but we still have the
896- // entry from a legacy implementation. This should be removed at some
897- // point.
942+ // entry for each.
898943 // Mark the field to prevent unintentional access through reflection.
899944 // Don't use the top bit because that is for unused fields.
900- offsets[field->index ()] = internal::kInvalidFieldOffsetTag ;
945+ offsets[field->index ()] =
946+ internal::kInvalidFieldOffsetTag | FieldFlags (field);
901947 }
902948 }
903949
0 commit comments