24#include "field_codec_default_message.h"
27std::unordered_map<std::string, unsigned> dccl::v4::DefaultMessageCodec::MaxSize::oneofs_max_size;
33void dccl::v4::DefaultMessageCodec::any_encode(Bitset* bits,
const dccl::any& wire_value)
35 if (is_empty(wire_value))
37 *bits = Bitset(min_size());
41 *bits = traverse_const_message<Encoder, Bitset>(wire_value);
44 bits->push_front(
true);
48unsigned dccl::v4::DefaultMessageCodec::any_size(
const dccl::any& wire_value)
50 if (is_empty(wire_value))
56 unsigned size = traverse_const_message<Size, unsigned>(wire_value);
59 const unsigned presence_bit = 1;
67void dccl::v4::DefaultMessageCodec::any_decode(Bitset* bits, dccl::any* wire_value)
71 auto* msg = dccl::any_cast<google::protobuf::Message*>(*wire_value);
75 if (!bits->to_ulong())
77 *wire_value = dccl::any();
86 const google::protobuf::Descriptor* desc = msg->GetDescriptor();
87 const google::protobuf::Reflection* refl = msg->GetReflection();
90 std::vector<int> oneof_cases(desc->oneof_decl_count());
91 for (
auto i = 0, n = desc->oneof_decl_count(); part() != HEAD && i < n; ++i)
93 Bitset case_bits(bits);
94 case_bits.get_more_bits(
oneof_size(desc->oneof_decl(i)));
97 oneof_cases[i] =
static_cast<int>(case_bits.to_ulong()) - 1;
101 for (
int i = 0, n = desc->field_count(); i < n; ++i)
103 const google::protobuf::FieldDescriptor* field_desc = desc->field(i);
105 if (!check_field(field_desc))
108 std::shared_ptr<FieldCodecBase> codec = find(field_desc);
109 std::shared_ptr<internal::FromProtoCppTypeBase> helper =
110 manager().type_helper().find(field_desc);
112 if (field_desc->is_repeated())
114 std::vector<dccl::any> field_values;
115 if (field_desc->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE)
117 unsigned max_repeat =
118 field_desc->options().GetExtension(dccl::field).max_repeat();
119 for (
unsigned j = 0, m = max_repeat; j < m; ++j)
120 field_values.emplace_back(refl->AddMessage(msg, field_desc));
122 codec->field_decode_repeated(bits, &field_values, field_desc);
125 for (
int j = field_values.size(), m = max_repeat; j < m; ++j)
127 refl->RemoveLast(msg, field_desc);
133 codec->field_decode_repeated(bits, &field_values, field_desc);
134 for (
auto& field_value : field_values)
135 helper->add_value(field_desc, msg, field_value);
144 if (field_desc->index_in_oneof() !=
150 DynamicConditions& dc = dynamic_conditions(field_desc);
151 if (dc.has_omit_if())
154 dc.regenerate(this_message(), root_message());
159 dccl::any field_value;
160 if (field_desc->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE)
163 field_value = refl->MutableMessage(msg, field_desc);
164 codec->field_decode(bits, &field_value, field_desc);
165 if (is_empty(field_value))
166 refl->ClearField(msg, field_desc);
171 codec->field_decode(bits, &field_value, field_desc);
172 helper->set_value(field_desc, msg, field_value);
177 std::vector<const google::protobuf::FieldDescriptor*> set_fields;
178 refl->ListFields(*msg, &set_fields);
181 catch (dccl::bad_any_cast& e)
184 "Bad type given to traverse mutable, expecting google::protobuf::Message*, got " +
185 std::string(wire_value->type().name())));
189unsigned dccl::v4::DefaultMessageCodec::max_size()
192 traverse_descriptor<MaxSize>(&u);
196 const unsigned presence_bit = 1;
203unsigned dccl::v4::DefaultMessageCodec::min_size()
207 const unsigned presence_bit = 1;
213 traverse_descriptor<MinSize>(&u);
218void dccl::v4::DefaultMessageCodec::validate()
221 traverse_descriptor<Validate>(&b);
224std::string dccl::v4::DefaultMessageCodec::info()
226 std::stringstream ss;
227 traverse_descriptor<Info>(&ss);
231std::size_t dccl::v4::DefaultMessageCodec::hash()
233 std::size_t hash = 0;
234 traverse_descriptor<Hash>(&hash);
238bool dccl::v4::DefaultMessageCodec::check_field(
const google::protobuf::FieldDescriptor* field)
247 if (dccl_field_options.omit())
251 else if (message_data().current_part() == UNKNOWN)
253 if ((part() == HEAD && !dccl_field_options.in_head()) ||
254 (part() == BODY && dccl_field_options.in_head()))
259 if (part() == HEAD && !dccl_field_options.has_in_head() &&
260 field->cpp_type() == google::protobuf::FieldDescriptor::CPPTYPE_MESSAGE &&
268 else if (message_data().current_part() != part())
bool has_head_field(const google::protobuf::Descriptor *desc)
Recursively checks if a message descriptor has any fields with in_head = true.
int containing_oneof_index(const google::protobuf::FieldDescriptor *field_desc)
Returns the index of the containing oneof of the given field, or -1 if the field is not part of a one...
bool is_part_of_oneof(const google::protobuf::FieldDescriptor *field_desc)
Checks whether a given field is part to a oneof or not.
int oneof_size(const google::protobuf::OneofDescriptor *oneof_desc)
Returns the number of bits needed to represent the oneof cases (including the unset case).