24 #ifndef DCCLFIELDCODECDEFAULTMESSAGEV420210701H
25 #define DCCLFIELDCODECDEFAULTMESSAGEV420210701H
27 #include <unordered_map>
29 #include "../field_codec.h"
30 #include "../field_codec_manager.h"
33 #include "dccl/option_extensions.pb.h"
43 void any_encode(
Bitset* bits,
const dccl::any& wire_value)
override;
44 void any_decode(
Bitset* bits, dccl::any* wire_value)
override;
45 unsigned max_size()
override;
46 unsigned min_size()
override;
47 unsigned any_size(
const dccl::any& wire_value)
override;
49 std::shared_ptr<FieldCodecBase> find(
const google::protobuf::FieldDescriptor* field_desc)
51 return manager().
find(field_desc, this->codec_version(), has_codec_group(), codec_group());
56 void validate()
override;
57 std::string info()
override;
58 std::size_t hash()
override;
59 bool check_field(
const google::protobuf::FieldDescriptor* field);
63 static void repeated(std::shared_ptr<FieldCodecBase> codec,
unsigned* return_value,
64 const std::vector<dccl::any>& field_values,
65 const google::protobuf::FieldDescriptor* field_desc)
67 codec->field_size_repeated(return_value, field_values, field_desc);
70 static void single(std::shared_ptr<FieldCodecBase> codec,
unsigned* return_value,
71 const dccl::any& field_value,
72 const google::protobuf::FieldDescriptor* field_desc)
75 codec->field_size(return_value, field_value, field_desc);
80 if (!is_empty(field_value))
81 codec->field_size(return_value, field_value, field_desc);
85 static void oneof(
unsigned* return_value,
86 const google::protobuf::OneofDescriptor* oneof_desc,
96 static void repeated(std::shared_ptr<FieldCodecBase> codec,
Bitset* return_value,
97 const std::vector<dccl::any>& field_values,
98 const google::protobuf::FieldDescriptor* field_desc)
100 codec->field_encode_repeated(return_value, field_values, field_desc);
103 static void single(std::shared_ptr<FieldCodecBase> codec,
Bitset* return_value,
104 const dccl::any& field_value,
105 const google::protobuf::FieldDescriptor* field_desc)
108 codec->field_encode(return_value, field_value, field_desc);
113 if (!is_empty(field_value))
114 codec->field_encode(return_value, field_value, field_desc);
118 static void oneof(
Bitset* return_value,
const google::protobuf::OneofDescriptor* oneof_desc,
123 auto refl = msg.GetReflection();
124 if (refl->HasOneof(msg, oneof_desc))
125 for (
auto i = 0; i < oneof_desc->field_count(); ++i)
126 if (refl->HasField(msg, oneof_desc->field(i)))
133 return_value->
append(case_bits);
140 static std::unordered_map<std::string, unsigned> oneofs_max_size;
142 static void field(std::shared_ptr<FieldCodecBase> codec,
unsigned* return_value,
143 const google::protobuf::FieldDescriptor* field_desc)
146 codec->field_max_size(return_value, field_desc);
153 auto fld_max_size = 0u;
154 codec->field_max_size(&fld_max_size, field_desc);
156 auto parent_oneof_name = field_desc->containing_oneof()->full_name();
159 auto new_max_size = std::max(fld_max_size, oneofs_max_size[parent_oneof_name]);
163 *return_value += (new_max_size - oneofs_max_size[parent_oneof_name]);
164 oneofs_max_size[parent_oneof_name] = new_max_size;
168 static void oneof(
unsigned* return_value,
169 const google::protobuf::OneofDescriptor* oneof_desc,
175 *return_value += oneofs_max_size[oneof_desc->full_name()];
181 static void field(std::shared_ptr<FieldCodecBase> codec,
unsigned* return_value,
182 const google::protobuf::FieldDescriptor* field_desc)
188 if (dc.has_omit_if() || dc.has_required_if())
192 codec->field_min_size(return_value, field_desc);
195 static void oneof(
unsigned* return_value,
196 const google::protobuf::OneofDescriptor* oneof_desc,
206 static void field(std::shared_ptr<FieldCodecBase> codec,
bool* return_value,
207 const google::protobuf::FieldDescriptor* field_desc)
209 codec->field_validate(return_value, field_desc);
212 static void oneof(
bool*,
const google::protobuf::OneofDescriptor*,
220 static void field(std::shared_ptr<FieldCodecBase> codec, std::stringstream* return_value,
221 const google::protobuf::FieldDescriptor* field_desc)
224 codec->field_info(return_value, field_desc);
227 static void oneof(std::stringstream* return_value,
228 const google::protobuf::OneofDescriptor* oneof_desc,
237 field_codec->message_data());
238 std::stringstream ss;
239 int depth = msg_handler.count();
242 std::to_string(oneof_desc->index()) +
". " + oneof_desc->name() +
" [oneof]";
245 const int spaces = 8;
246 std::string indent = std::string(spaces * (depth),
' ');
247 const int full_width = 40;
249 int width = full_width -
name.size();
251 std::stringstream range;
252 unsigned max_sz = 0, min_sz = 0;
253 MaxSize::oneof(&max_sz, oneof_desc, field_codec);
254 MinSize::oneof(&min_sz, oneof_desc, field_codec);
255 range << min_sz <<
"-" << max_sz;
257 ss << indent <<
name << std::setfill(
'.') << std::setw(std::max(1, width))
260 *return_value << ss.str() <<
" {\n";
262 for (
auto i = 0; i < oneof_desc->field_count(); ++i)
264 auto codec = field_codec->manager().
find(
265 oneof_desc->field(i), field_codec->codec_version(),
266 field_codec->has_codec_group(), field_codec->codec_group());
267 codec->field_info(return_value, oneof_desc->field(i));
270 *return_value << indent <<
"}\n";
276 static void field(std::shared_ptr<FieldCodecBase> codec, std::size_t* return_value,
277 const google::protobuf::FieldDescriptor* field_desc)
279 codec->field_hash(return_value, field_desc);
282 static void oneof(std::size_t* return_value,
283 const google::protobuf::OneofDescriptor* oneof_desc,
290 hash_combine(*return_value, oneof_desc->DebugString());
294 template <
typename Action,
typename ReturnType>
295 void traverse_descriptor(ReturnType* return_value)
300 for (
auto i = 0, n = desc->oneof_decl_count();
part() != HEAD && i < n; ++i)
301 Action::oneof(return_value, desc->oneof_decl(i),
this);
304 for (
int i = 0, n = desc->field_count(); i < n; ++i)
306 const google::protobuf::FieldDescriptor* field_desc = desc->field(i);
308 if (!check_field(field_desc))
311 Action::field(find(field_desc), return_value, field_desc);
315 template <
typename Action,
typename ReturnType>
316 ReturnType traverse_const_message(
const dccl::any& wire_value)
320 ReturnType return_value = ReturnType();
322 const auto* msg = dccl::any_cast<const google::protobuf::Message*>(wire_value);
323 const google::protobuf::Descriptor* desc = msg->GetDescriptor();
324 const google::protobuf::Reflection* refl = msg->GetReflection();
327 for (
auto i = 0, n = desc->oneof_decl_count();
part() != HEAD && i < n; ++i)
328 Action::oneof(&return_value, desc->oneof_decl(i), *msg);
331 for (
int i = 0, n = desc->field_count(); i < n; ++i)
333 const google::protobuf::FieldDescriptor* field_desc = desc->field(i);
335 if (!check_field(field_desc))
338 std::shared_ptr<FieldCodecBase> codec = find(field_desc);
339 std::shared_ptr<internal::FromProtoCppTypeBase> helper =
340 manager().type_helper().find(field_desc);
342 if (field_desc->is_repeated())
344 std::vector<dccl::any> field_values;
345 for (
int j = 0, m = refl->FieldSize(*msg, field_desc); j < m; ++j)
346 field_values.push_back(helper->get_repeated_value(field_desc, *msg, j));
348 Action::repeated(codec, &return_value, field_values, field_desc);
354 if (dc.has_omit_if())
357 dc.regenerate(this_message(), root_message());
362 Action::single(codec, &return_value, helper->get_value(field_desc, *msg),
368 catch (dccl::bad_any_cast& e)
370 throw(
Exception(
"Bad type given to traverse const, expecting const "
371 "google::protobuf::Message*, got " +
372 std::string(wire_value.type().name())));