DCCL v4
field_codec_default_message.h
1 // Copyright 2014-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 DCCLFIELDCODECDEFAULTMESSAGE20110510H
26 #define DCCLFIELDCODECDEFAULTMESSAGE20110510H
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 v2
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  void validate() override;
53  std::string info() override;
54  std::size_t hash() override;
55  bool check_field(const google::protobuf::FieldDescriptor* field);
56 
57  struct Size
58  {
59  static void repeated(std::shared_ptr<FieldCodecBase> codec, unsigned* return_value,
60  const std::vector<dccl::any>& field_values,
61  const google::protobuf::FieldDescriptor* field_desc)
62  {
63  codec->field_size_repeated(return_value, field_values, field_desc);
64  }
65 
66  static void single(std::shared_ptr<FieldCodecBase> codec, unsigned* return_value,
67  const dccl::any& field_value,
68  const google::protobuf::FieldDescriptor* field_desc)
69  {
70  codec->field_size(return_value, field_value, field_desc);
71  }
72  };
73 
74  struct Encoder
75  {
76  static void repeated(std::shared_ptr<FieldCodecBase> codec, Bitset* return_value,
77  const std::vector<dccl::any>& field_values,
78  const google::protobuf::FieldDescriptor* field_desc)
79  {
80  codec->field_encode_repeated(return_value, field_values, field_desc);
81  }
82 
83  static void single(std::shared_ptr<FieldCodecBase> codec, Bitset* return_value,
84  const dccl::any& field_value,
85  const google::protobuf::FieldDescriptor* field_desc)
86  {
87  codec->field_encode(return_value, field_value, field_desc);
88  }
89  };
90 
91  struct MaxSize
92  {
93  static void field(std::shared_ptr<FieldCodecBase> codec, unsigned* return_value,
94  const google::protobuf::FieldDescriptor* field_desc)
95  {
96  codec->field_max_size(return_value, field_desc);
97  }
98  };
99 
100  struct MinSize
101  {
102  static void field(std::shared_ptr<FieldCodecBase> codec, unsigned* return_value,
103  const google::protobuf::FieldDescriptor* field_desc)
104  {
105  codec->field_min_size(return_value, field_desc);
106  }
107  };
108 
109  struct Validate
110  {
111  static void field(std::shared_ptr<FieldCodecBase> codec, bool* return_value,
112  const google::protobuf::FieldDescriptor* field_desc)
113  {
114  codec->field_validate(return_value, field_desc);
115  }
116  };
117 
118  struct Info
119  {
120  static void field(std::shared_ptr<FieldCodecBase> codec, std::stringstream* return_value,
121  const google::protobuf::FieldDescriptor* field_desc)
122  {
123  codec->field_info(return_value, field_desc);
124  }
125  };
126 
127  struct Hash
128  {
129  static void field(std::shared_ptr<FieldCodecBase> codec, std::size_t* return_value,
130  const google::protobuf::FieldDescriptor* field_desc)
131  {
132  codec->field_hash(return_value, field_desc);
133  }
134  };
135 
136  template <typename Action, typename ReturnType>
137  void traverse_descriptor(ReturnType* return_value)
138  {
139  const google::protobuf::Descriptor* desc = FieldCodecBase::this_descriptor();
140  for (int i = 0, n = desc->field_count(); i < n; ++i)
141  {
142  const google::protobuf::FieldDescriptor* field_desc = desc->field(i);
143 
144  if (!check_field(field_desc))
145  continue;
146 
147  Action::field(find(field_desc), return_value, field_desc);
148  }
149  }
150 
151  template <typename Action, typename ReturnType>
152  ReturnType traverse_const_message(const dccl::any& wire_value)
153  {
154  try
155  {
156  ReturnType return_value = ReturnType();
157 
158  const auto* msg = dccl::any_cast<const google::protobuf::Message*>(wire_value);
159  const google::protobuf::Descriptor* desc = msg->GetDescriptor();
160  const google::protobuf::Reflection* refl = msg->GetReflection();
161  for (int i = 0, n = desc->field_count(); i < n; ++i)
162  {
163  const google::protobuf::FieldDescriptor* field_desc = desc->field(i);
164 
165  if (!check_field(field_desc))
166  continue;
167 
168  std::shared_ptr<FieldCodecBase> codec = find(field_desc);
169  std::shared_ptr<internal::FromProtoCppTypeBase> helper =
170  manager().type_helper().find(field_desc);
171 
172  if (field_desc->is_repeated())
173  {
174  std::vector<dccl::any> field_values;
175  for (int j = 0, m = refl->FieldSize(*msg, field_desc); j < m; ++j)
176  field_values.push_back(helper->get_repeated_value(field_desc, *msg, j));
177 
178  Action::repeated(codec, &return_value, field_values, field_desc);
179  }
180  else
181  {
182  Action::single(codec, &return_value, helper->get_value(field_desc, *msg),
183  field_desc);
184  }
185  }
186  return return_value;
187  }
188  catch (dccl::bad_any_cast& e)
189  {
190  throw(Exception("Bad type given to traverse const, expecting const "
191  "google::protobuf::Message*, got " +
192  std::string(wire_value.type().name())));
193  }
194  }
195 };
196 
197 } // namespace v2
198 } // namespace dccl
199 
200 //encode, size, etc.
201 
202 #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:658
dccl::FieldCodecBase
Provides a base class for defining DCCL field encoders / decoders. Most users who wish to define cust...
Definition: field_codec.h:54
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
Dynamic Compact Control Language namespace.
Definition: any.h:49
dccl::Exception
Exception class for DCCL.
Definition: exception.h:47
dccl::Bitset
A variable size container of bits (subclassed from std::deque<bool>) with an optional hierarchy....
Definition: bitset.h:41
dccl::v2::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