DCCL v4
field_codec_default_message.h
1 // Copyright 2009-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 // Chris Murphy <cmurphy@aphysci.com>
8 //
9 //
10 // This file is part of the Dynamic Compact Control Language Library
11 // ("DCCL").
12 //
13 // DCCL is free software: you can redistribute it and/or modify
14 // it under the terms of the GNU Lesser General Public License as published by
15 // the Free Software Foundation, either version 2.1 of the License, or
16 // (at your option) any later version.
17 //
18 // DCCL is distributed in the hope that it will be useful,
19 // but WITHOUT ANY WARRANTY; without even the implied warranty of
20 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21 // GNU Lesser General Public License for more details.
22 //
23 // You should have received a copy of the GNU Lesser General Public License
24 // along with DCCL. If not, see <http://www.gnu.org/licenses/>.
25 #ifndef DCCLFIELDCODECDEFAULTMESSAGEV320140421H
26 #define DCCLFIELDCODECDEFAULTMESSAGEV320140421H
27 
28 #include "../field_codec.h"
29 #include "../field_codec_manager.h"
30 
31 #include "dccl/option_extensions.pb.h"
32 
33 namespace dccl
34 {
35 namespace v3
36 {
39 {
40  private:
41  void any_encode(Bitset* bits, const dccl::any& wire_value) override;
42  void any_decode(Bitset* bits, dccl::any* wire_value) override;
43  unsigned max_size() override;
44  unsigned min_size() override;
45  unsigned any_size(const dccl::any& wire_value) override;
46 
47  std::shared_ptr<FieldCodecBase> find(const google::protobuf::FieldDescriptor* field_desc)
48  {
49  return manager().find(field_desc, this->codec_version(), has_codec_group(), codec_group());
50  }
51 
52  bool is_optional() { return this_field() && this_field()->is_optional(); }
53 
54  void validate() override;
55  std::string info() override;
56  std::size_t hash() override;
57  bool check_field(const google::protobuf::FieldDescriptor* field);
58 
59  struct Size
60  {
61  static void repeated(std::shared_ptr<FieldCodecBase> codec, unsigned* return_value,
62  const std::vector<dccl::any>& field_values,
63  const google::protobuf::FieldDescriptor* field_desc)
64  {
65  codec->field_size_repeated(return_value, field_values, field_desc);
66  }
67 
68  static void single(std::shared_ptr<FieldCodecBase> codec, unsigned* return_value,
69  const dccl::any& field_value,
70  const google::protobuf::FieldDescriptor* field_desc)
71  {
72  codec->field_size(return_value, field_value, field_desc);
73  }
74  };
75 
76  struct Encoder
77  {
78  static void repeated(std::shared_ptr<FieldCodecBase> codec, Bitset* return_value,
79  const std::vector<dccl::any>& field_values,
80  const google::protobuf::FieldDescriptor* field_desc)
81  {
82  codec->field_encode_repeated(return_value, field_values, field_desc);
83  }
84 
85  static void single(std::shared_ptr<FieldCodecBase> codec, Bitset* return_value,
86  const dccl::any& field_value,
87  const google::protobuf::FieldDescriptor* field_desc)
88  {
89  codec->field_encode(return_value, field_value, field_desc);
90  }
91  };
92 
93  struct MaxSize
94  {
95  static void field(std::shared_ptr<FieldCodecBase> codec, unsigned* return_value,
96  const google::protobuf::FieldDescriptor* field_desc)
97  {
98  codec->field_max_size(return_value, field_desc);
99  }
100  };
101 
102  struct MinSize
103  {
104  static void field(std::shared_ptr<FieldCodecBase> codec, unsigned* return_value,
105  const google::protobuf::FieldDescriptor* field_desc)
106  {
107  // defer minimum size calculation for dynamic conditions (since omit == 0)
108  // this may provide an incorrect min_size() value for reporting but allows
109  // use of index based lua scripts in dynamic conditions
110  DynamicConditions& dc = codec->dynamic_conditions(field_desc);
111  if (dc.has_omit_if() || dc.has_required_if())
112  *return_value = 0;
113  else
114  codec->field_min_size(return_value, field_desc);
115  }
116  };
117 
118  struct Validate
119  {
120  static void field(std::shared_ptr<FieldCodecBase> codec, bool* return_value,
121  const google::protobuf::FieldDescriptor* field_desc)
122  {
123  codec->field_validate(return_value, field_desc);
124  }
125  };
126 
127  struct Info
128  {
129  static void field(std::shared_ptr<FieldCodecBase> codec, std::stringstream* return_value,
130  const google::protobuf::FieldDescriptor* field_desc)
131  {
132  codec->field_info(return_value, field_desc);
133  }
134  };
135 
136  struct Hash
137  {
138  static void field(std::shared_ptr<FieldCodecBase> codec, std::size_t* return_value,
139  const google::protobuf::FieldDescriptor* field_desc)
140  {
141  codec->field_hash(return_value, field_desc);
142  }
143  };
144 
145  template <typename Action, typename ReturnType>
146  void traverse_descriptor(ReturnType* return_value)
147  {
148  const google::protobuf::Descriptor* desc = FieldCodecBase::this_descriptor();
149 
150  for (int i = 0, n = desc->field_count(); i < n; ++i)
151  {
152  const google::protobuf::FieldDescriptor* field_desc = desc->field(i);
153 
154  if (!check_field(field_desc))
155  continue;
156 
157  Action::field(find(field_desc), return_value, field_desc);
158  }
159  }
160 
161  template <typename Action, typename ReturnType>
162  ReturnType traverse_const_message(const dccl::any& wire_value)
163  {
164  try
165  {
166  ReturnType return_value = ReturnType();
167 
168  const auto* msg = dccl::any_cast<const google::protobuf::Message*>(wire_value);
169  const google::protobuf::Descriptor* desc = msg->GetDescriptor();
170  const google::protobuf::Reflection* refl = msg->GetReflection();
171 
172  for (int i = 0, n = desc->field_count(); i < n; ++i)
173  {
174  const google::protobuf::FieldDescriptor* field_desc = desc->field(i);
175 
176  if (!check_field(field_desc))
177  continue;
178 
179  std::shared_ptr<FieldCodecBase> codec = find(field_desc);
180  std::shared_ptr<internal::FromProtoCppTypeBase> helper =
181  manager().type_helper().find(field_desc);
182 
183  if (field_desc->is_repeated())
184  {
185  std::vector<dccl::any> field_values;
186  for (int j = 0, m = refl->FieldSize(*msg, field_desc); j < m; ++j)
187  field_values.push_back(helper->get_repeated_value(field_desc, *msg, j));
188 
189  Action::repeated(codec, &return_value, field_values, field_desc);
190  }
191  else
192  {
193  // singular field dynamic conditions - repeated fields handled in any_encode_repeated
194  DynamicConditions& dc = dynamic_conditions(field_desc);
195  if (dc.has_omit_if())
196  {
197  // expensive, so don't do this unless we're going to use it
198  dc.regenerate(this_message(), root_message());
199  if (dc.omit())
200  continue;
201  }
202 
203  Action::single(codec, &return_value, helper->get_value(field_desc, *msg),
204  field_desc);
205  }
206  }
207  return return_value;
208  }
209  catch (dccl::bad_any_cast& e)
210  {
211  throw(Exception("Bad type given to traverse const, expecting const "
212  "google::protobuf::Message*, got " +
213  std::string(wire_value.type().name())));
214  }
215  }
216 };
217 
218 } // namespace v3
219 } // namespace dccl
220 
221 //encode, size, etc.
222 
223 #endif
dccl::FieldCodecBase::this_descriptor
const google::protobuf::Descriptor * this_descriptor() const
Returns the Descriptor (message schema meta-data) for the immediate parent Message.
Definition: field_codec.cpp:657
dccl::FieldCodecBase
Provides a base class for defining DCCL field encoders / decoders. Most users who wish to define cust...
Definition: field_codec.h:53
dccl::FieldCodecManagerLocal::find
std::shared_ptr< FieldCodecBase > find(const google::protobuf::FieldDescriptor *field, int codec_version, bool has_codec_group, const std::string &codec_group) const
Find the codec for a given field. For embedded messages, prefers (dccl.field).codec (inside field) ov...
Definition: field_codec_manager.h:114
dccl::DynamicConditions
Definition: dynamic_conditions.h:39
dccl
Dynamic Compact Control Language namespace.
Definition: any.h:46
dccl::FieldCodecBase::this_field
const google::protobuf::FieldDescriptor * this_field() const
Returns the FieldDescriptor (field schema meta-data) for this field.
Definition: field_codec.cpp:652
dccl::Exception
Exception class for DCCL.
Definition: exception.h:46
dccl::Bitset
A variable size container of bits (subclassed from std::deque<bool>) with an optional hierarchy....
Definition: bitset.h:42
dccl::v3::DefaultMessageCodec
Provides the default codec for encoding a base Google Protobuf message or an embedded message by call...
Definition: field_codec_default_message.h:38