EmbeddedProto 4.0.0b1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- EmbeddedProto/EmbeddedProto.py +122 -0
- EmbeddedProto/Features.py +255 -0
- EmbeddedProto/Field.py +1295 -0
- EmbeddedProto/Oneof.py +74 -0
- EmbeddedProto/ProtoFile.py +210 -0
- EmbeddedProto/TypeDefinitions.py +367 -0
- EmbeddedProto/__init__.py +0 -0
- EmbeddedProto/__main__.py +28 -0
- EmbeddedProto/config.py +173 -0
- EmbeddedProto/custom_header.py +513 -0
- EmbeddedProto/embedded_proto_options.proto +62 -0
- EmbeddedProto/embedded_proto_options_pb2.py +37 -0
- EmbeddedProto/field_options.py +344 -0
- EmbeddedProto/main.py +316 -0
- EmbeddedProto/src/EmbeddedProto/BytesStringCallback.h +476 -0
- EmbeddedProto/src/EmbeddedProto/Defines.h +118 -0
- EmbeddedProto/src/EmbeddedProto/EmptyArray.h +81 -0
- EmbeddedProto/src/EmbeddedProto/Errors.h +53 -0
- EmbeddedProto/src/EmbeddedProto/FieldStringBytes.h +793 -0
- EmbeddedProto/src/EmbeddedProto/Fields.h +832 -0
- EmbeddedProto/src/EmbeddedProto/Functional.h +412 -0
- EmbeddedProto/src/EmbeddedProto/MessageCallback.h +688 -0
- EmbeddedProto/src/EmbeddedProto/MessageInterface.h +792 -0
- EmbeddedProto/src/EmbeddedProto/MessageSizeCalculator.h +109 -0
- EmbeddedProto/src/EmbeddedProto/MessageState.h +207 -0
- EmbeddedProto/src/EmbeddedProto/ReadBufferFixedSize.h +204 -0
- EmbeddedProto/src/EmbeddedProto/ReadBufferInterface.h +181 -0
- EmbeddedProto/src/EmbeddedProto/ReadBufferSection.h +232 -0
- EmbeddedProto/src/EmbeddedProto/RepeatedField.h +1053 -0
- EmbeddedProto/src/EmbeddedProto/RepeatedFieldCallback.h +432 -0
- EmbeddedProto/src/EmbeddedProto/RepeatedFieldFixedSize.h +367 -0
- EmbeddedProto/src/EmbeddedProto/Version.h +39 -0
- EmbeddedProto/src/EmbeddedProto/WireFormatter.h +852 -0
- EmbeddedProto/src/EmbeddedProto/WriteBufferFixedSize.h +114 -0
- EmbeddedProto/src/EmbeddedProto/WriteBufferInterface.h +134 -0
- EmbeddedProto/src/EmbeddedProto.h +55 -0
- EmbeddedProto/templates/FieldBasic_Deserialize.h.jinja2 +26 -0
- EmbeddedProto/templates/FieldBasic_GetSet.h.jinja2 +89 -0
- EmbeddedProto/templates/FieldBytes_GetSet.h.jinja2 +86 -0
- EmbeddedProto/templates/FieldEnum_Deserialize.h.jinja2 +50 -0
- EmbeddedProto/templates/FieldEnum_GetSet.h.jinja2 +93 -0
- EmbeddedProto/templates/FieldErrorRecursive_GetSet.h.jinja2 +29 -0
- EmbeddedProto/templates/FieldMap_GetSet.h.jinja2 +203 -0
- EmbeddedProto/templates/FieldMsg_Deserialize.h.jinja2 +44 -0
- EmbeddedProto/templates/FieldMsg_GetSet.h.jinja2 +93 -0
- EmbeddedProto/templates/FieldRepeated_GetSet.h.jinja2 +94 -0
- EmbeddedProto/templates/FieldString_GetSet.h.jinja2 +86 -0
- EmbeddedProto/templates/Field_DeserializePartial.h.jinja2 +33 -0
- EmbeddedProto/templates/Field_Serialize.h.jinja2 +112 -0
- EmbeddedProto/templates/Field_SerializePartial.h.jinja2 +119 -0
- EmbeddedProto/templates/Header.h.jinja2 +108 -0
- EmbeddedProto/templates/TypeDefEnum.h.jinja2 +45 -0
- EmbeddedProto/templates/TypeDefMsg.h.jinja2 +791 -0
- EmbeddedProto/templates/TypeOneof.h.jinja2 +178 -0
- EmbeddedProto/version.json +3 -0
- embeddedproto-4.0.0b1.dist-info/METADATA +141 -0
- embeddedproto-4.0.0b1.dist-info/RECORD +63 -0
- embeddedproto-4.0.0b1.dist-info/WHEEL +5 -0
- embeddedproto-4.0.0b1.dist-info/entry_points.txt +3 -0
- embeddedproto-4.0.0b1.dist-info/licenses/LICENSE +30 -0
- embeddedproto-4.0.0b1.dist-info/licenses/LICENSES/GPL-3.0-only.txt +674 -0
- embeddedproto-4.0.0b1.dist-info/licenses/LICENSES/LicenseRef-EmbeddedProto-Commercial.txt +12 -0
- embeddedproto-4.0.0b1.dist-info/top_level.txt +1 -0
|
@@ -0,0 +1,792 @@
|
|
|
1
|
+
/*
|
|
2
|
+
* Copyright (C) 2020-2026 Embedded AMS B.V. - All Rights Reserved
|
|
3
|
+
*
|
|
4
|
+
* This file is part of Embedded Proto.
|
|
5
|
+
*
|
|
6
|
+
* Embedded Proto is dual licensed. You may use it under the terms of the
|
|
7
|
+
* GNU General Public License version 3 (GPLv3) as published by the Free
|
|
8
|
+
* Software Foundation, or under a commercial license from Embedded AMS B.V.
|
|
9
|
+
*
|
|
10
|
+
* Under the GPLv3 you must release the source code of
|
|
11
|
+
* any product you distribute that includes Embedded Proto or code
|
|
12
|
+
* generated by it. A commercial license removes that obligation.
|
|
13
|
+
* See <https://embeddedproto.com/pricing/>.
|
|
14
|
+
*
|
|
15
|
+
* Embedded Proto is distributed WITHOUT ANY WARRANTY; without even the
|
|
16
|
+
* implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
|
|
17
|
+
* See the LICENSE file in the root of the repository for details.
|
|
18
|
+
*
|
|
19
|
+
* SPDX-License-Identifier: GPL-3.0-only OR LicenseRef-EmbeddedProto-Commercial
|
|
20
|
+
*
|
|
21
|
+
* Embedded AMS B.V., Hoorn, the Netherlands - info at EmbeddedProto dot com
|
|
22
|
+
*/
|
|
23
|
+
|
|
24
|
+
#ifndef _MESSAGE_INTERFACE_H_
|
|
25
|
+
#define _MESSAGE_INTERFACE_H_
|
|
26
|
+
|
|
27
|
+
#include "WireFormatter.h"
|
|
28
|
+
#include "Fields.h"
|
|
29
|
+
#include "Errors.h"
|
|
30
|
+
#include "MessageState.h"
|
|
31
|
+
#include "ReadBufferSection.h"
|
|
32
|
+
|
|
33
|
+
#include <cstdint>
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
namespace EmbeddedProto
|
|
37
|
+
{
|
|
38
|
+
|
|
39
|
+
class MessageInterface : public ::EmbeddedProto::Field
|
|
40
|
+
{
|
|
41
|
+
public:
|
|
42
|
+
|
|
43
|
+
MessageInterface() = default;
|
|
44
|
+
|
|
45
|
+
~MessageInterface() = default;
|
|
46
|
+
|
|
47
|
+
//! \see Field::deserialize()
|
|
48
|
+
Error deserialize(::EmbeddedProto::ReadBufferInterface& buffer) override = 0;
|
|
49
|
+
|
|
50
|
+
//! \see Field::deserialize()
|
|
51
|
+
Error deserialize_check_type(::EmbeddedProto::ReadBufferInterface& buffer,
|
|
52
|
+
const ::EmbeddedProto::WireFormatter::WireType& wire_type) final;
|
|
53
|
+
|
|
54
|
+
//! Clear the content of this message and set it to it's default state.
|
|
55
|
+
/*!
|
|
56
|
+
The defaults are to be set according to the Protobuf standard.
|
|
57
|
+
*/
|
|
58
|
+
void clear() override = 0;
|
|
59
|
+
|
|
60
|
+
//! Serialize this message as a delimited group (editions message_encoding =
|
|
61
|
+
//! DELIMITED).
|
|
62
|
+
/*!
|
|
63
|
+
Writes a START_GROUP tag, this message's fields inline, then an END_GROUP
|
|
64
|
+
tag. Because group framing carries no length prefix there is no size
|
|
65
|
+
pre-pass, which enables single-pass encoding of (nested) messages.
|
|
66
|
+
|
|
67
|
+
\param field_number The field number for the START/END group tags.
|
|
68
|
+
\param buffer The buffer to write to.
|
|
69
|
+
\return Error::NO_ERRORS when successful.
|
|
70
|
+
*/
|
|
71
|
+
Error serialize_as_group(const uint32_t field_number, WriteBufferInterface& buffer) const
|
|
72
|
+
{
|
|
73
|
+
Error return_value = WireFormatter::SerializeVarint(
|
|
74
|
+
WireFormatter::MakeTag(field_number, WireFormatter::WireType::START_GROUP), buffer);
|
|
75
|
+
if(Error::NO_ERRORS == return_value)
|
|
76
|
+
{
|
|
77
|
+
return_value = this->serialize(buffer);
|
|
78
|
+
}
|
|
79
|
+
if(Error::NO_ERRORS == return_value)
|
|
80
|
+
{
|
|
81
|
+
return_value = WireFormatter::SerializeVarint(
|
|
82
|
+
WireFormatter::MakeTag(field_number, WireFormatter::WireType::END_GROUP), buffer);
|
|
83
|
+
}
|
|
84
|
+
return return_value;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
#ifdef PARTIAL_SERIALIZATION_ENABLED
|
|
88
|
+
//! Deserialize message with partial state support.
|
|
89
|
+
/*!
|
|
90
|
+
This method deserializes the message in chunks, allowing deserialization to be paused
|
|
91
|
+
when the buffer ends and resumed with a fresh buffer.
|
|
92
|
+
|
|
93
|
+
A top-level message carries no length prefix, so this function cannot tell where the
|
|
94
|
+
input ends. After the last field it returns to the tag phase and reports
|
|
95
|
+
Error::END_OF_BUFFER when no next tag is available. Only the caller knows whether more
|
|
96
|
+
data will arrive:
|
|
97
|
+
|
|
98
|
+
\code
|
|
99
|
+
Error result = Error::END_OF_BUFFER;
|
|
100
|
+
while((Error::END_OF_BUFFER == result) && receive_next_chunk(buffer))
|
|
101
|
+
{
|
|
102
|
+
result = msg.deserialize_partial(buffer, state.root());
|
|
103
|
+
}
|
|
104
|
+
const bool complete = (Error::END_OF_BUFFER == result)
|
|
105
|
+
&& (FieldProcessingPhase::TAG == state.root().phase);
|
|
106
|
+
\endcode
|
|
107
|
+
|
|
108
|
+
\param buffer Read buffer (may be small).
|
|
109
|
+
\param state External state object (must persist between calls).
|
|
110
|
+
\return Error::END_OF_BUFFER with state.phase == FieldProcessingPhase::TAG when the buffer
|
|
111
|
+
ended at a field boundary. When the caller has no more input the message is
|
|
112
|
+
complete, otherwise call again with a fresh buffer.
|
|
113
|
+
\return Error::END_OF_BUFFER with any other phase when a field was cut, call again with a
|
|
114
|
+
fresh buffer.
|
|
115
|
+
\return Error::NO_ERRORS with state.phase == FieldProcessingPhase::COMPLETE when a
|
|
116
|
+
DELIMITED (group) message consumed its END_GROUP tag, see
|
|
117
|
+
deserialize_partial_as_group().
|
|
118
|
+
\return Other errors on failure (state should be reset).
|
|
119
|
+
*/
|
|
120
|
+
virtual Error deserialize_partial(ReadBufferInterface& buffer,
|
|
121
|
+
MessageState& state) = 0;
|
|
122
|
+
|
|
123
|
+
//! Serialize message with partial state support.
|
|
124
|
+
/*!
|
|
125
|
+
This method serializes the message in chunks, allowing serialization to be paused
|
|
126
|
+
when the buffer becomes full and resumed with a fresh buffer.
|
|
127
|
+
|
|
128
|
+
\param buffer Write buffer (may be small).
|
|
129
|
+
\param state External state object (must persist between calls).
|
|
130
|
+
\return Error::NO_ERRORS when complete.
|
|
131
|
+
\return Error::BUFFER_FULL when buffer full, call again with fresh buffer.
|
|
132
|
+
\return Other errors on failure (state should be reset).
|
|
133
|
+
*/
|
|
134
|
+
virtual Error serialize_partial(WriteBufferInterface& buffer,
|
|
135
|
+
MessageState& state) const = 0;
|
|
136
|
+
|
|
137
|
+
Error serialize_partial_as_field(uint32_t field_number,
|
|
138
|
+
WriteBufferInterface& buffer,
|
|
139
|
+
MessageState& state,
|
|
140
|
+
bool optional) const override
|
|
141
|
+
{
|
|
142
|
+
Error return_value = Error::NO_ERRORS;
|
|
143
|
+
|
|
144
|
+
// The size of this nested message is calculated once, when the field is entered,
|
|
145
|
+
// and kept in the state. Resuming after a full buffer reuses it instead of
|
|
146
|
+
// walking the whole subtree again for every chunk. Whether the field is emitted
|
|
147
|
+
// at all is decided here as well, so no later phase depends on the stored size.
|
|
148
|
+
if(::EmbeddedProto::FieldProcessingPhase::TAG == state.phase)
|
|
149
|
+
{
|
|
150
|
+
state.size_value = serialized_size();
|
|
151
|
+
|
|
152
|
+
// Skip serializing empty fields for non-optional fields (proto3 default behavior)
|
|
153
|
+
if((!optional) && (0U == state.size_value))
|
|
154
|
+
{
|
|
155
|
+
state.phase = ::EmbeddedProto::FieldProcessingPhase::COMPLETE;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
// Handle TAG and SIZE phases using helper method
|
|
160
|
+
if((::EmbeddedProto::FieldProcessingPhase::TAG == state.phase) || (::EmbeddedProto::FieldProcessingPhase::SIZE == state.phase))
|
|
161
|
+
{
|
|
162
|
+
return_value = serialize_partial_tag_and_size(field_number, state.size_value, buffer, state, optional);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
// A zero sized field never reaches the data phase, serialize_partial_tag_and_size()
|
|
166
|
+
// marks it complete, so the size no longer has to be checked here.
|
|
167
|
+
if(::EmbeddedProto::FieldProcessingPhase::DATA == state.phase)
|
|
168
|
+
{
|
|
169
|
+
if(nullptr != state.child)
|
|
170
|
+
{
|
|
171
|
+
return_value = this->serialize_partial(buffer, *state.child);
|
|
172
|
+
if((Error::NO_ERRORS == return_value) && (::EmbeddedProto::FieldProcessingPhase::COMPLETE == state.child->phase))
|
|
173
|
+
{
|
|
174
|
+
state.bytes_remaining = 0U;
|
|
175
|
+
state.phase = ::EmbeddedProto::FieldProcessingPhase::COMPLETE;
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
else
|
|
179
|
+
{
|
|
180
|
+
return_value = Error::NESTING_TOO_DEEP;
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
return return_value;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
//! Serialize this message as a delimited group with partial state support.
|
|
188
|
+
/*!
|
|
189
|
+
DELIMITED (group) framing has no length prefix, so there is no SIZE phase.
|
|
190
|
+
The phases used are TAG (write START_GROUP) -> DATA (stream the child) ->
|
|
191
|
+
SIZE (reused to write END_GROUP) -> COMPLETE. Each tag is written
|
|
192
|
+
atomically; on a full buffer the phase is left unchanged so the call
|
|
193
|
+
resumes from the same point with a fresh buffer.
|
|
194
|
+
|
|
195
|
+
\param field_number The field number for the START/END group tags.
|
|
196
|
+
\param buffer The (possibly small) write buffer.
|
|
197
|
+
\param state The state for this group field; state.child streams the body.
|
|
198
|
+
\return Error::NO_ERRORS when complete, Error::BUFFER_FULL to resume.
|
|
199
|
+
*/
|
|
200
|
+
Error serialize_partial_as_group(uint32_t field_number,
|
|
201
|
+
WriteBufferInterface& buffer,
|
|
202
|
+
MessageState& state) const
|
|
203
|
+
{
|
|
204
|
+
Error return_value = Error::NO_ERRORS;
|
|
205
|
+
|
|
206
|
+
// Phase TAG: write the START_GROUP tag.
|
|
207
|
+
if(::EmbeddedProto::FieldProcessingPhase::TAG == state.phase)
|
|
208
|
+
{
|
|
209
|
+
const uint32_t tag = WireFormatter::MakeTag(field_number, WireFormatter::WireType::START_GROUP);
|
|
210
|
+
if(buffer.get_available_size() >= WireFormatter::VarintSize(tag))
|
|
211
|
+
{
|
|
212
|
+
return_value = WireFormatter::SerializeVarint(tag, buffer);
|
|
213
|
+
if(Error::NO_ERRORS == return_value)
|
|
214
|
+
{
|
|
215
|
+
state.phase = ::EmbeddedProto::FieldProcessingPhase::DATA;
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
else
|
|
219
|
+
{
|
|
220
|
+
return_value = Error::BUFFER_FULL;
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
// Phase DATA: stream the child message's fields.
|
|
225
|
+
if((Error::NO_ERRORS == return_value) && (::EmbeddedProto::FieldProcessingPhase::DATA == state.phase))
|
|
226
|
+
{
|
|
227
|
+
if(nullptr != state.child)
|
|
228
|
+
{
|
|
229
|
+
return_value = this->serialize_partial(buffer, *state.child);
|
|
230
|
+
if((Error::NO_ERRORS == return_value) && (::EmbeddedProto::FieldProcessingPhase::COMPLETE == state.child->phase))
|
|
231
|
+
{
|
|
232
|
+
// Body complete; the END_GROUP tag still has to be written. Reuse the
|
|
233
|
+
// (otherwise unused) SIZE phase to mark "END_GROUP pending".
|
|
234
|
+
state.phase = ::EmbeddedProto::FieldProcessingPhase::SIZE;
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
else
|
|
238
|
+
{
|
|
239
|
+
return_value = Error::NESTING_TOO_DEEP;
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
// Phase SIZE (reused): write the END_GROUP tag.
|
|
244
|
+
if((Error::NO_ERRORS == return_value) && (::EmbeddedProto::FieldProcessingPhase::SIZE == state.phase))
|
|
245
|
+
{
|
|
246
|
+
const uint32_t tag = WireFormatter::MakeTag(field_number, WireFormatter::WireType::END_GROUP);
|
|
247
|
+
if(buffer.get_available_size() >= WireFormatter::VarintSize(tag))
|
|
248
|
+
{
|
|
249
|
+
return_value = WireFormatter::SerializeVarint(tag, buffer);
|
|
250
|
+
if(Error::NO_ERRORS == return_value)
|
|
251
|
+
{
|
|
252
|
+
state.bytes_remaining = 0U;
|
|
253
|
+
state.phase = ::EmbeddedProto::FieldProcessingPhase::COMPLETE;
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
else
|
|
257
|
+
{
|
|
258
|
+
return_value = Error::BUFFER_FULL;
|
|
259
|
+
}
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
return return_value;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
//! Deserialize a length-delimited nested message field with partial state support.
|
|
266
|
+
/*!
|
|
267
|
+
Unlike a top-level message the nested message has a known size. Once the declared
|
|
268
|
+
number of bytes has been consumed the nested Error::END_OF_BUFFER is mapped to
|
|
269
|
+
Error::NO_ERRORS and this field is marked COMPLETE. Error::END_OF_BUFFER from this
|
|
270
|
+
function therefore always means more data is needed.
|
|
271
|
+
|
|
272
|
+
\see Field::deserialize_partial_as_field()
|
|
273
|
+
*/
|
|
274
|
+
Error deserialize_partial_as_field(ReadBufferInterface& buffer,
|
|
275
|
+
MessageState& state) override;
|
|
276
|
+
|
|
277
|
+
//! Deserialize a delimited (group) message field with partial state support.
|
|
278
|
+
/*!
|
|
279
|
+
The opening START_GROUP tag has been consumed by the caller (phase DATA).
|
|
280
|
+
The child is streamed until it consumes its matching END_GROUP, at which
|
|
281
|
+
point the child returns Error::NO_ERRORS with phase COMPLETE and this field
|
|
282
|
+
is marked COMPLETE. Error::END_OF_BUFFER means more data is needed.
|
|
283
|
+
*/
|
|
284
|
+
Error deserialize_partial_as_group(ReadBufferInterface& buffer,
|
|
285
|
+
MessageState& state);
|
|
286
|
+
|
|
287
|
+
//! When partially deserializing skip bytes in the buffer of an unknown field.
|
|
288
|
+
Error skip_unknown_field_partial(::EmbeddedProto::ReadBufferInterface& buffer,
|
|
289
|
+
MessageState& state) const;
|
|
290
|
+
|
|
291
|
+
//! When partially deserializing skip an unknown DELIMITED (group) field.
|
|
292
|
+
/*!
|
|
293
|
+
The START_GROUP tag has been consumed by the caller (phase DATA). The fields
|
|
294
|
+
inside the group are skipped one at a time until the matching END_GROUP tag is
|
|
295
|
+
consumed, at which point the phase is COMPLETE. Nested groups are counted, not
|
|
296
|
+
recursed into, so the skip takes no level of the state stack. The progress is
|
|
297
|
+
kept in the otherwise unused members of the group state itself, see
|
|
298
|
+
SKIP_GROUP_WIRE_TYPE_SHIFT. Returns END_OF_BUFFER when the buffer runs out
|
|
299
|
+
inside the group, to be resumed with the next buffer.
|
|
300
|
+
*/
|
|
301
|
+
Error skip_group_partial(::EmbeddedProto::ReadBufferInterface& buffer,
|
|
302
|
+
MessageState& state) const;
|
|
303
|
+
#endif
|
|
304
|
+
|
|
305
|
+
protected:
|
|
306
|
+
//! When deserializing skip the bytes in the buffer of an unknown field.
|
|
307
|
+
/*!
|
|
308
|
+
This function is used when a field with an unknown id is encountered to move through the
|
|
309
|
+
buffer to the next tag.
|
|
310
|
+
*/
|
|
311
|
+
Error skip_unknown_field(::EmbeddedProto::ReadBufferInterface& buffer,
|
|
312
|
+
const ::EmbeddedProto::WireFormatter::WireType& wire_type) const;
|
|
313
|
+
|
|
314
|
+
Error skip_varint(::EmbeddedProto::ReadBufferInterface& buffer) const;
|
|
315
|
+
Error skip_fixed32(::EmbeddedProto::ReadBufferInterface& buffer) const;
|
|
316
|
+
Error skip_fixed64(::EmbeddedProto::ReadBufferInterface& buffer) const;
|
|
317
|
+
Error skip_length_delimited(::EmbeddedProto::ReadBufferInterface& buffer) const;
|
|
318
|
+
|
|
319
|
+
//! Skip an unknown DELIMITED (group) field up to its matching END_GROUP.
|
|
320
|
+
Error skip_group(::EmbeddedProto::ReadBufferInterface& buffer) const;
|
|
321
|
+
|
|
322
|
+
#ifdef PARTIAL_SERIALIZATION_ENABLED
|
|
323
|
+
//! Layout of the group state while skipping an unknown DELIMITED (group) field.
|
|
324
|
+
/*!
|
|
325
|
+
The state of the unknown field keeps wire_type START_GROUP and phase DATA, which
|
|
326
|
+
routes it into skip_group_partial(). The members a group has no other use for
|
|
327
|
+
track the field currently being skipped inside the group:
|
|
328
|
+
- element_index holds the nesting depth of groups inside the unknown group,
|
|
329
|
+
- bytes_remaining holds the bytes still to skip of the inner field,
|
|
330
|
+
- size_value holds the wire type and phase of the inner field, packed as
|
|
331
|
+
(wire_type << SKIP_GROUP_WIRE_TYPE_SHIFT) | phase.
|
|
332
|
+
The initial size_value of zero decodes to phase TAG, the first inner tag.
|
|
333
|
+
*/
|
|
334
|
+
static constexpr uint32_t SKIP_GROUP_WIRE_TYPE_SHIFT = 8U;
|
|
335
|
+
|
|
336
|
+
//! Mask of one packed inner field of the size_value, see SKIP_GROUP_WIRE_TYPE_SHIFT.
|
|
337
|
+
static constexpr uint32_t SKIP_GROUP_FIELD_MASK = 0xFFU;
|
|
338
|
+
|
|
339
|
+
//! Pack the wire type and phase of the inner field into size_value.
|
|
340
|
+
static constexpr uint32_t pack_skip_group_field(const WireFormatter::WireType wire_type,
|
|
341
|
+
const FieldProcessingPhase phase)
|
|
342
|
+
{
|
|
343
|
+
return (static_cast<uint32_t>(wire_type) << SKIP_GROUP_WIRE_TYPE_SHIFT)
|
|
344
|
+
| static_cast<uint32_t>(phase);
|
|
345
|
+
}
|
|
346
|
+
|
|
347
|
+
//! Unpack the wire type of the inner field from size_value.
|
|
348
|
+
static constexpr WireFormatter::WireType skip_group_field_wire_type(const uint32_t size_value)
|
|
349
|
+
{
|
|
350
|
+
return static_cast<WireFormatter::WireType>((size_value >> SKIP_GROUP_WIRE_TYPE_SHIFT)
|
|
351
|
+
& SKIP_GROUP_FIELD_MASK);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
//! Unpack the phase of the inner field from size_value.
|
|
355
|
+
static constexpr FieldProcessingPhase skip_group_field_phase(const uint32_t size_value)
|
|
356
|
+
{
|
|
357
|
+
return static_cast<FieldProcessingPhase>(size_value & SKIP_GROUP_FIELD_MASK);
|
|
358
|
+
}
|
|
359
|
+
#endif
|
|
360
|
+
|
|
361
|
+
};
|
|
362
|
+
|
|
363
|
+
|
|
364
|
+
// Definitions of the member functions declared above. The library is header only, so they are
|
|
365
|
+
// inline.
|
|
366
|
+
|
|
367
|
+
inline Error MessageInterface::deserialize_check_type(::EmbeddedProto::ReadBufferInterface& buffer,
|
|
368
|
+
const ::EmbeddedProto::WireFormatter::WireType& wire_type)
|
|
369
|
+
{
|
|
370
|
+
Error return_value = ::EmbeddedProto::WireFormatter::WireType::LENGTH_DELIMITED == wire_type
|
|
371
|
+
? Error::NO_ERRORS : Error::INVALID_WIRETYPE;
|
|
372
|
+
if(Error::NO_ERRORS == return_value)
|
|
373
|
+
{
|
|
374
|
+
uint32_t size = 0;
|
|
375
|
+
return_value = ::EmbeddedProto::WireFormatter::DeserializeVarint(buffer, size);
|
|
376
|
+
::EmbeddedProto::ReadBufferSection bufferSection(buffer, size);
|
|
377
|
+
if(::EmbeddedProto::Error::NO_ERRORS == return_value)
|
|
378
|
+
{
|
|
379
|
+
return_value = deserialize(bufferSection);
|
|
380
|
+
if((Error::END_OF_BUFFER == return_value) && (0U == size))
|
|
381
|
+
{
|
|
382
|
+
// A size of zero is a valid empty message (all fields default). The nested
|
|
383
|
+
// deserialize finds no tag in the empty section and reports END_OF_BUFFER,
|
|
384
|
+
// which is the expected clean end here and not a truncated message.
|
|
385
|
+
return_value = Error::NO_ERRORS;
|
|
386
|
+
}
|
|
387
|
+
else if((Error::NO_ERRORS == return_value) && (0U != bufferSection.get_size()))
|
|
388
|
+
{
|
|
389
|
+
// The nested deserialize only stops before the end of its section after
|
|
390
|
+
// consuming an END_GROUP tag. That tag closes group framing and is malformed
|
|
391
|
+
// inside a length-delimited field. Accepting it would leave the rest of the
|
|
392
|
+
// section to be read as fields of this message.
|
|
393
|
+
return_value = Error::INVALID_WIRETYPE;
|
|
394
|
+
}
|
|
395
|
+
else
|
|
396
|
+
{
|
|
397
|
+
// Any other result is passed on as is.
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
return return_value;
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
#ifdef PARTIAL_SERIALIZATION_ENABLED
|
|
405
|
+
inline Error MessageInterface::deserialize_partial_as_field(::EmbeddedProto::ReadBufferInterface& buffer,
|
|
406
|
+
MessageState& state)
|
|
407
|
+
{
|
|
408
|
+
Error return_value = Error::NO_ERRORS;
|
|
409
|
+
|
|
410
|
+
if(::EmbeddedProto::FieldProcessingPhase::SIZE == state.phase)
|
|
411
|
+
{
|
|
412
|
+
return_value = deserialize_partial_size_phase(buffer, state);
|
|
413
|
+
}
|
|
414
|
+
|
|
415
|
+
if((Error::NO_ERRORS == return_value) && (::EmbeddedProto::FieldProcessingPhase::DATA == state.phase))
|
|
416
|
+
{
|
|
417
|
+
if(nullptr != state.child)
|
|
418
|
+
{
|
|
419
|
+
// The section is clamped to what is currently in the buffer, which may be
|
|
420
|
+
// less than the declared nested message size. Track progress against the
|
|
421
|
+
// declared size using the number of bytes actually consumed.
|
|
422
|
+
::EmbeddedProto::ReadBufferSection section(buffer, state.bytes_remaining);
|
|
423
|
+
const uint32_t section_size_before = section.get_max_size();
|
|
424
|
+
return_value = this->deserialize_partial(section, *state.child);
|
|
425
|
+
const uint32_t bytes_consumed = section_size_before - section.get_size();
|
|
426
|
+
state.bytes_remaining -= bytes_consumed;
|
|
427
|
+
|
|
428
|
+
if((Error::NO_ERRORS == return_value)
|
|
429
|
+
&& (::EmbeddedProto::FieldProcessingPhase::COMPLETE == state.child->phase))
|
|
430
|
+
{
|
|
431
|
+
// The child only returns NO_ERRORS in the COMPLETE phase after consuming an
|
|
432
|
+
// END_GROUP tag. That tag closes group framing, which is handled by
|
|
433
|
+
// deserialize_partial_as_group. Inside a length-delimited field it is
|
|
434
|
+
// malformed input, accepting it would end the nested message early with
|
|
435
|
+
// bytes of the section left unread.
|
|
436
|
+
return_value = Error::INVALID_WIRETYPE;
|
|
437
|
+
}
|
|
438
|
+
|
|
439
|
+
if(0U == state.bytes_remaining)
|
|
440
|
+
{
|
|
441
|
+
// The whole nested message has been consumed. The child reports
|
|
442
|
+
// END_OF_BUFFER once its bounded section runs out; for a fully received
|
|
443
|
+
// nested message that simply means it is complete.
|
|
444
|
+
if(Error::END_OF_BUFFER == return_value)
|
|
445
|
+
{
|
|
446
|
+
return_value = Error::NO_ERRORS;
|
|
447
|
+
}
|
|
448
|
+
if(Error::NO_ERRORS == return_value)
|
|
449
|
+
{
|
|
450
|
+
state.phase = ::EmbeddedProto::FieldProcessingPhase::COMPLETE;
|
|
451
|
+
state.child->reset();
|
|
452
|
+
}
|
|
453
|
+
}
|
|
454
|
+
}
|
|
455
|
+
else
|
|
456
|
+
{
|
|
457
|
+
return_value = Error::NESTING_TOO_DEEP;
|
|
458
|
+
}
|
|
459
|
+
}
|
|
460
|
+
|
|
461
|
+
return return_value;
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
inline Error MessageInterface::deserialize_partial_as_group(::EmbeddedProto::ReadBufferInterface& buffer,
|
|
465
|
+
MessageState& state)
|
|
466
|
+
{
|
|
467
|
+
Error return_value = Error::NO_ERRORS;
|
|
468
|
+
|
|
469
|
+
// Groups have no SIZE phase. The caller consumed the START_GROUP tag and set
|
|
470
|
+
// the phase to DATA.
|
|
471
|
+
if(::EmbeddedProto::FieldProcessingPhase::DATA == state.phase)
|
|
472
|
+
{
|
|
473
|
+
if(nullptr != state.child)
|
|
474
|
+
{
|
|
475
|
+
// Stream the child's fields directly from the buffer. The child's partial
|
|
476
|
+
// deserialize stops (reporting completion) when it consumes its matching
|
|
477
|
+
// END_GROUP; otherwise it returns END_OF_BUFFER to resume later with the
|
|
478
|
+
// child state preserved.
|
|
479
|
+
return_value = this->deserialize_partial(buffer, *state.child);
|
|
480
|
+
if((Error::NO_ERRORS == return_value)
|
|
481
|
+
&& (::EmbeddedProto::FieldProcessingPhase::COMPLETE == state.child->phase))
|
|
482
|
+
{
|
|
483
|
+
state.phase = ::EmbeddedProto::FieldProcessingPhase::COMPLETE;
|
|
484
|
+
state.child->reset();
|
|
485
|
+
}
|
|
486
|
+
}
|
|
487
|
+
else
|
|
488
|
+
{
|
|
489
|
+
return_value = Error::NESTING_TOO_DEEP;
|
|
490
|
+
}
|
|
491
|
+
}
|
|
492
|
+
|
|
493
|
+
return return_value;
|
|
494
|
+
}
|
|
495
|
+
|
|
496
|
+
inline Error MessageInterface::skip_unknown_field_partial(::EmbeddedProto::ReadBufferInterface& buffer,
|
|
497
|
+
MessageState& state) const
|
|
498
|
+
{
|
|
499
|
+
Error return_value = Error::STATE_MISMATCH;
|
|
500
|
+
|
|
501
|
+
if(::EmbeddedProto::WireFormatter::WireType::VARINT == state.wire_type)
|
|
502
|
+
{
|
|
503
|
+
if(::EmbeddedProto::FieldProcessingPhase::DATA == state.phase)
|
|
504
|
+
{
|
|
505
|
+
return_value = skip_varint(buffer);
|
|
506
|
+
if(Error::NO_ERRORS == return_value)
|
|
507
|
+
{
|
|
508
|
+
state.phase = ::EmbeddedProto::FieldProcessingPhase::COMPLETE;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
}
|
|
512
|
+
else if(::EmbeddedProto::WireFormatter::WireType::FIXED32 == state.wire_type)
|
|
513
|
+
{
|
|
514
|
+
if(::EmbeddedProto::FieldProcessingPhase::DATA == state.phase)
|
|
515
|
+
{
|
|
516
|
+
if(0U == state.bytes_remaining)
|
|
517
|
+
{
|
|
518
|
+
state.bytes_remaining = 4U;
|
|
519
|
+
}
|
|
520
|
+
|
|
521
|
+
const uint32_t bytes_to_advance = (state.bytes_remaining < buffer.get_size())
|
|
522
|
+
? state.bytes_remaining
|
|
523
|
+
: buffer.get_size();
|
|
524
|
+
|
|
525
|
+
buffer.advance(bytes_to_advance);
|
|
526
|
+
state.bytes_remaining -= bytes_to_advance;
|
|
527
|
+
|
|
528
|
+
if(0U == state.bytes_remaining)
|
|
529
|
+
{
|
|
530
|
+
state.phase = ::EmbeddedProto::FieldProcessingPhase::COMPLETE;
|
|
531
|
+
return_value = Error::NO_ERRORS;
|
|
532
|
+
}
|
|
533
|
+
else
|
|
534
|
+
{
|
|
535
|
+
return_value = Error::END_OF_BUFFER;
|
|
536
|
+
}
|
|
537
|
+
}
|
|
538
|
+
}
|
|
539
|
+
else if(::EmbeddedProto::WireFormatter::WireType::FIXED64 == state.wire_type)
|
|
540
|
+
{
|
|
541
|
+
if(::EmbeddedProto::FieldProcessingPhase::DATA == state.phase)
|
|
542
|
+
{
|
|
543
|
+
if(0U == state.bytes_remaining)
|
|
544
|
+
{
|
|
545
|
+
state.bytes_remaining = 8U;
|
|
546
|
+
}
|
|
547
|
+
|
|
548
|
+
const uint32_t bytes_to_advance = (state.bytes_remaining < buffer.get_size())
|
|
549
|
+
? state.bytes_remaining
|
|
550
|
+
: buffer.get_size();
|
|
551
|
+
|
|
552
|
+
buffer.advance(bytes_to_advance);
|
|
553
|
+
state.bytes_remaining -= bytes_to_advance;
|
|
554
|
+
|
|
555
|
+
if(0U == state.bytes_remaining)
|
|
556
|
+
{
|
|
557
|
+
state.phase = ::EmbeddedProto::FieldProcessingPhase::COMPLETE;
|
|
558
|
+
return_value = Error::NO_ERRORS;
|
|
559
|
+
}
|
|
560
|
+
else
|
|
561
|
+
{
|
|
562
|
+
return_value = Error::END_OF_BUFFER;
|
|
563
|
+
}
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
else if(::EmbeddedProto::WireFormatter::WireType::LENGTH_DELIMITED == state.wire_type)
|
|
567
|
+
{
|
|
568
|
+
return_value = Error::NO_ERRORS;
|
|
569
|
+
|
|
570
|
+
if(::EmbeddedProto::FieldProcessingPhase::SIZE == state.phase)
|
|
571
|
+
{
|
|
572
|
+
return_value = deserialize_partial_size_phase(buffer, state);
|
|
573
|
+
}
|
|
574
|
+
|
|
575
|
+
if((Error::NO_ERRORS == return_value) && (::EmbeddedProto::FieldProcessingPhase::DATA == state.phase))
|
|
576
|
+
{
|
|
577
|
+
const uint32_t bytes_to_advance = (state.bytes_remaining < buffer.get_size())
|
|
578
|
+
? state.bytes_remaining
|
|
579
|
+
: buffer.get_size();
|
|
580
|
+
|
|
581
|
+
buffer.advance(bytes_to_advance);
|
|
582
|
+
state.bytes_remaining -= bytes_to_advance;
|
|
583
|
+
|
|
584
|
+
if(0U == state.bytes_remaining)
|
|
585
|
+
{
|
|
586
|
+
state.phase = ::EmbeddedProto::FieldProcessingPhase::COMPLETE;
|
|
587
|
+
return_value = Error::NO_ERRORS;
|
|
588
|
+
}
|
|
589
|
+
else
|
|
590
|
+
{
|
|
591
|
+
return_value = Error::END_OF_BUFFER;
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
else if(::EmbeddedProto::WireFormatter::WireType::START_GROUP == state.wire_type)
|
|
596
|
+
{
|
|
597
|
+
// An unknown DELIMITED field: skip the whole group up to its END_GROUP.
|
|
598
|
+
if(::EmbeddedProto::FieldProcessingPhase::DATA == state.phase)
|
|
599
|
+
{
|
|
600
|
+
return_value = skip_group_partial(buffer, state);
|
|
601
|
+
}
|
|
602
|
+
}
|
|
603
|
+
|
|
604
|
+
return return_value;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
inline Error MessageInterface::skip_group_partial(::EmbeddedProto::ReadBufferInterface& buffer,
|
|
608
|
+
MessageState& state) const
|
|
609
|
+
{
|
|
610
|
+
Error return_value = Error::NO_ERRORS;
|
|
611
|
+
|
|
612
|
+
// The field inside the group currently being skipped, restored from the members of
|
|
613
|
+
// the group state, see SKIP_GROUP_WIRE_TYPE_SHIFT. It is cleared after every field,
|
|
614
|
+
// so a resume always continues where the previous buffer ran out: at the next tag
|
|
615
|
+
// or inside a field value.
|
|
616
|
+
MessageState field;
|
|
617
|
+
field.wire_type = skip_group_field_wire_type(state.size_value);
|
|
618
|
+
field.phase = skip_group_field_phase(state.size_value);
|
|
619
|
+
field.bytes_remaining = state.bytes_remaining;
|
|
620
|
+
|
|
621
|
+
bool continue_skipping = true;
|
|
622
|
+
while(continue_skipping)
|
|
623
|
+
{
|
|
624
|
+
if(::EmbeddedProto::FieldProcessingPhase::TAG == field.phase)
|
|
625
|
+
{
|
|
626
|
+
return_value = ::EmbeddedProto::WireFormatter::DeserializeTag(buffer, field.wire_type,
|
|
627
|
+
field.field_id);
|
|
628
|
+
if(Error::NO_ERRORS == return_value)
|
|
629
|
+
{
|
|
630
|
+
if(::EmbeddedProto::WireFormatter::WireType::START_GROUP == field.wire_type)
|
|
631
|
+
{
|
|
632
|
+
// A nested group, count it and go on with the tags inside it.
|
|
633
|
+
++state.element_index;
|
|
634
|
+
}
|
|
635
|
+
else if(::EmbeddedProto::WireFormatter::WireType::END_GROUP == field.wire_type)
|
|
636
|
+
{
|
|
637
|
+
if(0U == state.element_index)
|
|
638
|
+
{
|
|
639
|
+
// The END_GROUP matching the unknown field, the skip is complete.
|
|
640
|
+
state.phase = ::EmbeddedProto::FieldProcessingPhase::COMPLETE;
|
|
641
|
+
continue_skipping = false;
|
|
642
|
+
}
|
|
643
|
+
else
|
|
644
|
+
{
|
|
645
|
+
// The END_GROUP of a nested group.
|
|
646
|
+
--state.element_index;
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
else
|
|
650
|
+
{
|
|
651
|
+
field.phase = (::EmbeddedProto::WireFormatter::WireType::LENGTH_DELIMITED == field.wire_type)
|
|
652
|
+
? ::EmbeddedProto::FieldProcessingPhase::SIZE
|
|
653
|
+
: ::EmbeddedProto::FieldProcessingPhase::DATA;
|
|
654
|
+
}
|
|
655
|
+
}
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
if(continue_skipping && (Error::NO_ERRORS == return_value)
|
|
659
|
+
&& (::EmbeddedProto::FieldProcessingPhase::TAG != field.phase))
|
|
660
|
+
{
|
|
661
|
+
return_value = skip_unknown_field_partial(buffer, field);
|
|
662
|
+
if((Error::NO_ERRORS == return_value)
|
|
663
|
+
&& (::EmbeddedProto::FieldProcessingPhase::COMPLETE == field.phase))
|
|
664
|
+
{
|
|
665
|
+
field.reset();
|
|
666
|
+
}
|
|
667
|
+
}
|
|
668
|
+
|
|
669
|
+
if(Error::NO_ERRORS != return_value)
|
|
670
|
+
{
|
|
671
|
+
continue_skipping = false;
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
// Store the inner field for the next buffer, or clear it when the group is complete.
|
|
676
|
+
if(::EmbeddedProto::FieldProcessingPhase::COMPLETE == state.phase)
|
|
677
|
+
{
|
|
678
|
+
state.size_value = 0U;
|
|
679
|
+
state.bytes_remaining = 0U;
|
|
680
|
+
state.element_index = 0U;
|
|
681
|
+
}
|
|
682
|
+
else
|
|
683
|
+
{
|
|
684
|
+
state.size_value = pack_skip_group_field(field.wire_type, field.phase);
|
|
685
|
+
state.bytes_remaining = field.bytes_remaining;
|
|
686
|
+
}
|
|
687
|
+
|
|
688
|
+
return return_value;
|
|
689
|
+
}
|
|
690
|
+
#endif
|
|
691
|
+
|
|
692
|
+
|
|
693
|
+
inline Error MessageInterface::skip_unknown_field(::EmbeddedProto::ReadBufferInterface& buffer,
|
|
694
|
+
const ::EmbeddedProto::WireFormatter::WireType& wire_type) const
|
|
695
|
+
{
|
|
696
|
+
Error return_value = Error::NO_ERRORS;
|
|
697
|
+
|
|
698
|
+
// Depending on the wire type select one of its valid variable types and deserialize the value.
|
|
699
|
+
switch(wire_type) {
|
|
700
|
+
case ::EmbeddedProto::WireFormatter::WireType::VARINT:
|
|
701
|
+
return_value = skip_varint(buffer);
|
|
702
|
+
break;
|
|
703
|
+
|
|
704
|
+
case ::EmbeddedProto::WireFormatter::WireType::FIXED64:
|
|
705
|
+
return_value = skip_fixed64(buffer);
|
|
706
|
+
break;
|
|
707
|
+
|
|
708
|
+
case ::EmbeddedProto::WireFormatter::WireType::LENGTH_DELIMITED:
|
|
709
|
+
return_value = skip_length_delimited(buffer);
|
|
710
|
+
break;
|
|
711
|
+
|
|
712
|
+
case ::EmbeddedProto::WireFormatter::WireType::FIXED32:
|
|
713
|
+
return_value = skip_fixed32(buffer);
|
|
714
|
+
break;
|
|
715
|
+
|
|
716
|
+
case ::EmbeddedProto::WireFormatter::WireType::START_GROUP:
|
|
717
|
+
// An unknown DELIMITED field: skip the whole group up to its END_GROUP.
|
|
718
|
+
return_value = skip_group(buffer);
|
|
719
|
+
break;
|
|
720
|
+
|
|
721
|
+
default:
|
|
722
|
+
// We should never get here. DeserializeTag catches this case.
|
|
723
|
+
break;
|
|
724
|
+
}
|
|
725
|
+
|
|
726
|
+
return return_value;
|
|
727
|
+
}
|
|
728
|
+
|
|
729
|
+
inline Error MessageInterface::skip_group(::EmbeddedProto::ReadBufferInterface& buffer) const
|
|
730
|
+
{
|
|
731
|
+
// The opening START_GROUP tag has already been consumed. Read and discard
|
|
732
|
+
// fields until the matching END_GROUP. Nested groups are skipped recursively
|
|
733
|
+
// (skip_unknown_field routes START_GROUP back here), so the first END_GROUP
|
|
734
|
+
// seen at this level is the matching one.
|
|
735
|
+
Error return_value = Error::NO_ERRORS;
|
|
736
|
+
bool done = false;
|
|
737
|
+
while((!done) && (Error::NO_ERRORS == return_value))
|
|
738
|
+
{
|
|
739
|
+
::EmbeddedProto::WireFormatter::WireType wire_type;
|
|
740
|
+
uint32_t id = 0;
|
|
741
|
+
return_value = ::EmbeddedProto::WireFormatter::DeserializeTag(buffer, wire_type, id);
|
|
742
|
+
if(Error::NO_ERRORS == return_value)
|
|
743
|
+
{
|
|
744
|
+
if(::EmbeddedProto::WireFormatter::WireType::END_GROUP == wire_type)
|
|
745
|
+
{
|
|
746
|
+
done = true;
|
|
747
|
+
}
|
|
748
|
+
else
|
|
749
|
+
{
|
|
750
|
+
return_value = skip_unknown_field(buffer, wire_type);
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
return return_value;
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
|
|
758
|
+
inline Error MessageInterface::skip_varint(::EmbeddedProto::ReadBufferInterface& buffer) const
|
|
759
|
+
{
|
|
760
|
+
// Use a 64 bit variable to decode the maximum possible number of bytes. As we do not know
|
|
761
|
+
// the actual type.
|
|
762
|
+
uint64_t dummy;
|
|
763
|
+
return ::EmbeddedProto::WireFormatter::DeserializeVarint(buffer, dummy);
|
|
764
|
+
}
|
|
765
|
+
|
|
766
|
+
inline Error MessageInterface::skip_fixed32(::EmbeddedProto::ReadBufferInterface& buffer) const
|
|
767
|
+
{
|
|
768
|
+
float dummy;
|
|
769
|
+
return ::EmbeddedProto::WireFormatter::DeserializeFloat(buffer, dummy);
|
|
770
|
+
}
|
|
771
|
+
|
|
772
|
+
inline Error MessageInterface::skip_fixed64(::EmbeddedProto::ReadBufferInterface& buffer) const
|
|
773
|
+
{
|
|
774
|
+
double dummy;
|
|
775
|
+
return ::EmbeddedProto::WireFormatter::DeserializeDouble(buffer, dummy);
|
|
776
|
+
}
|
|
777
|
+
|
|
778
|
+
inline Error MessageInterface::skip_length_delimited(::EmbeddedProto::ReadBufferInterface& buffer) const
|
|
779
|
+
{
|
|
780
|
+
// First read the number of bytes
|
|
781
|
+
uint32_t n_bytes = 0;
|
|
782
|
+
const Error return_value = ::EmbeddedProto::WireFormatter::DeserializeVarint(buffer, n_bytes);
|
|
783
|
+
if(Error::NO_ERRORS == return_value)
|
|
784
|
+
{
|
|
785
|
+
buffer.advance(n_bytes);
|
|
786
|
+
}
|
|
787
|
+
return return_value;
|
|
788
|
+
}
|
|
789
|
+
|
|
790
|
+
} // End of namespace EmbeddedProto
|
|
791
|
+
|
|
792
|
+
#endif // _MESSAGE_INTERFACE_H_
|