24 #include "field_codec.h"
26 #include "exception.h"
29 using namespace dccl::logger;
34 dccl::FieldCodecBase::FieldCodecBase() =
default;
37 MessagePart part,
bool strict)
39 BaseRAII scoped_globals(
this, part, &field_value, strict);
44 manager().type_helper().find(field_value.GetDescriptor())->get_value(field_value),
49 const google::protobuf::FieldDescriptor* field)
54 dlog.
is(DEBUG2, ENCODE) && dlog <<
"Starting encode for field: " << field->DebugString()
58 field_pre_encode(&wire_value, field_value);
61 any_encode(&new_bits, wire_value);
62 disp_size(field, new_bits, msg_handler.field_size());
66 dlog.
is(DEBUG2, ENCODE) && dlog <<
"... produced these " << new_bits.size()
67 <<
" bits: " << new_bits << std::endl;
71 const std::vector<dccl::any>& field_values,
72 const google::protobuf::FieldDescriptor* field)
76 std::vector<dccl::any> wire_values;
77 field_pre_encode_repeated(&wire_values, field_values);
80 any_encode_repeated(&new_bits, wire_values);
81 disp_size(field, new_bits, msg_handler.field_size(), wire_values.size());
88 BaseRAII scoped_globals(
this, part, &msg);
92 field_size(bit_size, &msg,
nullptr);
96 const google::protobuf::FieldDescriptor* field)
100 dccl::any wire_value;
101 field_pre_encode(&wire_value, field_value);
103 *bit_size += any_size(wire_value);
107 const std::vector<dccl::any>& field_values,
108 const google::protobuf::FieldDescriptor* field)
112 std::vector<dccl::any> wire_values;
113 field_pre_encode_repeated(&wire_values, field_values);
115 *bit_size += any_size_repeated(wire_values);
121 BaseRAII scoped_globals(
this, part, field_value);
122 dccl::any value(field_value);
123 field_decode(bits, &value,
nullptr);
127 const google::protobuf::FieldDescriptor* field)
132 throw(
Exception(
"Decode called with NULL dccl::any"));
134 throw(
Exception(
"Decode called with NULL Bitset"));
137 dlog.
is(DEBUG2, DECODE) && dlog <<
"Starting decode for field: " << field->DebugString()
141 dlog.
is(DEBUG3, DECODE) && dlog <<
"Message thus far is: " << root_message()->DebugString()
146 unsigned bits_to_transfer = 0;
147 field_min_size(&bits_to_transfer, field);
151 dlog.
is(DEBUG2, DECODE) && dlog <<
"... using these bits: " << these_bits << std::endl;
153 dccl::any wire_value = *field_value;
155 any_decode(&these_bits, &wire_value);
157 field_post_decode(wire_value, field_value);
161 const google::protobuf::FieldDescriptor* field)
166 throw(
Exception(
"Decode called with NULL field_values"));
168 throw(
Exception(
"Decode called with NULL Bitset"));
171 dlog.
is(DEBUG2, DECODE) &&
172 dlog <<
"Starting repeated decode for field: " << field->DebugString() << std::endl;
176 unsigned bits_to_transfer = 0;
177 field_min_size(&bits_to_transfer, field);
180 dlog.
is(DEBUG2, DECODE) && dlog <<
"using these " << these_bits.size()
181 <<
" bits: " << these_bits << std::endl;
183 std::vector<dccl::any> wire_values = *field_values;
184 any_decode_repeated(&these_bits, &wire_values);
186 field_values->clear();
187 field_post_decode_repeated(wire_values, field_values);
191 const google::protobuf::Descriptor* desc, MessagePart part)
193 BaseRAII scoped_globals(
this, part, desc);
198 msg_handler.push(desc);
200 throw(
Exception(
"Max Size called with NULL Descriptor"));
202 field_max_size(bit_size,
static_cast<google::protobuf::FieldDescriptor*
>(
nullptr));
206 const google::protobuf::FieldDescriptor* field)
211 *bit_size += this_field()->is_repeated() ? max_size_repeated() : max_size();
213 *bit_size += max_size();
217 const google::protobuf::Descriptor* desc, MessagePart part)
219 BaseRAII scoped_globals(
this, part, desc);
225 msg_handler.push(desc);
227 throw(
Exception(
"Min Size called with NULL Descriptor"));
229 field_min_size(bit_size,
static_cast<google::protobuf::FieldDescriptor*
>(
nullptr));
233 const google::protobuf::FieldDescriptor* field)
239 *bit_size += this_field()->is_repeated() ? min_size_repeated() : min_size();
241 *bit_size += min_size();
246 BaseRAII scoped_globals(
this, part, desc);
250 msg_handler.push(desc);
252 throw(
Exception(
"Validate called with NULL Descriptor"));
255 field_validate(&b,
static_cast<google::protobuf::FieldDescriptor*
>(
nullptr));
259 const google::protobuf::FieldDescriptor* field)
263 if (field && dccl_field_options().in_head() && variable_size())
264 throw(
Exception(
"Variable size codec used in header - header fields must be encoded with "
265 "fixed size codec."));
269 "Oneof field used in header - oneof fields cannot be encoded in the header."));
277 BaseRAII scoped_globals(
this, part, desc);
281 msg_handler.push(desc);
283 throw(
Exception(
"info called with NULL Descriptor"));
285 field_info(os,
static_cast<google::protobuf::FieldDescriptor*
>(
nullptr));
289 const google::protobuf::FieldDescriptor* field)
293 std::stringstream ss;
294 int depth = msg_handler.count();
297 ((this_field()) ? std::to_string(this_field()->number()) +
". " + this_field()->name()
298 : this_descriptor()->full_name());
299 if (this_field() && this_field()->is_repeated())
301 (dccl_field_options().has_min_repeat()
302 ? (std::to_string(dccl_field_options().min_repeat()) +
"-")
304 std::to_string(dccl_field_options().max_repeat()) +
"]";
306 if (!this_field() || this_field()->type() == google::protobuf::FieldDescriptor::TYPE_MESSAGE)
309 const int spaces = 8;
311 std::string(spaces * (depth) + spaces / 2 * (field &&
is_part_of_oneof(field)),
314 const int full_width = 40;
316 bool is_zero_size =
false;
318 std::stringstream range;
321 unsigned max_sz = 0, min_sz = 0;
322 field_max_size(&max_sz, field);
323 field_min_size(&min_sz, field);
326 range << min_sz <<
"-" << max_sz;
331 field_max_size(&sz, field);
337 int width = this_field() ? full_width - name.size() : full_width - name.size() + spaces;
338 ss << indent << name << std::setfill(
'.') << std::setw(std::max(1, width)) << range.str()
340 << (this_field() ? manager().find(this_field(), codec_version(), has_codec_group(), codec_group())->name()
341 : manager().find(manager().codec_data().root_descriptor_)->name())
345 *os << ss.str() <<
"\n";
347 std::string specific_info = info();
348 if (!specific_info.empty())
349 *os << specific_info;
355 BaseRAII scoped_globals(
this, part, desc);
359 msg_handler.push(desc);
361 throw(
Exception(
"Hash called with NULL Descriptor"));
363 field_hash(hash,
static_cast<google::protobuf::FieldDescriptor*
>(
nullptr));
367 const google::protobuf::FieldDescriptor* field)
371 if (field && dccl_field_options().in_head() && variable_size())
372 throw(
Exception(
"Variable size codec used in header - header fields must be encoded with "
373 "fixed size codec."));
377 "Oneof field used in header - oneof fields cannot be encoded in the header."));
381 google::protobuf::FieldDescriptorProto field_to_hash;
382 this_field()->CopyTo(&field_to_hash);
385 field_to_hash.clear_name();
387 field_to_hash.clear_options();
388 field_to_hash.clear_type_name();
389 field_to_hash.clear_default_value();
393 hash_combine(*hash_value, field_to_hash.DebugString());
394 hash_combine(*hash_value, dccl_opts.DebugString());
400 dccl_opts.clear_max_bytes();
402 hash_combine(*hash_value, dccl_opts.DebugString());
405 hash_combine(*hash_value, hash());
408 std::string dccl::FieldCodecBase::codec_group(
const google::protobuf::Descriptor* desc)
410 if (desc->options().GetExtension(dccl::msg).has_codec_group())
411 return desc->options().GetExtension(dccl::msg).codec_group();
413 return Codec::default_codec_name(desc->options().GetExtension(dccl::msg).codec_version());
422 void dccl::FieldCodecBase::any_encode_repeated(
dccl::Bitset* bits,
423 const std::vector<dccl::any>& wire_values)
427 unsigned wire_vector_size = dccl_field_options().max_repeat();
429 if (wire_values.size() > wire_vector_size && strict())
433 this->this_field(), this->this_descriptor()));
435 if (wire_values.size() < dccl_field_options().min_repeat() && strict())
437 std::string(
"Repeated size is less than min_repeat for field: ") +
439 this->this_field(), this->this_descriptor()));
442 if (codec_version() > 2)
444 wire_vector_size = std::min(
static_cast<int>(dccl_field_options().max_repeat()),
445 static_cast<int>(wire_values.size()));
447 wire_vector_size = std::max(
static_cast<int>(dccl_field_options().min_repeat()),
448 static_cast<int>(wire_vector_size));
450 Bitset size_bits(repeated_vector_field_size(dccl_field_options().min_repeat(),
451 dccl_field_options().max_repeat()),
452 wire_vector_size - dccl_field_options().min_repeat());
455 dlog.
is(DEBUG2, ENCODE) && dlog <<
"repeated size field ... produced these "
456 << size_bits.size() <<
" bits: " << size_bits << std::endl;
459 internal::MessageStack msg_handler(root_message(), message_data(), this->this_field());
460 for (
unsigned i = 0, n = wire_vector_size; i < n; ++i)
462 msg_handler.update_index(root_message(), this->this_field(), i);
464 DynamicConditions& dc = this->dynamic_conditions(this->this_field());
465 dc.set_repeated_index(i);
466 if (dc.has_omit_if())
468 dc.regenerate(this_message(), root_message(), i);
474 if (i < wire_values.size())
475 any_encode(&new_bits, wire_values[i]);
477 any_encode(&new_bits, dccl::any());
482 void dccl::FieldCodecBase::any_decode_repeated(Bitset* repeated_bits,
483 std::vector<dccl::any>* wire_values)
485 unsigned wire_vector_size = dccl_field_options().max_repeat();
486 if (codec_version() > 2)
488 Bitset size_bits(repeated_bits);
489 size_bits.get_more_bits(repeated_vector_field_size(dccl_field_options().min_repeat(),
490 dccl_field_options().max_repeat()));
492 wire_vector_size = size_bits.to_ulong() + dccl_field_options().min_repeat();
495 wire_values->resize(wire_vector_size);
497 internal::MessageStack msg_handler(root_message(), message_data(), this->this_field());
498 for (
unsigned i = 0, n = wire_vector_size; i < n; ++i)
500 msg_handler.update_index(root_message(), this->this_field(), i);
502 DynamicConditions& dc = this->dynamic_conditions(this->this_field());
503 dc.set_repeated_index(i);
504 if (dc.has_omit_if())
506 dc.regenerate(this_message(), root_message(), i);
511 Bitset these_bits(repeated_bits);
512 these_bits.get_more_bits(min_size());
513 any_decode(&these_bits, &(*wire_values)[i]);
517 unsigned dccl::FieldCodecBase::any_size_repeated(
const std::vector<dccl::any>& wire_values)
520 unsigned wire_vector_size = dccl_field_options().max_repeat();
522 if (codec_version() > 2)
524 wire_vector_size = std::min(
static_cast<int>(dccl_field_options().max_repeat()),
525 static_cast<int>(wire_values.size()));
526 out += repeated_vector_field_size(dccl_field_options().min_repeat(),
527 dccl_field_options().max_repeat());
530 internal::MessageStack msg_handler(root_message(), message_data(), this->this_field());
531 for (
unsigned i = 0, n = wire_vector_size; i < n; ++i)
533 msg_handler.update_index(root_message(), this->this_field(), i);
534 DynamicConditions& dc = this->dynamic_conditions(this->this_field());
535 dc.set_repeated_index(i);
536 if (dc.has_omit_if())
538 dc.regenerate(this_message(), root_message(), i);
543 if (i < wire_values.size())
544 out += any_size(wire_values[i]);
546 out += any_size(dccl::any());
551 void dccl::FieldCodecBase::check_repeat_settings()
const
553 if (!dccl_field_options().has_max_repeat())
554 throw(Exception(
"Missing (dccl.field).max_repeat option on `repeated` field: " +
555 this_field()->DebugString(),
556 this->this_descriptor()));
557 else if (dccl_field_options().max_repeat() < 1)
558 throw(Exception(
"(dccl.field).max_repeat must not be less than 1: " +
559 this_field()->DebugString(),
560 this->this_descriptor()));
561 else if (dccl_field_options().max_repeat() < dccl_field_options().min_repeat())
562 throw(Exception(
"(dccl.field).max_repeat must not be less than (dccl.field).min_repeat: " +
563 this_field()->DebugString(),
564 this->this_descriptor()));
567 unsigned dccl::FieldCodecBase::max_size_repeated()
569 check_repeat_settings();
571 if (codec_version() > 2)
572 return repeated_vector_field_size(dccl_field_options().min_repeat(),
573 dccl_field_options().max_repeat()) +
574 max_size() * dccl_field_options().max_repeat();
576 return max_size() * dccl_field_options().max_repeat();
579 unsigned dccl::FieldCodecBase::min_size_repeated()
581 check_repeat_settings();
583 if (codec_version() > 2)
584 return repeated_vector_field_size(dccl_field_options().min_repeat(),
585 dccl_field_options().max_repeat()) +
586 min_size() * dccl_field_options().min_repeat();
589 return min_size() * dccl_field_options().max_repeat();
592 void dccl::FieldCodecBase::any_pre_encode_repeated(std::vector<dccl::any>* wire_values,
593 const std::vector<dccl::any>& field_values)
595 for (
const auto& field_value : field_values)
597 dccl::any wire_value;
598 any_pre_encode(&wire_value, field_value);
599 wire_values->push_back(wire_value);
602 void dccl::FieldCodecBase::any_post_decode_repeated(
const std::vector<dccl::any>& wire_values,
603 std::vector<dccl::any>* field_values)
605 for (
const auto& wire_value : wire_values)
607 dccl::any field_value;
608 any_post_decode(wire_value, &field_value);
609 field_values->push_back(field_value);
617 void dccl::FieldCodecBase::disp_size(
const google::protobuf::FieldDescriptor* field,
618 const Bitset& new_bits,
int depth,
int vector_size )
620 if (!root_descriptor())
623 if (dlog.
check(DEBUG2))
625 std::string name = ((field) ? field->name() : root_descriptor()->full_name());
626 if (vector_size >= 0)
627 name +=
"[" + std::to_string(vector_size) +
"]";
629 dlog.
is(DEBUG2, SIZE) && dlog << std::string(depth,
'|') << name << std::setfill(
'.')
630 << std::setw(40 - name.size() - depth) << new_bits.size()
634 dlog.
is(DEBUG2, SIZE) && dlog << std::endl;
640 using google::protobuf::FieldDescriptor;
641 return os <<
"[FieldCodec '" << field_codec.
name() <<
"']: field type: "
642 << field_codec.manager().type_helper().find(field_codec.
field_type())->as_str()
644 << field_codec.manager()
646 .find(FieldDescriptor::TypeToCppType(field_codec.
field_type()))
649 << field_codec.manager().type_helper().find(field_codec.
wire_type())->as_str();
654 return message_data().top_field();
659 return message_data().top_descriptor();
664 return message_data().top_message();
669 return manager().codec_data().root_message_;
672 const google::protobuf::Descriptor* dccl::FieldCodecBase::root_descriptor()
const
674 return manager().codec_data().root_descriptor_;
679 return manager().codec_data().message_data_;
684 return manager().codec_data().message_data_;
686 bool dccl::FieldCodecBase::has_codec_group()
688 const google::protobuf::Descriptor* root_desc = root_descriptor();
691 return root_desc->options().GetExtension(dccl::msg).has_codec_group() ||
692 root_desc->options().GetExtension(dccl::msg).has_codec_version();
700 bool dccl::FieldCodecBase::strict() {
return manager().codec_data().strict_; }
702 int dccl::FieldCodecBase::codec_version()
704 return root_descriptor()->options().GetExtension(dccl::msg).codec_version();
707 std::string dccl::FieldCodecBase::codec_group() {
return codec_group(root_descriptor()); }
710 dccl::FieldCodecBase::dynamic_conditions(
const google::protobuf::FieldDescriptor* field)
712 manager().codec_data().dynamic_conditions_.set_field(field);
713 return manager().codec_data().dynamic_conditions_;
716 dccl::FieldCodecBase::BaseRAII::BaseRAII(FieldCodecBase* field_codec, MessagePart part,
717 const google::protobuf::Descriptor* root_descriptor,
719 : field_codec_(field_codec)
722 field_codec_->manager().codec_data().part_ =
part;
723 field_codec_->manager().codec_data().strict_ = strict;
724 field_codec_->manager().codec_data().root_message_ =
nullptr;
725 field_codec_->manager().codec_data().root_descriptor_ = root_descriptor;
727 dccl::FieldCodecBase::BaseRAII::BaseRAII(FieldCodecBase* field_codec, MessagePart part,
729 : field_codec_(field_codec)
732 field_codec_->manager().codec_data().part_ =
part;
733 field_codec_->manager().codec_data().strict_ = strict;
734 field_codec_->manager().codec_data().root_message_ = root_message;
735 field_codec_->manager().codec_data().root_descriptor_ = root_message->GetDescriptor();
737 dccl::FieldCodecBase::BaseRAII::~BaseRAII()
739 field_codec_->manager().codec_data().part_ = dccl::UNKNOWN;
740 field_codec_->manager().codec_data().strict_ =
false;
741 field_codec_->manager().codec_data().root_message_ =
nullptr;
742 field_codec_->manager().codec_data().root_descriptor_ =
nullptr;