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,432 @@
|
|
|
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 _REPEATED_FIELD_CALLBACK_H_
|
|
25
|
+
#define _REPEATED_FIELD_CALLBACK_H_
|
|
26
|
+
|
|
27
|
+
#include "RepeatedField.h"
|
|
28
|
+
#include "Functional.h"
|
|
29
|
+
#include "Errors.h"
|
|
30
|
+
|
|
31
|
+
#include <cstdint>
|
|
32
|
+
|
|
33
|
+
|
|
34
|
+
namespace EmbeddedProto
|
|
35
|
+
{
|
|
36
|
+
|
|
37
|
+
//! A repeated field whose elements are streamed to/from the user, not stored.
|
|
38
|
+
/*!
|
|
39
|
+
RepeatedFieldCallback is a drop-in storage type for a repeated scalar field
|
|
40
|
+
that owns no element buffer. Instead of holding an array it forwards each
|
|
41
|
+
element across the interface seam:
|
|
42
|
+
|
|
43
|
+
- on deserialize, every parsed element is pushed to a user *sink*;
|
|
44
|
+
- on serialize, elements are pulled one by one from a user *source*.
|
|
45
|
+
|
|
46
|
+
This lets a device stream arbitrarily many elements through a fixed, tiny
|
|
47
|
+
RAM footprint (just the two Functional handles plus a single transient
|
|
48
|
+
return slot required by the RepeatedField interface). It plugs in through
|
|
49
|
+
the existing customStorage mechanism: it derives from RepeatedField and
|
|
50
|
+
satisfies the same static_assert.
|
|
51
|
+
|
|
52
|
+
This skeleton implements the RepeatedField interface minimally; the
|
|
53
|
+
streaming behaviour is wired up in the following steps of the callback
|
|
54
|
+
storage plan (sink on deserialize, source on serialize, then partial /
|
|
55
|
+
resumable support).
|
|
56
|
+
|
|
57
|
+
\tparam DATA_TYPE The element field type (a FieldTemplate scalar such as
|
|
58
|
+
EmbeddedProto::int32).
|
|
59
|
+
*/
|
|
60
|
+
template<class DATA_TYPE>
|
|
61
|
+
class RepeatedFieldCallback : public RepeatedField<DATA_TYPE>
|
|
62
|
+
{
|
|
63
|
+
public:
|
|
64
|
+
|
|
65
|
+
//! Pull callback used during serialize: fill \p element, return true when a value was produced, false to signal the end of the stream.
|
|
66
|
+
using SourceCallback = Functional<bool(DATA_TYPE&)>;
|
|
67
|
+
|
|
68
|
+
//! Push callback used during deserialize: consume one parsed \p element, return an Error (NO_ERRORS to continue).
|
|
69
|
+
using SinkCallback = Functional<Error(const DATA_TYPE&)>;
|
|
70
|
+
|
|
71
|
+
RepeatedFieldCallback() = default;
|
|
72
|
+
~RepeatedFieldCallback() = default;
|
|
73
|
+
|
|
74
|
+
// --- Binding (reference-taking, no ownership) --------------------------
|
|
75
|
+
|
|
76
|
+
//! Bind the source used to pull elements during serialization.
|
|
77
|
+
void set_source(const SourceCallback& source) { source_ = source; }
|
|
78
|
+
|
|
79
|
+
//! Bind the sink used to push elements during deserialization.
|
|
80
|
+
void set_sink(const SinkCallback& sink) { sink_ = sink; }
|
|
81
|
+
|
|
82
|
+
//! Remove the bound source.
|
|
83
|
+
void clear_source() { source_.clear(); }
|
|
84
|
+
|
|
85
|
+
//! Remove the bound sink.
|
|
86
|
+
void clear_sink() { sink_.clear(); }
|
|
87
|
+
|
|
88
|
+
//! Check whether a source (pull) callback is bound.
|
|
89
|
+
bool is_source_set() const { return source_.is_set(); }
|
|
90
|
+
|
|
91
|
+
//! Check whether a sink (push) callback is bound.
|
|
92
|
+
bool is_sink_set() const { return sink_.is_set(); }
|
|
93
|
+
|
|
94
|
+
//! Require a binding for the direction being used.
|
|
95
|
+
/*!
|
|
96
|
+
When strict, streaming without the relevant callback bound returns
|
|
97
|
+
CALLBACK_NOT_SET instead of silently discarding (deserialize) or
|
|
98
|
+
emitting nothing (serialize).
|
|
99
|
+
*/
|
|
100
|
+
void set_strict(bool strict) { strict_ = strict; }
|
|
101
|
+
|
|
102
|
+
//! Whether strict (require-binding) mode is enabled.
|
|
103
|
+
bool is_strict() const { return strict_; }
|
|
104
|
+
|
|
105
|
+
// --- RepeatedField interface -------------------------------------------
|
|
106
|
+
|
|
107
|
+
//! Number of elements streamed so far (a running counter, not a capacity).
|
|
108
|
+
uint32_t get_length() const override { return length_; }
|
|
109
|
+
|
|
110
|
+
//! Streaming is effectively unbounded; report a large sentinel so the engine's "array full" checks never fire.
|
|
111
|
+
uint32_t get_max_length() const override { return UINT32_MAX; }
|
|
112
|
+
|
|
113
|
+
//! No elements are stored, so no bytes are resident.
|
|
114
|
+
uint32_t get_size() const override { return 0U; }
|
|
115
|
+
|
|
116
|
+
//! Streaming is effectively unbounded.
|
|
117
|
+
uint32_t get_max_size() const override { return UINT32_MAX; }
|
|
118
|
+
|
|
119
|
+
//! Required of a customStorage repeated type.
|
|
120
|
+
/*!
|
|
121
|
+
A stream has no finite serialized size, so report the unbounded sentinel
|
|
122
|
+
(consistent with get_max_length/get_max_size). A message with a callback field
|
|
123
|
+
therefore cannot be statically buffer-sized, which is inherent.
|
|
124
|
+
*/
|
|
125
|
+
static constexpr uint32_t max_serialized_size(const uint32_t field_number)
|
|
126
|
+
{
|
|
127
|
+
static_cast<void>(field_number);
|
|
128
|
+
return UINT32_MAX;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
//! Random access is unsupported; return the transient slot as a landing area for the engine (its contents are not retained).
|
|
132
|
+
DATA_TYPE& get(uint32_t index) override
|
|
133
|
+
{
|
|
134
|
+
static_cast<void>(index);
|
|
135
|
+
return transient_;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
//! Random access is unsupported; return the transient slot.
|
|
139
|
+
const DATA_TYPE& get_const(uint32_t index) const override
|
|
140
|
+
{
|
|
141
|
+
static_cast<void>(index);
|
|
142
|
+
return transient_;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
//! Random access is unsupported.
|
|
146
|
+
Error get_const(const uint32_t index, DATA_TYPE& value) const override
|
|
147
|
+
{
|
|
148
|
+
static_cast<void>(index);
|
|
149
|
+
static_cast<void>(value);
|
|
150
|
+
return Error::INDEX_OUT_OF_BOUND;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
//! Random access is unsupported; setting a specific index is a no-op.
|
|
154
|
+
void set(uint32_t index, const DATA_TYPE& value) override
|
|
155
|
+
{
|
|
156
|
+
static_cast<void>(index);
|
|
157
|
+
static_cast<void>(value);
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
//! Keep the pointer and length form of set_data() reachable next to the override below.
|
|
161
|
+
using RepeatedField<DATA_TYPE>::set_data;
|
|
162
|
+
|
|
163
|
+
//! Bulk assignment is unsupported for a streaming field.
|
|
164
|
+
Error set_data(const array_view<const DATA_TYPE>& data) override
|
|
165
|
+
{
|
|
166
|
+
static_cast<void>(data);
|
|
167
|
+
return Error::ARRAY_FULL;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
//! Append one element: push it to the bound sink instead of storing it.
|
|
171
|
+
/*!
|
|
172
|
+
Every parsed element funnels through here (the base packed-decode loop
|
|
173
|
+
calls the virtual add(), and the expanded path is routed here by the
|
|
174
|
+
deserialize_check_type override below). With a sink bound, the element
|
|
175
|
+
is forwarded and the sink's Error is propagated. With no sink bound the
|
|
176
|
+
element is drained and discarded (NO_ERRORS), unless strict mode is on,
|
|
177
|
+
in which case CALLBACK_NOT_SET is returned. The element counter is
|
|
178
|
+
advanced only for an element that was accepted.
|
|
179
|
+
*/
|
|
180
|
+
Error add(const DATA_TYPE& value) override
|
|
181
|
+
{
|
|
182
|
+
Error return_value = Error::NO_ERRORS;
|
|
183
|
+
if(sink_.is_set())
|
|
184
|
+
{
|
|
185
|
+
Error sink_result = Error::NO_ERRORS;
|
|
186
|
+
static_cast<void>(sink_.invoke(sink_result, value));
|
|
187
|
+
return_value = sink_result;
|
|
188
|
+
}
|
|
189
|
+
else if(strict_)
|
|
190
|
+
{
|
|
191
|
+
return_value = Error::CALLBACK_NOT_SET;
|
|
192
|
+
}
|
|
193
|
+
else
|
|
194
|
+
{
|
|
195
|
+
// No sink bound and not strict: drain and discard.
|
|
196
|
+
static_cast<void>(value);
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
if(Error::NO_ERRORS == return_value)
|
|
200
|
+
{
|
|
201
|
+
++length_;
|
|
202
|
+
}
|
|
203
|
+
return return_value;
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
//! Route deserialization through add() for both packed and expanded input.
|
|
207
|
+
/*!
|
|
208
|
+
Length-delimited (packed) input is handled by the base deserialize(),
|
|
209
|
+
whose element loop already calls the virtual add(). Expanded input
|
|
210
|
+
(one tag per element) would otherwise be routed to the random-access
|
|
211
|
+
get(index) slot this field lacks, so it is deserialized into a stack
|
|
212
|
+
local here and pushed through add() as well.
|
|
213
|
+
*/
|
|
214
|
+
Error deserialize_check_type(::EmbeddedProto::ReadBufferInterface& buffer,
|
|
215
|
+
const ::EmbeddedProto::WireFormatter::WireType& wire_type) override
|
|
216
|
+
{
|
|
217
|
+
Error return_value = Error::NO_ERRORS;
|
|
218
|
+
const bool is_length_delimited =
|
|
219
|
+
::EmbeddedProto::WireFormatter::WireType::LENGTH_DELIMITED == wire_type;
|
|
220
|
+
if(is_length_delimited)
|
|
221
|
+
{
|
|
222
|
+
return_value = this->deserialize(buffer);
|
|
223
|
+
}
|
|
224
|
+
else
|
|
225
|
+
{
|
|
226
|
+
DATA_TYPE element;
|
|
227
|
+
return_value = element.deserialize_check_type(buffer, wire_type);
|
|
228
|
+
if(Error::NO_ERRORS == return_value)
|
|
229
|
+
{
|
|
230
|
+
return_value = this->add(element);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
return return_value;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
//! Guard against packed / size-pass serialization of a streaming field.
|
|
237
|
+
/*!
|
|
238
|
+
The base RepeatedField::serialize() writes the packed element payload
|
|
239
|
+
with no tags, and is also what a size pass reaches via
|
|
240
|
+
Field::serialized_size() (serialize into a counting buffer). A callback
|
|
241
|
+
field owns no elements to pack and must not be pulled twice, so it only
|
|
242
|
+
ever emits EXPANDED through serialize_expanded(). Any call here means the
|
|
243
|
+
field was placed where a length-delimited (LEN) framing is required
|
|
244
|
+
(e.g. as a packed field or under a LEN ancestor), which is unsupported
|
|
245
|
+
for streaming storage: report CALLBACK_SEQUENCE instead of silently
|
|
246
|
+
draining the source. See design section 16.3.
|
|
247
|
+
*/
|
|
248
|
+
Error serialize(WriteBufferInterface& buffer) const override
|
|
249
|
+
{
|
|
250
|
+
static_cast<void>(buffer);
|
|
251
|
+
return Error::CALLBACK_SEQUENCE;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
//! Pull elements from the bound source and emit them EXPANDED.
|
|
255
|
+
/*!
|
|
256
|
+
One tag+value is written per element (the same wire form as an EXPANDED
|
|
257
|
+
repeated scalar field), so no field-level size prefix is needed and the
|
|
258
|
+
source is drained exactly once in a single pass. Production ends when the
|
|
259
|
+
source callback returns false. With no source bound nothing is emitted
|
|
260
|
+
(NO_ERRORS), unless strict mode is on, in which case CALLBACK_NOT_SET is
|
|
261
|
+
returned. A re-entrant call (the field being pulled while already
|
|
262
|
+
pulling, e.g. a stray size pass) returns CALLBACK_SEQUENCE rather than
|
|
263
|
+
double-pulling the stream.
|
|
264
|
+
|
|
265
|
+
\param field_number The field number written in each element's tag.
|
|
266
|
+
\param buffer The destination buffer.
|
|
267
|
+
*/
|
|
268
|
+
Error serialize_expanded(uint32_t field_number, WriteBufferInterface& buffer) const
|
|
269
|
+
{
|
|
270
|
+
Error return_value = Error::NO_ERRORS;
|
|
271
|
+
if(pulling_)
|
|
272
|
+
{
|
|
273
|
+
return_value = Error::CALLBACK_SEQUENCE;
|
|
274
|
+
}
|
|
275
|
+
else if(!source_.is_set())
|
|
276
|
+
{
|
|
277
|
+
if(strict_)
|
|
278
|
+
{
|
|
279
|
+
return_value = Error::CALLBACK_NOT_SET;
|
|
280
|
+
}
|
|
281
|
+
// Not strict: no source bound, emit nothing.
|
|
282
|
+
}
|
|
283
|
+
else
|
|
284
|
+
{
|
|
285
|
+
pulling_ = true;
|
|
286
|
+
bool more = true;
|
|
287
|
+
while(more && (Error::NO_ERRORS == return_value))
|
|
288
|
+
{
|
|
289
|
+
bool produced = false;
|
|
290
|
+
transient_ = DATA_TYPE();
|
|
291
|
+
static_cast<void>(source_.invoke(produced, transient_));
|
|
292
|
+
if(produced)
|
|
293
|
+
{
|
|
294
|
+
return_value = transient_.serialize_with_id(field_number, buffer, true);
|
|
295
|
+
if(Error::NO_ERRORS == return_value)
|
|
296
|
+
{
|
|
297
|
+
++length_;
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
else
|
|
301
|
+
{
|
|
302
|
+
more = false;
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
pulling_ = false;
|
|
306
|
+
}
|
|
307
|
+
return return_value;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
#ifdef PARTIAL_SERIALIZATION_ENABLED
|
|
311
|
+
//! Resumable EXPANDED pull-serialize for the partial engine.
|
|
312
|
+
/*!
|
|
313
|
+
Emits one tag+value per element, pulling from the source, and survives a
|
|
314
|
+
write buffer that fills mid-stream. Before each element is pulled the
|
|
315
|
+
remaining buffer space is checked against the element's maximum
|
|
316
|
+
serialized size; when it does not fit, BUFFER_FULL is returned WITHOUT
|
|
317
|
+
pulling, so the not-yet-produced element stays in the source and the next
|
|
318
|
+
call resumes with it (all-or-nothing, no double-pull). The source's own
|
|
319
|
+
cursor is the resumable state; no in-flight element is stored in the
|
|
320
|
+
field (design section 8.2). The write buffer must be able to hold at
|
|
321
|
+
least one element's maximum size for the stream to make progress.
|
|
322
|
+
*/
|
|
323
|
+
Error serialize_partial_as_field_expanded(uint32_t field_number,
|
|
324
|
+
WriteBufferInterface& buffer,
|
|
325
|
+
MessageState& state,
|
|
326
|
+
bool optional) const
|
|
327
|
+
{
|
|
328
|
+
static_cast<void>(optional);
|
|
329
|
+
Error return_value = Error::NO_ERRORS;
|
|
330
|
+
if(::EmbeddedProto::FieldProcessingPhase::COMPLETE == state.phase)
|
|
331
|
+
{
|
|
332
|
+
// The stream was already fully drained on an earlier call.
|
|
333
|
+
}
|
|
334
|
+
else if(!source_.is_set())
|
|
335
|
+
{
|
|
336
|
+
if(strict_)
|
|
337
|
+
{
|
|
338
|
+
return_value = Error::CALLBACK_NOT_SET;
|
|
339
|
+
}
|
|
340
|
+
else
|
|
341
|
+
{
|
|
342
|
+
state.phase = ::EmbeddedProto::FieldProcessingPhase::COMPLETE;
|
|
343
|
+
}
|
|
344
|
+
}
|
|
345
|
+
else
|
|
346
|
+
{
|
|
347
|
+
bool more = true;
|
|
348
|
+
while(more && (Error::NO_ERRORS == return_value))
|
|
349
|
+
{
|
|
350
|
+
if(buffer.get_available_size() < DATA_TYPE::max_serialized_size(field_number))
|
|
351
|
+
{
|
|
352
|
+
// Cannot guarantee the next element fits: stop before pulling and
|
|
353
|
+
// resume on the next call once the buffer has been flushed.
|
|
354
|
+
return_value = Error::BUFFER_FULL;
|
|
355
|
+
}
|
|
356
|
+
else
|
|
357
|
+
{
|
|
358
|
+
bool produced = false;
|
|
359
|
+
transient_ = DATA_TYPE();
|
|
360
|
+
static_cast<void>(source_.invoke(produced, transient_));
|
|
361
|
+
if(produced)
|
|
362
|
+
{
|
|
363
|
+
// Space was pre-checked, so this write always fits.
|
|
364
|
+
return_value = transient_.serialize_with_id(field_number, buffer, true);
|
|
365
|
+
if(Error::NO_ERRORS == return_value)
|
|
366
|
+
{
|
|
367
|
+
++length_;
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
else
|
|
371
|
+
{
|
|
372
|
+
more = false;
|
|
373
|
+
state.phase = ::EmbeddedProto::FieldProcessingPhase::COMPLETE;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
}
|
|
378
|
+
return return_value;
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
//! Guard the packed / LEN partial path.
|
|
382
|
+
/*!
|
|
383
|
+
A streaming field is emitted EXPANDED only (via
|
|
384
|
+
serialize_partial_as_field_expanded). The default
|
|
385
|
+
serialize_partial_as_field routes packed scalars through a length-prefixed
|
|
386
|
+
block that needs a size pass, which a callback field cannot provide
|
|
387
|
+
without draining its source twice. Reject it with CALLBACK_SEQUENCE
|
|
388
|
+
instead (design section 16.3).
|
|
389
|
+
*/
|
|
390
|
+
Error serialize_partial_as_field(uint32_t field_number,
|
|
391
|
+
WriteBufferInterface& buffer,
|
|
392
|
+
MessageState& state,
|
|
393
|
+
bool optional) const override
|
|
394
|
+
{
|
|
395
|
+
static_cast<void>(field_number);
|
|
396
|
+
static_cast<void>(buffer);
|
|
397
|
+
static_cast<void>(state);
|
|
398
|
+
static_cast<void>(optional);
|
|
399
|
+
return Error::CALLBACK_SEQUENCE;
|
|
400
|
+
}
|
|
401
|
+
#endif // PARTIAL_SERIALIZATION_ENABLED
|
|
402
|
+
|
|
403
|
+
//! Reset the streaming state (the element counter). Bindings are kept.
|
|
404
|
+
void clear() override { length_ = 0U; }
|
|
405
|
+
|
|
406
|
+
private:
|
|
407
|
+
|
|
408
|
+
//! Running count of elements streamed through this field. Mutable because serialize is const yet advances the counter as elements are pulled.
|
|
409
|
+
mutable uint32_t length_ = 0U;
|
|
410
|
+
|
|
411
|
+
//! Set while serialize_expanded() is draining the source, so a re-entrant call (e.g. a stray size pass) is rejected instead of double-pulling.
|
|
412
|
+
mutable bool pulling_ = false;
|
|
413
|
+
|
|
414
|
+
//! When true, streaming without a bound callback is an error rather than a silent drain/no-op.
|
|
415
|
+
bool strict_ = false;
|
|
416
|
+
|
|
417
|
+
//! Single-element landing slot required by the reference-returning RepeatedField interface.
|
|
418
|
+
/*!
|
|
419
|
+
It is not stream storage: the collection owns no per-element buffer.
|
|
420
|
+
*/
|
|
421
|
+
mutable DATA_TYPE transient_ = {};
|
|
422
|
+
|
|
423
|
+
//! Pull callback invoked to produce elements while serializing.
|
|
424
|
+
SourceCallback source_{};
|
|
425
|
+
|
|
426
|
+
//! Push callback invoked to consume elements while deserializing.
|
|
427
|
+
SinkCallback sink_{};
|
|
428
|
+
};
|
|
429
|
+
|
|
430
|
+
} // End of namespace EmbeddedProto
|
|
431
|
+
|
|
432
|
+
#endif // End of _REPEATED_FIELD_CALLBACK_H_
|