DCCL v4
Loading...
Searching...
No Matches
field_codec.cpp
1// Copyright 2011-2023:
2// GobySoft, LLC (2013-)
3// Massachusetts Institute of Technology (2007-2014)
4// Community contributors (see AUTHORS file)
5// File authors:
6// Toby Schneider <toby@gobysoft.org>
7//
8//
9// This file is part of the Dynamic Compact Control Language Library
10// ("DCCL").
11//
12// DCCL is free software: you can redistribute it and/or modify
13// it under the terms of the GNU Lesser General Public License as published by
14// the Free Software Foundation, either version 2.1 of the License, or
15// (at your option) any later version.
16//
17// DCCL is distributed in the hope that it will be useful,
18// but WITHOUT ANY WARRANTY; without even the implied warranty of
19// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20// GNU Lesser General Public License for more details.
21//
22// You should have received a copy of the GNU Lesser General Public License
23// along with DCCL. If not, see <http://www.gnu.org/licenses/>.
24#include "field_codec.h"
25#include "codec.h"
26#include "exception.h"
27
28using dccl::dlog;
29using namespace dccl::logger;
30
31//
32// FieldCodecBase public
33//
34dccl::FieldCodecBase::FieldCodecBase() = default;
35
36void dccl::FieldCodecBase::base_encode(Bitset* bits, const google::protobuf::Message& field_value,
37 MessagePart part, bool strict)
38{
39 BaseRAII scoped_globals(this, part, &field_value, strict);
40
41 // we pass this through the FromProtoCppTypeBase to do dynamic_cast (RTTI) for
42 // custom message codecs so that these codecs can be written in the derived class (not google::protobuf::Message)
43 field_encode(bits,
44 manager().type_helper().find(field_value.GetDescriptor())->get_value(field_value),
45 nullptr);
46}
47
48void dccl::FieldCodecBase::field_encode(Bitset* bits, const dccl::any& field_value,
49 const google::protobuf::FieldDescriptor* field)
50{
51 internal::MessageStack msg_handler(root_message(), message_data(), field);
52
53 if (field)
54 dlog.is(DEBUG2, ENCODE) && dlog << "Starting encode for field: " << field->DebugString()
55 << std::flush;
56
57 dccl::any wire_value;
58 field_pre_encode(&wire_value, field_value);
59
60 Bitset new_bits;
61 any_encode(&new_bits, wire_value);
62 disp_size(field, new_bits, msg_handler.field_size());
63 bits->append(new_bits);
64
65 if (field)
66 dlog.is(DEBUG2, ENCODE) && dlog << "... produced these " << new_bits.size()
67 << " bits: " << new_bits << std::endl;
68}
69
71 const std::vector<dccl::any>& field_values,
72 const google::protobuf::FieldDescriptor* field)
73{
74 internal::MessageStack msg_handler(root_message(), message_data(), field);
75
76 std::vector<dccl::any> wire_values;
77 field_pre_encode_repeated(&wire_values, field_values);
78
79 Bitset new_bits;
80 any_encode_repeated(&new_bits, wire_values);
81 disp_size(field, new_bits, msg_handler.field_size(), wire_values.size());
82 bits->append(new_bits);
83}
84
85void dccl::FieldCodecBase::base_size(unsigned* bit_size, const google::protobuf::Message& msg,
86 MessagePart part)
87{
88 BaseRAII scoped_globals(this, part, &msg);
89
90 *bit_size = 0;
91
92 field_size(bit_size, &msg, nullptr);
93}
94
95void dccl::FieldCodecBase::field_size(unsigned* bit_size, const dccl::any& field_value,
96 const google::protobuf::FieldDescriptor* field)
97{
98 internal::MessageStack msg_handler(root_message(), message_data(), field);
99
100 dccl::any wire_value;
101 field_pre_encode(&wire_value, field_value);
102
103 *bit_size += any_size(wire_value);
104}
105
107 const std::vector<dccl::any>& field_values,
108 const google::protobuf::FieldDescriptor* field)
109{
110 internal::MessageStack msg_handler(root_message(), message_data(), field);
111
112 std::vector<dccl::any> wire_values;
113 field_pre_encode_repeated(&wire_values, field_values);
114
115 *bit_size += any_size_repeated(wire_values);
116}
117
118void dccl::FieldCodecBase::base_decode(Bitset* bits, google::protobuf::Message* field_value,
119 MessagePart part)
120{
121 BaseRAII scoped_globals(this, part, field_value);
122 dccl::any value(field_value);
123 field_decode(bits, &value, nullptr);
124}
125
126void dccl::FieldCodecBase::field_decode(Bitset* bits, dccl::any* field_value,
127 const google::protobuf::FieldDescriptor* field)
128{
129 internal::MessageStack msg_handler(root_message(), message_data(), field);
130
131 if (!field_value)
132 throw(Exception("Decode called with NULL dccl::any"));
133 else if (!bits)
134 throw(Exception("Decode called with NULL Bitset"));
135
136 if (field)
137 dlog.is(DEBUG2, DECODE) && dlog << "Starting decode for field: " << field->DebugString()
138 << std::flush;
139
140 if (root_message())
141 dlog.is(DEBUG3, DECODE) && dlog << "Message thus far is: " << root_message()->DebugString()
142 << std::flush;
143
144 Bitset these_bits(bits);
145
146 unsigned bits_to_transfer = 0;
147 field_min_size(&bits_to_transfer, field);
148 these_bits.get_more_bits(bits_to_transfer);
149
150 if (field)
151 dlog.is(DEBUG2, DECODE) && dlog << "... using these bits: " << these_bits << std::endl;
152
153 dccl::any wire_value = *field_value;
154
155 any_decode(&these_bits, &wire_value);
156
157 field_post_decode(wire_value, field_value);
158}
159
160void dccl::FieldCodecBase::field_decode_repeated(Bitset* bits, std::vector<dccl::any>* field_values,
161 const google::protobuf::FieldDescriptor* field)
162{
163 internal::MessageStack msg_handler(root_message(), message_data(), field);
164
165 if (!field_values)
166 throw(Exception("Decode called with NULL field_values"));
167 else if (!bits)
168 throw(Exception("Decode called with NULL Bitset"));
169
170 if (field)
171 dlog.is(DEBUG2, DECODE) &&
172 dlog << "Starting repeated decode for field: " << field->DebugString() << std::endl;
173
174 Bitset these_bits(bits);
175
176 unsigned bits_to_transfer = 0;
177 field_min_size(&bits_to_transfer, field);
178 these_bits.get_more_bits(bits_to_transfer);
179
180 dlog.is(DEBUG2, DECODE) && dlog << "using these " << these_bits.size()
181 << " bits: " << these_bits << std::endl;
182
183 std::vector<dccl::any> wire_values = *field_values;
184 any_decode_repeated(&these_bits, &wire_values);
185
186 field_values->clear();
187 field_post_decode_repeated(wire_values, field_values);
188}
189
191 const google::protobuf::Descriptor* desc, MessagePart part)
192{
193 BaseRAII scoped_globals(this, part, desc);
194 *bit_size = 0;
195
196 internal::MessageStack msg_handler(root_message(), message_data());
197 if (desc)
198 msg_handler.push(desc);
199 else
200 throw(Exception("Max Size called with NULL Descriptor"));
201
202 field_max_size(bit_size, static_cast<google::protobuf::FieldDescriptor*>(nullptr));
203}
204
206 const google::protobuf::FieldDescriptor* field)
207{
208 internal::MessageStack msg_handler(root_message(), message_data(), field);
209
210 if (this_field())
211 *bit_size += this_field()->is_repeated() ? max_size_repeated() : max_size();
212 else
213 *bit_size += max_size();
214}
215
217 const google::protobuf::Descriptor* desc, MessagePart part)
218{
219 BaseRAII scoped_globals(this, part, desc);
220
221 *bit_size = 0;
222
223 internal::MessageStack msg_handler(root_message(), message_data());
224 if (desc)
225 msg_handler.push(desc);
226 else
227 throw(Exception("Min Size called with NULL Descriptor"));
228
229 field_min_size(bit_size, static_cast<google::protobuf::FieldDescriptor*>(nullptr));
230}
231
233 const google::protobuf::FieldDescriptor* field)
234
235{
236 internal::MessageStack msg_handler(root_message(), message_data(), field);
237
238 if (this_field())
239 *bit_size += this_field()->is_repeated() ? min_size_repeated() : min_size();
240 else
241 *bit_size += min_size();
242}
243
244void dccl::FieldCodecBase::base_validate(const google::protobuf::Descriptor* desc, MessagePart part)
245{
246 BaseRAII scoped_globals(this, part, desc);
247
248 internal::MessageStack msg_handler(root_message(), message_data());
249 if (desc)
250 msg_handler.push(desc);
251 else
252 throw(Exception("Validate called with NULL Descriptor"));
253
254 bool b = false;
255 field_validate(&b, static_cast<google::protobuf::FieldDescriptor*>(nullptr));
256}
257
259 const google::protobuf::FieldDescriptor* field)
260{
261 internal::MessageStack msg_handler(root_message(), message_data(), field);
262
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."));
266
267 if (field && dccl_field_options().in_head() && is_part_of_oneof(field))
268 throw(Exception(
269 "Oneof field used in header - oneof fields cannot be encoded in the header."));
270
271 validate();
272}
273
274void dccl::FieldCodecBase::base_info(std::ostream* os, const google::protobuf::Descriptor* desc,
275 MessagePart part)
276{
277 BaseRAII scoped_globals(this, part, desc);
278
279 internal::MessageStack msg_handler(root_message(), message_data());
280 if (desc)
281 msg_handler.push(desc);
282 else
283 throw(Exception("info called with NULL Descriptor"));
284
285 field_info(os, static_cast<google::protobuf::FieldDescriptor*>(nullptr));
286}
287
289 const google::protobuf::FieldDescriptor* field)
290{
291 internal::MessageStack msg_handler(root_message(), message_data(), field);
292
293 std::stringstream ss;
294 int depth = msg_handler.count();
295
296 std::string name =
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())
300 name += "[" +
301 (dccl_field_options().has_min_repeat()
302 ? (std::to_string(dccl_field_options().min_repeat()) + "-")
303 : "") +
304 std::to_string(dccl_field_options().max_repeat()) + "]";
305
306 if (!this_field() || this_field()->type() == google::protobuf::FieldDescriptor::TYPE_MESSAGE)
307 depth -= 1;
308
309 const int spaces = 8;
310 std::string indent =
311 std::string(spaces * (depth) + spaces / 2 * (field && is_part_of_oneof(field)),
312 ' '); // Add 4 spaces of indentation for fields belonging to oneofs
313
314 const int full_width = 40;
315
316 bool is_zero_size = false;
317
318 std::stringstream range;
319 if (variable_size())
320 {
321 unsigned max_sz = 0, min_sz = 0;
322 field_max_size(&max_sz, field);
323 field_min_size(&min_sz, field);
324 if (!max_sz)
325 is_zero_size = true;
326 range << min_sz << "-" << max_sz;
327 }
328 else
329 {
330 unsigned sz = 0;
331 field_max_size(&sz, field);
332 if (!sz)
333 is_zero_size = true;
334 range << sz;
335 }
336
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()
339 << " {"
340 << (this_field() ? manager().find(this_field(), codec_version(), has_codec_group(), codec_group())->name()
341 : manager().find(manager().codec_data().root_descriptor_)->name())
342 << "}";
343
344 if (!is_zero_size)
345 *os << ss.str() << "\n";
346
347 std::string specific_info = info();
348 if (!specific_info.empty())
349 *os << specific_info;
350}
351
352void dccl::FieldCodecBase::base_hash(std::size_t* hash, const google::protobuf::Descriptor* desc,
353 MessagePart part)
354{
355 BaseRAII scoped_globals(this, part, desc);
356
357 internal::MessageStack msg_handler(root_message(), message_data());
358 if (desc)
359 msg_handler.push(desc);
360 else
361 throw(Exception("Hash called with NULL Descriptor"));
362
363 field_hash(hash, static_cast<google::protobuf::FieldDescriptor*>(nullptr));
364}
365
366void dccl::FieldCodecBase::field_hash(std::size_t* hash_value,
367 const google::protobuf::FieldDescriptor* field)
368{
369 internal::MessageStack msg_handler(root_message(), message_data(), field);
370
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."));
374
375 if (field && dccl_field_options().in_head() && is_part_of_oneof(field))
376 throw(Exception(
377 "Oneof field used in header - oneof fields cannot be encoded in the header."));
378
379 if (this_field())
380 {
381 google::protobuf::FieldDescriptorProto field_to_hash;
382 this_field()->CopyTo(&field_to_hash);
383
384 // name doesn't affect encoding
385 field_to_hash.clear_name();
386 // we will handle dccl options separately, non-dccl options don't affect encoding
387 field_to_hash.clear_options();
388 field_to_hash.clear_type_name();
389 field_to_hash.clear_default_value();
390
391 dccl::DCCLFieldOptions dccl_opts = dccl_field_options();
392
393 hash_combine(*hash_value, field_to_hash.DebugString());
394 hash_combine(*hash_value, dccl_opts.DebugString());
395 }
396 else
397 {
398 // root level message
399 dccl::DCCLMessageOptions dccl_opts = this_descriptor()->options().GetExtension(dccl::msg);
400 dccl_opts.clear_max_bytes(); // max bytes doesn't affect encoding
401
402 hash_combine(*hash_value, dccl_opts.DebugString());
403 }
404
405 hash_combine(*hash_value, hash());
406}
407
408std::string dccl::FieldCodecBase::codec_group(const google::protobuf::Descriptor* desc)
409{
410 if (desc->options().GetExtension(dccl::msg).has_codec_group())
411 return desc->options().GetExtension(dccl::msg).codec_group();
412 else
413 return Codec::default_codec_name(desc->options().GetExtension(dccl::msg).codec_version());
414}
415
416//
417// FieldCodecBase protected
418//
419
420std::string dccl::FieldCodecBase::info() { return std::string(); }
421
422void dccl::FieldCodecBase::any_encode_repeated(dccl::Bitset* bits,
423 const std::vector<dccl::any>& wire_values)
424{
425 // out_bits = [field_values[2]][field_values[1]][field_values[0]]
426
427 unsigned wire_vector_size = dccl_field_options().max_repeat();
428
429 if (wire_values.size() > wire_vector_size && strict())
430 throw(
431 dccl::OutOfRangeException(std::string("Repeated size exceeds max_repeat for field: ") +
432 FieldCodecBase::this_field()->DebugString(),
433 this->this_field(), this->this_descriptor()));
434
435 if (wire_values.size() < dccl_field_options().min_repeat() && strict())
437 std::string("Repeated size is less than min_repeat for field: ") +
438 FieldCodecBase::this_field()->DebugString(),
439 this->this_field(), this->this_descriptor()));
440
441 // for DCCL3 and beyond, add a prefix numeric field giving the vector size (rather than always going to max_repeat)
442 if (codec_version() > 2)
443 {
444 wire_vector_size = std::min(static_cast<int>(dccl_field_options().max_repeat()),
445 static_cast<int>(wire_values.size()));
446
447 wire_vector_size = std::max(static_cast<int>(dccl_field_options().min_repeat()),
448 static_cast<int>(wire_vector_size));
449
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());
453 bits->append(size_bits);
454
455 dlog.is(DEBUG2, ENCODE) && dlog << "repeated size field ... produced these "
456 << size_bits.size() << " bits: " << size_bits << std::endl;
457 }
458
459 internal::MessageStack msg_handler(root_message(), message_data(), this->this_field());
460 for (unsigned i = 0, n = wire_vector_size; i < n; ++i)
461 {
462 msg_handler.update_index(root_message(), this->this_field(), i);
463
464 DynamicConditions& dc = this->dynamic_conditions(this->this_field());
465 dc.set_repeated_index(i);
466 if (dc.has_omit_if())
467 {
468 dc.regenerate(this_message(), root_message(), i);
469 if (dc.omit())
470 continue;
471 }
472
473 Bitset new_bits;
474 if (i < wire_values.size())
475 any_encode(&new_bits, wire_values[i]);
476 else
477 any_encode(&new_bits, dccl::any());
478 bits->append(new_bits);
479 }
480}
481
482void dccl::FieldCodecBase::any_decode_repeated(Bitset* repeated_bits,
483 std::vector<dccl::any>* wire_values)
484{
485 unsigned wire_vector_size = dccl_field_options().max_repeat();
486 if (codec_version() > 2)
487 {
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()));
491
492 wire_vector_size = size_bits.to_ulong() + dccl_field_options().min_repeat();
493 }
494
495 wire_values->resize(wire_vector_size);
496
497 internal::MessageStack msg_handler(root_message(), message_data(), this->this_field());
498 for (unsigned i = 0, n = wire_vector_size; i < n; ++i)
499 {
500 msg_handler.update_index(root_message(), this->this_field(), i);
501
502 DynamicConditions& dc = this->dynamic_conditions(this->this_field());
503 dc.set_repeated_index(i);
504 if (dc.has_omit_if())
505 {
506 dc.regenerate(this_message(), root_message(), i);
507 if (dc.omit())
508 continue;
509 }
510
511 Bitset these_bits(repeated_bits);
512 these_bits.get_more_bits(min_size());
513 any_decode(&these_bits, &(*wire_values)[i]);
514 }
515}
516
517unsigned dccl::FieldCodecBase::any_size_repeated(const std::vector<dccl::any>& wire_values)
518{
519 unsigned out = 0;
520 unsigned wire_vector_size = dccl_field_options().max_repeat();
521
522 if (codec_version() > 2)
523 {
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());
528 }
529
530 internal::MessageStack msg_handler(root_message(), message_data(), this->this_field());
531 for (unsigned i = 0, n = wire_vector_size; i < n; ++i)
532 {
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())
537 {
538 dc.regenerate(this_message(), root_message(), i);
539 if (dc.omit())
540 continue;
541 }
542
543 if (i < wire_values.size())
544 out += any_size(wire_values[i]);
545 else
546 out += any_size(dccl::any());
547 }
548 return out;
549}
550
551void dccl::FieldCodecBase::check_repeat_settings() const
552{
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()));
565}
566
567unsigned dccl::FieldCodecBase::max_size_repeated()
568{
569 check_repeat_settings();
570
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();
575 else
576 return max_size() * dccl_field_options().max_repeat();
577}
578
579unsigned dccl::FieldCodecBase::min_size_repeated()
580{
581 check_repeat_settings();
582
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();
587
588 else
589 return min_size() * dccl_field_options().max_repeat();
590}
591
592void dccl::FieldCodecBase::any_pre_encode_repeated(std::vector<dccl::any>* wire_values,
593 const std::vector<dccl::any>& field_values)
594{
595 for (const auto& field_value : field_values)
596 {
597 dccl::any wire_value;
598 any_pre_encode(&wire_value, field_value);
599 wire_values->push_back(wire_value);
600 }
601}
602void dccl::FieldCodecBase::any_post_decode_repeated(const std::vector<dccl::any>& wire_values,
603 std::vector<dccl::any>* field_values)
604{
605 for (const auto& wire_value : wire_values)
606 {
607 dccl::any field_value;
608 any_post_decode(wire_value, &field_value);
609 field_values->push_back(field_value);
610 }
611}
612
613//
614// FieldCodecBase private
615//
616
617void dccl::FieldCodecBase::disp_size(const google::protobuf::FieldDescriptor* field,
618 const Bitset& new_bits, int depth, int vector_size /* = -1 */)
619{
620 if (!root_descriptor())
621 return;
622
623 if (dlog.check(DEBUG2))
624 {
625 std::string name = ((field) ? field->name() : root_descriptor()->full_name());
626 if (vector_size >= 0)
627 name += "[" + std::to_string(vector_size) + "]";
628
629 dlog.is(DEBUG2, SIZE) && dlog << std::string(depth, '|') << name << std::setfill('.')
630 << std::setw(40 - name.size() - depth) << new_bits.size()
631 << std::endl;
632
633 if (!field)
634 dlog.is(DEBUG2, SIZE) && dlog << std::endl;
635 }
636}
637
638std::ostream& dccl::operator<<(std::ostream& os, const dccl::FieldCodecBase& field_codec)
639{
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()
643 << " ("
644 << field_codec.manager()
645 .type_helper()
646 .find(FieldDescriptor::TypeToCppType(field_codec.field_type()))
647 ->as_str()
648 << ") | wire type: "
649 << field_codec.manager().type_helper().find(field_codec.wire_type())->as_str();
650}
651
652const google::protobuf::FieldDescriptor* dccl::FieldCodecBase::this_field() const
653{
654 return message_data().top_field();
655}
656
657const google::protobuf::Descriptor* dccl::FieldCodecBase::this_descriptor() const
658{
659 return message_data().top_descriptor();
660}
661
662const google::protobuf::Message* dccl::FieldCodecBase::this_message()
663{
664 return message_data().top_message();
665}
666
667const google::protobuf::Message* dccl::FieldCodecBase::root_message()
668{
669 return manager().codec_data().root_message_;
670}
671
672const google::protobuf::Descriptor* dccl::FieldCodecBase::root_descriptor() const
673{
674 return manager().codec_data().root_descriptor_;
675}
676
677dccl::internal::MessageStackData& dccl::FieldCodecBase::message_data()
678{
679 return manager().codec_data().message_data_;
680}
681
682const dccl::internal::MessageStackData& dccl::FieldCodecBase::message_data() const
683{
684 return manager().codec_data().message_data_;
685}
686bool dccl::FieldCodecBase::has_codec_group()
687{
688 const google::protobuf::Descriptor* root_desc = root_descriptor();
689 if (root_desc)
690 {
691 return root_desc->options().GetExtension(dccl::msg).has_codec_group() ||
692 root_desc->options().GetExtension(dccl::msg).has_codec_version();
693 }
694 else
695 return false;
696}
697
698dccl::MessagePart dccl::FieldCodecBase::part() { return manager().codec_data().part_; }
699
700bool dccl::FieldCodecBase::strict() { return manager().codec_data().strict_; }
701
702int dccl::FieldCodecBase::codec_version()
703{
704 return root_descriptor()->options().GetExtension(dccl::msg).codec_version();
705}
706
707std::string dccl::FieldCodecBase::codec_group() { return codec_group(root_descriptor()); }
708
710dccl::FieldCodecBase::dynamic_conditions(const google::protobuf::FieldDescriptor* field)
711{
712 manager().codec_data().dynamic_conditions_.set_field(field);
713 return manager().codec_data().dynamic_conditions_;
714}
715
716dccl::FieldCodecBase::BaseRAII::BaseRAII(FieldCodecBase* field_codec, MessagePart part,
717 const google::protobuf::Descriptor* root_descriptor,
718 bool strict)
719 : field_codec_(field_codec)
720
721{
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;
726}
727dccl::FieldCodecBase::BaseRAII::BaseRAII(FieldCodecBase* field_codec, MessagePart part,
728 const google::protobuf::Message* root_message, bool strict)
729 : field_codec_(field_codec)
730
731{
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();
736}
737dccl::FieldCodecBase::BaseRAII::~BaseRAII()
738{
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;
743}
A variable size container of bits (subclassed from std::deque<bool>) with an optional hierarchy....
Definition bitset.h:43
void get_more_bits(size_type num_bits)
Retrieve more bits from the parent Bitset.
Definition bitset.h:420
Bitset & append(const Bitset &bits)
Adds the bitset to the big end.
Definition bitset.h:361
Exception class for DCCL.
Definition exception.h:47
Provides a base class for defining DCCL field encoders / decoders. Most users who wish to define cust...
Definition field_codec.h:54
void field_encode(Bitset *bits, const dccl::any &field_value, const google::protobuf::FieldDescriptor *field)
Encode a non-repeated field.
void field_size(unsigned *bit_size, const dccl::any &field_value, const google::protobuf::FieldDescriptor *field)
Calculate the size of a field.
void base_hash(std::size_t *hash, const google::protobuf::Descriptor *desc, MessagePart part)
Provide a hash of the DCCL message definition to detect changes in the DCCL message.
const google::protobuf::Descriptor * this_descriptor() const
Returns the Descriptor (message schema meta-data) for the immediate parent Message.
virtual std::string info()
Write field specific information (in addition to general information such as sizes that are automatic...
google::protobuf::FieldDescriptor::CppType wire_type() const
the C++ type used "on the wire". This is the type visible after pre_encode and before post_decode fun...
Definition field_codec.h:75
const google::protobuf::FieldDescriptor * this_field() const
Returns the FieldDescriptor (field schema meta-data) for this field.
MessagePart part()
the part of the message currently being encoded (head or body)
void field_encode_repeated(Bitset *bits, const std::vector< dccl::any > &field_values, const google::protobuf::FieldDescriptor *field)
Encode a repeated field.
std::string name() const
the name of the codec used to identifier it in the .proto custom option extension
Definition field_codec.h:66
void base_validate(const google::protobuf::Descriptor *desc, MessagePart part)
Validate this part of the message to make sure all required extensions are set.
void field_decode(Bitset *bits, dccl::any *field_value, const google::protobuf::FieldDescriptor *field)
Decode a non-repeated field.
void base_info(std::ostream *os, const google::protobuf::Descriptor *desc, MessagePart part)
Get human readable information (size of fields, etc.) about this part of the DCCL message.
void base_min_size(unsigned *bit_size, const google::protobuf::Descriptor *desc, MessagePart part)
Calculate the minimum size of a message given its Descriptor alone (no data)
void base_max_size(unsigned *bit_size, const google::protobuf::Descriptor *desc, MessagePart part)
Calculate the maximum size of a message given its Descriptor alone (no data)
void field_hash(std::size_t *hash, const google::protobuf::FieldDescriptor *field)
Provide a hash for this field definition.
void base_decode(Bitset *bits, google::protobuf::Message *msg, MessagePart part)
Decode part of a message.
void base_size(unsigned *bit_size, const google::protobuf::Message &msg, MessagePart part)
Calculate the size (in bits) of a part of the base message when it is encoded.
google::protobuf::FieldDescriptor::Type field_type() const
the type exposed to the user in the original and decoded Protobuf messages
Definition field_codec.h:70
void field_min_size(unsigned *bit_size, const google::protobuf::FieldDescriptor *field)
Calculate the lower bound on this field's size (in bits)
void base_encode(Bitset *bits, const google::protobuf::Message &msg, MessagePart part, bool strict)
Encode this part (body or head) of the base message.
void field_validate(bool *b, const google::protobuf::FieldDescriptor *field)
Validate this field, checking that all required option extensions are set (e.g. (dccl....
void field_max_size(unsigned *bit_size, const google::protobuf::FieldDescriptor *field)
Calculate the upper bound on this field's size (in bits)
void field_decode_repeated(Bitset *bits, std::vector< dccl::any > *field_values, const google::protobuf::FieldDescriptor *field)
Decode a repeated field.
void field_size_repeated(unsigned *bit_size, const std::vector< dccl::any > &field_values, const google::protobuf::FieldDescriptor *field)
Calculate the size of a repeated field.
void field_info(std::ostream *os, const google::protobuf::FieldDescriptor *field)
Write human readable information about the field and its bounds to the provided stream.
bool is(logger::Verbosity verbosity, logger::Group group=logger::GENERAL)
Indicates the verbosity of the Logger until the next std::flush or std::endl. The boolean return is u...
Definition logger.h:192
bool check(logger::Verbosity verbosity)
Same as is() but doesn't set the verbosity or lock the mutex.
Definition logger.h:181
bool is_part_of_oneof(const google::protobuf::FieldDescriptor *field_desc)
Checks whether a given field is part to a oneof or not.
Definition oneof.h:36
void hash_combine(std::size_t &seed, const T &v)
hash combine - from boost::hash_combine
Definition common.h:152