DCCL v4
Loading...
Searching...
No Matches
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
33namespace dccl
34{
35namespace 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
A variable size container of bits (subclassed from std::deque<bool>) with an optional hierarchy....
Definition bitset.h:43
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
const google::protobuf::Descriptor * this_descriptor() const
Returns the Descriptor (message schema meta-data) for the immediate parent Message.
const google::protobuf::FieldDescriptor * this_field() const
Returns the FieldDescriptor (field schema meta-data) for this field.
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...
Provides the default codec for encoding a base Google Protobuf message or an embedded message by call...
Dynamic Compact Control Language namespace.
Definition any.h:47