Skip to content

Commit

Permalink
Allow friendly use of Reflection::MutableRaw(), Reflection::MutableRa…
Browse files Browse the repository at this point in the history
…wNonOneof().

PiperOrigin-RevId: 591330894
  • Loading branch information
protobuf-github-bot authored and copybara-github committed Dec 15, 2023
1 parent 14dd8e9 commit 481c4fe
Show file tree
Hide file tree
Showing 2 changed files with 79 additions and 52 deletions.
60 changes: 25 additions & 35 deletions src/google/protobuf/generated_message_reflection.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2659,20 +2659,6 @@ const FieldDescriptor* Reflection::FindKnownExtensionByNumber(
// These simple template accessors obtain pointers (or references) to
// the given field.

template <class Type>
const Type& Reflection::GetRawNonOneof(const Message& message,
const FieldDescriptor* field) const {
const uint32_t field_offset = schema_.GetFieldOffsetNonOneof(field);
if (!schema_.IsSplit(field)) {
return GetConstRefAtOffset<Type>(message, field_offset);
}
const void* split = GetSplitField(&message);
if (SplitFieldHasExtraIndirection(field)) {
return **GetConstPointerAtOffset<Type*>(split, field_offset);
}
return *GetConstPointerAtOffset<Type>(split, field_offset);
}

void Reflection::PrepareSplitMessageForWrite(Message* message) const {
ABSL_DCHECK_NE(message, schema_.default_instance_);
void** split = MutableSplitField(message);
Expand Down Expand Up @@ -2705,38 +2691,42 @@ static Type* AllocIfDefault(const FieldDescriptor* field, Type*& ptr,
return ptr;
}

template <class Type>
Type* Reflection::MutableRawNonOneof(Message* message,
const FieldDescriptor* field) const {
void* Reflection::MutableRawSplitImpl(Message* message,
const FieldDescriptor* field) const {
ABSL_DCHECK(!schema_.InRealOneof(field)) << "Field = " << field->full_name();

const uint32_t field_offset = schema_.GetFieldOffsetNonOneof(field);
if (!schema_.IsSplit(field)) {
return GetPointerAtOffset<Type>(message, field_offset);
}
PrepareSplitMessageForWrite(message);
void** split = MutableSplitField(message);
if (SplitFieldHasExtraIndirection(field)) {
return AllocIfDefault(field,
*GetPointerAtOffset<Type*>(*split, field_offset),
*GetPointerAtOffset<void*>(*split, field_offset),
message->GetArena());
}
return GetPointerAtOffset<Type>(*split, field_offset);
return GetPointerAtOffset<void>(*split, field_offset);
}

template <typename Type>
Type* Reflection::MutableRaw(Message* message,
const FieldDescriptor* field) const {
const uint32_t field_offset = schema_.GetFieldOffset(field);
if (!schema_.IsSplit(field)) {
return GetPointerAtOffset<Type>(message, field_offset);
void* Reflection::MutableRawNonOneofImpl(Message* message,
const FieldDescriptor* field) const {
if (PROTOBUF_PREDICT_FALSE(schema_.IsSplit(field))) {
return MutableRawSplitImpl(message, field);
}
PrepareSplitMessageForWrite(message);
void** split = MutableSplitField(message);
if (SplitFieldHasExtraIndirection(field)) {
return AllocIfDefault(field,
*GetPointerAtOffset<Type*>(*split, field_offset),
message->GetArena());

const uint32_t field_offset = schema_.GetFieldOffsetNonOneof(field);
return GetPointerAtOffset<void>(message, field_offset);
}

void* Reflection::MutableRawImpl(Message* message,
const FieldDescriptor* field) const {
if (PROTOBUF_PREDICT_TRUE(!schema_.InRealOneof(field))) {
return MutableRawNonOneofImpl(message, field);
}
return GetPointerAtOffset<Type>(*split, field_offset);

// Oneof fields are not split.
ABSL_DCHECK(!schema_.IsSplit(field));

const uint32_t field_offset = schema_.GetFieldOffset(field);
return GetPointerAtOffset<void>(message, field_offset);
}

const uint32_t* Reflection::GetHasBits(const Message& message) const {
Expand Down
71 changes: 54 additions & 17 deletions src/google/protobuf/message.h
Original file line number Diff line number Diff line change
Expand Up @@ -1105,19 +1105,34 @@ class PROTOBUF_EXPORT Reflection final {
const T& GetRawNonOneof(const Message& message,
const FieldDescriptor* field) const;
template <class T>
T* MutableRawNonOneof(Message* message, const FieldDescriptor* field) const;

const T& GetRawSplit(const Message& message,
const FieldDescriptor* field) const;
template <typename Type>
const Type& GetRaw(const Message& message,
const FieldDescriptor* field) const;

void* MutableRawNonOneofImpl(Message* message,
const FieldDescriptor* field) const;
void* MutableRawSplitImpl(Message* message,
const FieldDescriptor* field) const;
void* MutableRawImpl(Message* message, const FieldDescriptor* field) const;

template <typename Type>
inline Type* MutableRaw(Message* message, const FieldDescriptor* field) const;
Type* MutableRawNonOneof(Message* message,
const FieldDescriptor* field) const {
return reinterpret_cast<Type*>(MutableRawNonOneofImpl(message, field));
}
template <typename Type>
Type* MutableRaw(Message* message, const FieldDescriptor* field) const {
return reinterpret_cast<Type*>(MutableRawImpl(message, field));
}

template <typename Type>
const Type& DefaultRaw(const FieldDescriptor* field) const;

const Message* GetDefaultMessageInstance(const FieldDescriptor* field) const;

inline const uint32_t* GetHasBits(const Message& message) const;
const uint32_t* GetHasBits(const Message& message) const;
inline uint32_t* MutableHasBits(Message* message) const;
uint32_t GetOneofCase(const Message& message,
const OneofDescriptor* oneof_descriptor) const;
Expand All @@ -1136,9 +1151,8 @@ class PROTOBUF_EXPORT Reflection final {

inline bool IsInlined(const FieldDescriptor* field) const;

inline bool HasBit(const Message& message,
const FieldDescriptor* field) const;
inline void SetBit(Message* message, const FieldDescriptor* field) const;
bool HasBit(const Message& message, const FieldDescriptor* field) const;
void SetBit(Message* message, const FieldDescriptor* field) const;
inline void ClearBit(Message* message, const FieldDescriptor* field) const;
inline void SwapBit(Message* message1, Message* message2,
const FieldDescriptor* field) const;
Expand Down Expand Up @@ -1188,8 +1202,7 @@ class PROTOBUF_EXPORT Reflection final {
const FieldDescriptor* field) const;
inline void SetOneofCase(Message* message,
const FieldDescriptor* field) const;
inline void ClearOneofField(Message* message,
const FieldDescriptor* field) const;
void ClearOneofField(Message* message, const FieldDescriptor* field) const;

template <typename Type>
inline const Type& GetField(const Message& message,
Expand Down Expand Up @@ -1546,21 +1559,45 @@ class RawMessageBase : public Message {
} // namespace internal

template <typename Type>
const Type& Reflection::GetRaw(const Message& message,
const FieldDescriptor* field) const {
ABSL_DCHECK(!schema_.InRealOneof(field) || HasOneofField(message, field))
<< "Field = " << field->full_name();
const uint32_t field_offset = schema_.GetFieldOffset(field);
if (!schema_.IsSplit(field)) {
return internal::GetConstRefAtOffset<Type>(message, field_offset);
}
const Type& Reflection::GetRawSplit(const Message& message,
const FieldDescriptor* field) const {
ABSL_DCHECK(!schema_.InRealOneof(field)) << "Field = " << field->full_name();

const void* split = GetSplitField(&message);
const uint32_t field_offset = schema_.GetFieldOffsetNonOneof(field);
if (internal::SplitFieldHasExtraIndirectionStatic<Type>(field)) {
return **internal::GetConstPointerAtOffset<Type*>(split, field_offset);
}
return *internal::GetConstPointerAtOffset<Type>(split, field_offset);
}

template <class Type>
const Type& Reflection::GetRawNonOneof(const Message& message,
const FieldDescriptor* field) const {
if (PROTOBUF_PREDICT_FALSE(schema_.IsSplit(field))) {
return GetRawSplit<Type>(message, field);
}
const uint32_t field_offset = schema_.GetFieldOffsetNonOneof(field);
return internal::GetConstRefAtOffset<Type>(message, field_offset);
}

template <typename Type>
const Type& Reflection::GetRaw(const Message& message,
const FieldDescriptor* field) const {
ABSL_DCHECK(!schema_.InRealOneof(field) || HasOneofField(message, field))
<< "Field = " << field->full_name();

if (PROTOBUF_PREDICT_TRUE(!schema_.InRealOneof(field))) {
return GetRawNonOneof<Type>(message, field);
}

// Oneof fields are not split.
ABSL_DCHECK(!schema_.IsSplit(field));

const uint32_t field_offset = schema_.GetFieldOffset(field);
return internal::GetConstRefAtOffset<Type>(message, field_offset);
}

template <typename T>
RepeatedFieldRef<T> Reflection::GetRepeatedFieldRef(
const Message& message, const FieldDescriptor* field) const {
Expand Down

0 comments on commit 481c4fe

Please sign in to comment.