24#include "field_codec_message_stack.h"
25#include "../field_codec.h"
32 for (
int i = 0, n = desc->field_count(); i < n; ++i)
34 const auto* field = desc->field(i);
35 const auto field_opts = field->options().GetExtension(dccl::field);
36 if (field_opts.in_head())
38 if (field->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE &&
39 !field_opts.has_in_head())
51void dccl::internal::MessageStack::push(
const google::protobuf::Descriptor* desc)
54 data_.desc.push_back(desc);
55 ++descriptors_pushed_;
58void dccl::internal::MessageStack::push(
const google::protobuf::FieldDescriptor* field)
60 data_.field.push_back(field);
64void dccl::internal::MessageStack::push(MessagePart part)
66 data_.parts.push_back(part);
70void dccl::internal::MessageStack::__pop_desc()
72 if (!data_.desc.empty())
73 data_.desc.pop_back();
74 --descriptors_pushed_;
77void dccl::internal::MessageStack::__pop_field()
79 if (!data_.field.empty())
80 data_.field.pop_back();
84void dccl::internal::MessageStack::__pop_parts()
86 if (!data_.parts.empty())
87 data_.parts.pop_back();
91void dccl::internal::MessageStack::__pop_messages()
93 if (!data_.messages.empty())
94 data_.messages.pop_back();
98dccl::internal::MessageStack::MessageStack(
const google::protobuf::Message* root_message,
99 MessageStackData& data,
100 const google::protobuf::FieldDescriptor* field)
101 : data_(data), descriptors_pushed_(0), fields_pushed_(0), parts_pushed_(0), messages_pushed_(0)
105 if (field->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE)
107 MessagePart part = UNKNOWN;
108 if (field->options().GetExtension(dccl::field).has_in_head())
111 part = field->options().GetExtension(dccl::field).in_head() ? HEAD : BODY;
116 part = current_part();
119 push(field->message_type());
121 push_message(root_message, field);
126void dccl::internal::MessageStack::update_index(
const google::protobuf::Message* root_message,
127 const google::protobuf::FieldDescriptor* field,
130 push_message(root_message, field, index);
133void dccl::internal::MessageStack::push_message(
const google::protobuf::Message* root_message,
134 const google::protobuf::FieldDescriptor* field,
137 if (data_.messages.empty() && root_message)
139 data_.messages.push_back({root_message,
nullptr});
143 if (field->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE)
146 if (!data_.messages.empty() && field == data_.messages.back().field &&
147 !data_.messages.empty())
149 data_.messages.pop_back();
154 if (data_.messages.size() &&
155 data_.messages.back().msg->GetDescriptor() == field->containing_type())
157 const auto* refl = data_.messages.back().msg->GetReflection();
158 if (field->is_repeated())
160 if (index >= 0 && index < refl->FieldSize(*data_.messages.back().msg, field))
162 data_.messages.push_back(
163 {&refl->GetRepeatedMessage(*data_.messages.back().msg, field, index),
170 data_.messages.push_back(
171 {&refl->GetMessage(*data_.messages.back().msg, field), field});
178dccl::internal::MessageStack::~MessageStack()
180 while (fields_pushed_ > 0) __pop_field();
181 while (descriptors_pushed_ > 0) __pop_desc();
182 while (parts_pushed_ > 0) __pop_parts();
183 while (messages_pushed_ > 0) __pop_messages();
bool has_head_field(const google::protobuf::Descriptor *desc)
Recursively checks if a message descriptor has any fields with in_head = true.