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.
Files changed (63) hide show
  1. EmbeddedProto/EmbeddedProto.py +122 -0
  2. EmbeddedProto/Features.py +255 -0
  3. EmbeddedProto/Field.py +1295 -0
  4. EmbeddedProto/Oneof.py +74 -0
  5. EmbeddedProto/ProtoFile.py +210 -0
  6. EmbeddedProto/TypeDefinitions.py +367 -0
  7. EmbeddedProto/__init__.py +0 -0
  8. EmbeddedProto/__main__.py +28 -0
  9. EmbeddedProto/config.py +173 -0
  10. EmbeddedProto/custom_header.py +513 -0
  11. EmbeddedProto/embedded_proto_options.proto +62 -0
  12. EmbeddedProto/embedded_proto_options_pb2.py +37 -0
  13. EmbeddedProto/field_options.py +344 -0
  14. EmbeddedProto/main.py +316 -0
  15. EmbeddedProto/src/EmbeddedProto/BytesStringCallback.h +476 -0
  16. EmbeddedProto/src/EmbeddedProto/Defines.h +118 -0
  17. EmbeddedProto/src/EmbeddedProto/EmptyArray.h +81 -0
  18. EmbeddedProto/src/EmbeddedProto/Errors.h +53 -0
  19. EmbeddedProto/src/EmbeddedProto/FieldStringBytes.h +793 -0
  20. EmbeddedProto/src/EmbeddedProto/Fields.h +832 -0
  21. EmbeddedProto/src/EmbeddedProto/Functional.h +412 -0
  22. EmbeddedProto/src/EmbeddedProto/MessageCallback.h +688 -0
  23. EmbeddedProto/src/EmbeddedProto/MessageInterface.h +792 -0
  24. EmbeddedProto/src/EmbeddedProto/MessageSizeCalculator.h +109 -0
  25. EmbeddedProto/src/EmbeddedProto/MessageState.h +207 -0
  26. EmbeddedProto/src/EmbeddedProto/ReadBufferFixedSize.h +204 -0
  27. EmbeddedProto/src/EmbeddedProto/ReadBufferInterface.h +181 -0
  28. EmbeddedProto/src/EmbeddedProto/ReadBufferSection.h +232 -0
  29. EmbeddedProto/src/EmbeddedProto/RepeatedField.h +1053 -0
  30. EmbeddedProto/src/EmbeddedProto/RepeatedFieldCallback.h +432 -0
  31. EmbeddedProto/src/EmbeddedProto/RepeatedFieldFixedSize.h +367 -0
  32. EmbeddedProto/src/EmbeddedProto/Version.h +39 -0
  33. EmbeddedProto/src/EmbeddedProto/WireFormatter.h +852 -0
  34. EmbeddedProto/src/EmbeddedProto/WriteBufferFixedSize.h +114 -0
  35. EmbeddedProto/src/EmbeddedProto/WriteBufferInterface.h +134 -0
  36. EmbeddedProto/src/EmbeddedProto.h +55 -0
  37. EmbeddedProto/templates/FieldBasic_Deserialize.h.jinja2 +26 -0
  38. EmbeddedProto/templates/FieldBasic_GetSet.h.jinja2 +89 -0
  39. EmbeddedProto/templates/FieldBytes_GetSet.h.jinja2 +86 -0
  40. EmbeddedProto/templates/FieldEnum_Deserialize.h.jinja2 +50 -0
  41. EmbeddedProto/templates/FieldEnum_GetSet.h.jinja2 +93 -0
  42. EmbeddedProto/templates/FieldErrorRecursive_GetSet.h.jinja2 +29 -0
  43. EmbeddedProto/templates/FieldMap_GetSet.h.jinja2 +203 -0
  44. EmbeddedProto/templates/FieldMsg_Deserialize.h.jinja2 +44 -0
  45. EmbeddedProto/templates/FieldMsg_GetSet.h.jinja2 +93 -0
  46. EmbeddedProto/templates/FieldRepeated_GetSet.h.jinja2 +94 -0
  47. EmbeddedProto/templates/FieldString_GetSet.h.jinja2 +86 -0
  48. EmbeddedProto/templates/Field_DeserializePartial.h.jinja2 +33 -0
  49. EmbeddedProto/templates/Field_Serialize.h.jinja2 +112 -0
  50. EmbeddedProto/templates/Field_SerializePartial.h.jinja2 +119 -0
  51. EmbeddedProto/templates/Header.h.jinja2 +108 -0
  52. EmbeddedProto/templates/TypeDefEnum.h.jinja2 +45 -0
  53. EmbeddedProto/templates/TypeDefMsg.h.jinja2 +791 -0
  54. EmbeddedProto/templates/TypeOneof.h.jinja2 +178 -0
  55. EmbeddedProto/version.json +3 -0
  56. embeddedproto-4.0.0b1.dist-info/METADATA +141 -0
  57. embeddedproto-4.0.0b1.dist-info/RECORD +63 -0
  58. embeddedproto-4.0.0b1.dist-info/WHEEL +5 -0
  59. embeddedproto-4.0.0b1.dist-info/entry_points.txt +3 -0
  60. embeddedproto-4.0.0b1.dist-info/licenses/LICENSE +30 -0
  61. embeddedproto-4.0.0b1.dist-info/licenses/LICENSES/GPL-3.0-only.txt +674 -0
  62. embeddedproto-4.0.0b1.dist-info/licenses/LICENSES/LicenseRef-EmbeddedProto-Commercial.txt +12 -0
  63. embeddedproto-4.0.0b1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,476 @@
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 _BYTES_STRING_CALLBACK_H_
25
+ #define _BYTES_STRING_CALLBACK_H_
26
+
27
+ #include "FieldStringBytes.h"
28
+ #include "Functional.h"
29
+ #include "Errors.h"
30
+ #include "Defines.h"
31
+ #include "WireFormatter.h"
32
+
33
+ #include <cstdint>
34
+ #include <type_traits>
35
+
36
+
37
+ namespace EmbeddedProto
38
+ {
39
+
40
+ //! A bytes/string field whose payload is streamed to/from the user in windows, not stored.
41
+ /*!
42
+ BytesStringCallback is the storage type of a singular bytes or string field
43
+ with the callbackStorage option. It keeps no value resident: the value moves
44
+ across the interface seam a window at a time, so a large blob (a firmware
45
+ image, a log, a picture) streams through the message in slices that never
46
+ add up to a whole value:
47
+
48
+ - on deserialize, every freshly parsed window is offered to the user
49
+ deserialize chunk callback, which returns how many elements it accepted;
50
+ - on serialize, a writable window is handed to the user serialize chunk
51
+ callback, which fills it and returns how many elements it produced.
52
+
53
+ No offset is passed. A stateful callback tracks its own position.
54
+
55
+ Serialize needs the total length up front for the LEN prefix, so the user
56
+ declares it once with set_length() before the first window is pulled. The
57
+ prefix is then written from that length and serialized_size() reports it
58
+ without pulling any data. Deserialize needs no such declaration, the wire
59
+ carries the length.
60
+
61
+ The buffer interfaces hand out no contiguous memory, so every window is
62
+ staged in memory the user binds with set_window(): a view over an array the
63
+ platform owns, a static array, a DMA buffer or a scratch region shared
64
+ between fields. Its size is the largest window a callback is offered. The
65
+ field itself holds only the view, not the window, so the message size does
66
+ not depend on the platform. One window serves both directions, a field never
67
+ serializes and deserializes at the same time. A window of one element gives
68
+ byte-by-byte streaming when that is all the user wants. The class derives
69
+ from internal::BaseStringBytes and satisfies the same static_assert the
70
+ customStorage mechanism checks.
71
+
72
+ \tparam DATA_TYPE The element type: char for a string field, uint8_t for a
73
+ bytes field.
74
+ */
75
+ template<class DATA_TYPE>
76
+ class BytesStringCallback : public internal::BaseStringBytes
77
+ {
78
+ static_assert(std::is_same<uint8_t, DATA_TYPE>::value || std::is_same<char, DATA_TYPE>::value,
79
+ "This class only supports uint8_t or chars.");
80
+
81
+ public:
82
+
83
+ //! The window handed to a callback: string_view for a string field, bytes_view for a bytes field.
84
+ using VIEW = array_view<DATA_TYPE>;
85
+
86
+ //! Chunk callback shared by both directions, see set_on_serialize_chunk() and set_on_deserialize_chunk().
87
+ using ChunkCallback = Functional<uint32_t(VIEW)>;
88
+
89
+ BytesStringCallback() = default;
90
+ ~BytesStringCallback() = default;
91
+
92
+ // --- Binding (reference-taking, no ownership) --------------------------
93
+
94
+ //! Bind the callback that fills windows during serialization.
95
+ /*!
96
+ The callback receives a writable window of up to the bound window's size
97
+ and returns how many it produced, at most the window size. Zero before the
98
+ declared length is reached ends the stream early, which is reported as
99
+ CALLBACK_SIZE_MISMATCH. The callback is not called once the declared
100
+ length is reached.
101
+ */
102
+ void set_on_serialize_chunk(const ChunkCallback& callback) { on_serialize_chunk_ = callback; }
103
+
104
+ //! Bind the callback that receives windows during deserialization.
105
+ /*!
106
+ The callback receives a window of freshly parsed elements it should read
107
+ and not modify, and returns how many it accepted. Returning less than the
108
+ window size stops the field: deserialization returns CALLBACK_STOPPED.
109
+ Under partial deserialization the accepted elements are consumed and the
110
+ state stays resumable, so a caller may retry after the callback has room
111
+ again.
112
+ */
113
+ void set_on_deserialize_chunk(const ChunkCallback& callback) { on_deserialize_chunk_ = callback; }
114
+
115
+ //! Bind the memory the windows are staged in; its size is the largest window a callback is offered.
116
+ /*!
117
+ The view does not own the array, which must outlive every serialize or
118
+ deserialize call, like the bound callbacks. Streaming without a window
119
+ bound is CALLBACK_NOT_SET.
120
+ */
121
+ void set_window(const VIEW& window) { window_ = window; }
122
+
123
+ //! Remove the bound window.
124
+ void clear_window() { window_ = VIEW{nullptr, 0U}; }
125
+
126
+ //! Check whether a usable window is bound.
127
+ bool is_window_set() const { return (nullptr != window_.data) && (0U < window_.size); }
128
+
129
+ //! Remove the bound serialize chunk callback.
130
+ void clear_on_serialize_chunk() { on_serialize_chunk_.clear(); }
131
+
132
+ //! Remove the bound deserialize chunk callback.
133
+ void clear_on_deserialize_chunk() { on_deserialize_chunk_.clear(); }
134
+
135
+ //! Check whether a serialize chunk callback is bound.
136
+ bool is_on_serialize_chunk_set() const { return on_serialize_chunk_.is_set(); }
137
+
138
+ //! Check whether a deserialize chunk callback is bound.
139
+ bool is_on_deserialize_chunk_set() const { return on_deserialize_chunk_.is_set(); }
140
+
141
+ //! Declare the total number of elements the serialize chunk callback will produce, written as the LEN prefix.
142
+ void set_length(const uint32_t length) { length_ = length; }
143
+
144
+ //! Require a binding for the direction being used.
145
+ /*!
146
+ When strict, deserializing without a chunk callback bound returns
147
+ CALLBACK_NOT_SET instead of silently discarding the value.
148
+ */
149
+ void set_strict(bool strict) { strict_ = strict; }
150
+
151
+ //! Whether strict (require-binding) mode is enabled.
152
+ bool is_strict() const { return strict_; }
153
+
154
+ //! Copy the bindings, the window and the declared length from another chunked field (used by the generated message copy/assignment).
155
+ /*!
156
+ \return Always NO_ERRORS, for signature compatibility with FieldStringBytes::set().
157
+ */
158
+ Error set(const BytesStringCallback<DATA_TYPE>& rhs)
159
+ {
160
+ on_serialize_chunk_ = rhs.on_serialize_chunk_;
161
+ on_deserialize_chunk_ = rhs.on_deserialize_chunk_;
162
+ window_ = rhs.window_;
163
+ length_ = rhs.length_;
164
+ strict_ = rhs.strict_;
165
+ return Error::NO_ERRORS;
166
+ }
167
+
168
+ // --- FieldStringBytes-shaped interface ---------------------------------
169
+
170
+ //! The declared payload length written as the LEN prefix, see set_length().
171
+ uint32_t get_length() const { return length_; }
172
+
173
+ //! Streaming is effectively unbounded; report a large sentinel so capacity checks never fire.
174
+ uint32_t get_max_length() const { return UINT32_MAX; }
175
+
176
+ //! The number of elements the bound window holds, the largest window a callback is offered (0 when unbound).
177
+ uint32_t get_window_size() const { return is_window_set() ? window_.size : 0U; }
178
+
179
+ //! Required of a customStorage bytes/string type.
180
+ /*!
181
+ A stream has no finite serialized size, so report the unbounded sentinel; a
182
+ message with a chunked field therefore cannot be statically buffer-sized,
183
+ which is inherent to streaming.
184
+ */
185
+ static constexpr uint32_t max_serialized_size(const uint32_t field_number)
186
+ {
187
+ static_cast<void>(field_number);
188
+ return UINT32_MAX;
189
+ }
190
+
191
+ //! Pull the payload in windows from the bound callback and write it (no tag, no size; the caller frames it with serialize_len).
192
+ /*!
193
+ Windows are pulled until exactly get_length() elements are written. A
194
+ non-empty value with no callback or no window bound cannot be produced:
195
+ CALLBACK_NOT_SET.
196
+ */
197
+ Error serialize(WriteBufferInterface& buffer) const override
198
+ {
199
+ Error return_value = Error::NO_ERRORS;
200
+ uint32_t remaining = length_;
201
+ if(0U == remaining)
202
+ {
203
+ // Nothing declared to emit; the caller wrote an empty (or no) prefix.
204
+ }
205
+ else if(!on_serialize_chunk_.is_set() || !is_window_set())
206
+ {
207
+ return_value = Error::CALLBACK_NOT_SET;
208
+ }
209
+ else
210
+ {
211
+ while((0U < remaining) && (Error::NO_ERRORS == return_value))
212
+ {
213
+ return_value = pull_window(buffer, remaining);
214
+ }
215
+ }
216
+ return return_value;
217
+ }
218
+
219
+ //! Read the LEN prefix, then offer each parsed window to the bound callback (drain-and-discard when unbound and not strict).
220
+ Error deserialize(ReadBufferInterface& buffer) override
221
+ {
222
+ uint32_t remaining = 0U;
223
+ Error return_value = WireFormatter::DeserializeVarint(buffer, remaining);
224
+ while((0U < remaining) && (Error::NO_ERRORS == return_value))
225
+ {
226
+ return_value = offer_window(buffer, remaining);
227
+ }
228
+ return return_value;
229
+ }
230
+
231
+ //! Validate the wire type is length-delimited, then deserialize.
232
+ Error deserialize_check_type(::EmbeddedProto::ReadBufferInterface& buffer,
233
+ const ::EmbeddedProto::WireFormatter::WireType& wire_type) override
234
+ {
235
+ Error return_value = ::EmbeddedProto::WireFormatter::WireType::LENGTH_DELIMITED == wire_type
236
+ ? Error::NO_ERRORS : Error::INVALID_WIRETYPE;
237
+ if(Error::NO_ERRORS == return_value)
238
+ {
239
+ return_value = this->deserialize(buffer);
240
+ }
241
+ return return_value;
242
+ }
243
+
244
+ #ifdef PARTIAL_SERIALIZATION_ENABLED
245
+ //! Resumable window-serialize for the partial engine.
246
+ /*!
247
+ The TAG and SIZE phases write the tag and the declared length, so the
248
+ field survives a write buffer that splits before the payload. The DATA
249
+ phase pulls one window at a time, never larger than the room left in the
250
+ buffer, so a produced window is never lost on a BUFFER_FULL resume. The
251
+ callback's own cursor is the resumable state.
252
+ */
253
+ Error serialize_partial_as_field(uint32_t field_number,
254
+ WriteBufferInterface& buffer,
255
+ MessageState& state,
256
+ bool optional) const override
257
+ {
258
+ Error return_value = Error::NO_ERRORS;
259
+ if(::EmbeddedProto::FieldProcessingPhase::DATA != state.phase)
260
+ {
261
+ return_value = serialize_partial_tag_and_size(field_number, length_, buffer, state, optional);
262
+ }
263
+
264
+ if((Error::NO_ERRORS == return_value) && (::EmbeddedProto::FieldProcessingPhase::DATA == state.phase))
265
+ {
266
+ if(!on_serialize_chunk_.is_set() || !is_window_set())
267
+ {
268
+ return_value = Error::CALLBACK_NOT_SET;
269
+ }
270
+ else
271
+ {
272
+ while((0U < state.bytes_remaining) && (Error::NO_ERRORS == return_value))
273
+ {
274
+ return_value = pull_window(buffer, state.bytes_remaining);
275
+ }
276
+ if(0U == state.bytes_remaining)
277
+ {
278
+ state.phase = ::EmbeddedProto::FieldProcessingPhase::COMPLETE;
279
+ }
280
+ }
281
+ }
282
+ return return_value;
283
+ }
284
+
285
+ //! Resumable window-deserialize for the partial engine.
286
+ /*!
287
+ The SIZE phase reads the LEN prefix into state.bytes_remaining; the DATA
288
+ phase offers windows to the callback, decrementing bytes_remaining, and
289
+ returns END_OF_BUFFER (leaving the phase at DATA) when the read buffer
290
+ drains mid-value so the next call resumes where it stopped. A window is
291
+ at most what the buffer holds, so a refill boundary simply ends a window.
292
+ */
293
+ Error deserialize_partial_as_field(ReadBufferInterface& buffer,
294
+ MessageState& state) override
295
+ {
296
+ Error return_value = Error::NO_ERRORS;
297
+ if((::EmbeddedProto::FieldProcessingPhase::SIZE != state.phase) && (::EmbeddedProto::FieldProcessingPhase::DATA != state.phase))
298
+ {
299
+ return_value = Error::STATE_MISMATCH;
300
+ }
301
+
302
+ if((Error::NO_ERRORS == return_value) && (::EmbeddedProto::FieldProcessingPhase::SIZE == state.phase))
303
+ {
304
+ return_value = deserialize_partial_size_phase(buffer, state);
305
+ }
306
+
307
+ if((Error::NO_ERRORS == return_value) && (::EmbeddedProto::FieldProcessingPhase::DATA == state.phase))
308
+ {
309
+ while((0U < state.bytes_remaining) && (Error::NO_ERRORS == return_value))
310
+ {
311
+ return_value = offer_window(buffer, state.bytes_remaining);
312
+ }
313
+ if(0U == state.bytes_remaining)
314
+ {
315
+ state.phase = ::EmbeddedProto::FieldProcessingPhase::COMPLETE;
316
+ }
317
+ }
318
+ return return_value;
319
+ }
320
+ #endif // PARTIAL_SERIALIZATION_ENABLED
321
+
322
+ //! Forget the declared length; the bindings and the window are kept.
323
+ void clear() override { length_ = 0U; }
324
+
325
+ #ifdef MSG_TO_STRING
326
+ //! A callback field holds no resident value to print, so leave the string unchanged.
327
+ ::EmbeddedProto::string_view to_string(::EmbeddedProto::string_view& str, const uint32_t indent_level, char const* name, const bool first_field) const override
328
+ {
329
+ static_cast<void>(indent_level);
330
+ static_cast<void>(name);
331
+ static_cast<void>(first_field);
332
+ return str;
333
+ }
334
+ #endif // MSG_TO_STRING
335
+
336
+ private:
337
+
338
+ //! Pull one window from the serialize callback and push it into the buffer.
339
+ /*!
340
+ The window offered is the smallest of the bound window, the elements
341
+ still to write and the room left in the buffer, so what the callback
342
+ produces always fits. No room at all is BUFFER_FULL before anything is pulled.
343
+
344
+ \param[in] buffer The buffer to write to.
345
+ \param[in,out] remaining The number of elements still to write, decremented by what was produced.
346
+ */
347
+ Error pull_window(WriteBufferInterface& buffer, uint32_t& remaining) const
348
+ {
349
+ Error return_value = Error::NO_ERRORS;
350
+ const uint32_t offered = min(min(window_.size, remaining), buffer.get_available_size());
351
+ if(0U == offered)
352
+ {
353
+ return_value = Error::BUFFER_FULL;
354
+ }
355
+ else
356
+ {
357
+ uint32_t produced = 0U;
358
+ static_cast<void>(on_serialize_chunk_.invoke(produced, VIEW{window_.data, offered}));
359
+ if((0U == produced) || (offered < produced))
360
+ {
361
+ return_value = Error::CALLBACK_SIZE_MISMATCH;
362
+ }
363
+ else if(!buffer.push(const_bytes_view{window_bytes(), produced}))
364
+ {
365
+ return_value = Error::BUFFER_FULL;
366
+ }
367
+ else
368
+ {
369
+ remaining -= produced;
370
+ }
371
+ }
372
+ return return_value;
373
+ }
374
+
375
+ //! Peek one window out of the buffer, offer it to the deserialize callback and consume what it accepted.
376
+ /*!
377
+ The window offered is the smallest of the bound window, the elements
378
+ still to read and the bytes the buffer holds. An empty buffer is
379
+ END_OF_BUFFER before anything is consumed. Without a window nothing can
380
+ be offered: CALLBACK_NOT_SET. Without a callback no window is needed to
381
+ drain and discard. The window is peeked, not popped, so only
382
+ the accepted elements leave the buffer and a stopped field can resume.
383
+
384
+ \param[in] buffer The buffer to read from.
385
+ \param[in,out] remaining The number of elements still to read, decremented by what was accepted.
386
+ */
387
+ Error offer_window(ReadBufferInterface& buffer, uint32_t& remaining)
388
+ {
389
+ Error return_value = Error::NO_ERRORS;
390
+ const uint32_t offered = min(remaining, buffer.get_size());
391
+ if(0U == offered)
392
+ {
393
+ return_value = Error::END_OF_BUFFER;
394
+ }
395
+ else if(on_deserialize_chunk_.is_set())
396
+ {
397
+ if(!is_window_set())
398
+ {
399
+ return_value = Error::CALLBACK_NOT_SET;
400
+ }
401
+ else
402
+ {
403
+ return_value = offer_to_callback(buffer, remaining, min(window_.size, offered));
404
+ }
405
+ }
406
+ else if(strict_)
407
+ {
408
+ return_value = Error::CALLBACK_NOT_SET;
409
+ }
410
+ else
411
+ {
412
+ // No callback bound and not strict: drain and discard.
413
+ static_cast<void>(buffer.advance(offered));
414
+ remaining -= offered;
415
+ }
416
+ return return_value;
417
+ }
418
+
419
+ //! Peek the offered elements into the window, hand it to the callback and consume what it accepted.
420
+ Error offer_to_callback(ReadBufferInterface& buffer, uint32_t& remaining, const uint32_t offered)
421
+ {
422
+ Error return_value = Error::NO_ERRORS;
423
+ // The bytes stay in the buffer until the callback says how many it accepted.
424
+ static_cast<void>(buffer.peek(bytes_view{window_bytes(), offered}));
425
+
426
+ uint32_t accepted = 0U;
427
+ static_cast<void>(on_deserialize_chunk_.invoke(accepted, VIEW{window_.data, offered}));
428
+ if(offered < accepted)
429
+ {
430
+ return_value = Error::CALLBACK_SIZE_MISMATCH;
431
+ }
432
+ else
433
+ {
434
+ static_cast<void>(buffer.advance(accepted));
435
+ remaining -= accepted;
436
+ if(accepted < offered)
437
+ {
438
+ return_value = Error::CALLBACK_STOPPED;
439
+ }
440
+ }
441
+ return return_value;
442
+ }
443
+
444
+ //! The window as writable bytes, the unit the read buffer fills.
445
+ uint8_t* window_bytes()
446
+ {
447
+ void* void_pointer = static_cast<void*>(window_.data);
448
+ return static_cast<uint8_t*>(void_pointer);
449
+ }
450
+
451
+ //! The window as bytes, the unit the write buffer takes.
452
+ const uint8_t* window_bytes() const
453
+ {
454
+ const void* void_pointer = static_cast<const void*>(window_.data);
455
+ return static_cast<const uint8_t*>(void_pointer);
456
+ }
457
+
458
+ //! When true, deserializing without a bound callback is an error rather than a silent drain.
459
+ bool strict_ = false;
460
+
461
+ //! The declared payload length written as the LEN prefix.
462
+ uint32_t length_ = 0U;
463
+
464
+ //! The user supplied memory the windows are staged in; its size bounds every window offered.
465
+ VIEW window_{nullptr, 0U};
466
+
467
+ //! Callback invoked to fill a window while serializing.
468
+ ChunkCallback on_serialize_chunk_{};
469
+
470
+ //! Callback invoked with a parsed window while deserializing.
471
+ ChunkCallback on_deserialize_chunk_{};
472
+ };
473
+
474
+ } // End of namespace EmbeddedProto
475
+
476
+ #endif // End of _BYTES_STRING_CALLBACK_H_
@@ -0,0 +1,118 @@
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 _EMBEDDED_PROTO_DEFINES_H_
25
+ #define _EMBEDDED_PROTO_DEFINES_H_
26
+
27
+ #include <type_traits>
28
+ #include <cstdint>
29
+
30
+ #if __cplusplus >= 201703L // C++17 and up
31
+ #include <memory>
32
+ #endif
33
+
34
+ namespace EmbeddedProto
35
+ {
36
+
37
+ //! Define PARTIAL_SERIALIZATION_ENABLED to enable partial (chunked) serialization
38
+ //! and deserialization. When defined the generated messages and the library gain
39
+ //! the serialize_partial()/deserialize_partial() methods, which allow (de)serialization
40
+ //! to be paused when a buffer is exhausted and resumed with a fresh buffer.
41
+ //! When the macro is not defined only the regular, single-call serialize()/deserialize()
42
+ //! are available.
43
+
44
+ //! Define VIRTUAL_DESTRUCTORS_ENABLED to give the Field, ReadBufferInterface and
45
+ //! WriteBufferInterface base classes a public virtual destructor.
46
+ /*!
47
+ By default those destructors are protected and non-virtual: objects are destroyed as
48
+ their concrete type and deleting one through a pointer to the interface is a compile
49
+ error. A virtual destructor puts a deleting destructor in every vtable, which references
50
+ operator delete and links malloc and free into firmware that never frees anything
51
+ (about 700 bytes of flash and 400 bytes of RAM on a Cortex-M4). Define the macro when
52
+ messages or buffers are owned and deleted through an interface pointer, for example a
53
+ std::unique_ptr<MessageInterface> backed by an RTOS heap.
54
+ */
55
+
56
+ #if __cplusplus >= 201703L // C++17 and up
57
+
58
+ template<class T>
59
+ inline constexpr void destroy_at(T* p)
60
+ {
61
+ std::destroy_at(p);
62
+ }
63
+
64
+ #elif __cplusplus >= 201402L // C++14
65
+
66
+ template<class T>
67
+ constexpr void destroy_at(T* p)
68
+ {
69
+ p->~T();
70
+ }
71
+
72
+ #elif __cplusplus >= 201103L // C++11
73
+
74
+ template<class T>
75
+ constexpr void destroy_at(T* p)
76
+ {
77
+ p->~T();
78
+ }
79
+
80
+ #else // Other
81
+
82
+ #error "Unsupported version of C++. Embedded Proto supports C++11 and up."
83
+
84
+ #endif
85
+
86
+
87
+ //! A simple struct holding both a pointer to an array and the size of that array.
88
+ /*!
89
+ The view keeps the pointer and its bound together, which is what the array
90
+ interfaces of the library take instead of a separate pointer and length. Use a
91
+ const element type, for example array_view<const uint8_t>, to view an array which
92
+ is only read.
93
+ */
94
+ template<class T>
95
+ struct array_view {
96
+ T* data; //!< A pointer to the start of an array.
97
+ uint32_t size; //!< The number of elements in the array.
98
+ };
99
+
100
+ using string_view = array_view<char>;
101
+ using bytes_view = array_view<uint8_t>;
102
+ using const_string_view = array_view<const char>; //!< A view on characters which are only read.
103
+ using const_bytes_view = array_view<const uint8_t>; //!< A view on bytes which are only read.
104
+
105
+ //! Simple max function as constexpr
106
+ constexpr uint32_t max(const uint32_t a, const uint32_t b)
107
+ {
108
+ return (a > b) ? a : b;
109
+ }
110
+
111
+ //! Simple min function as constexpr
112
+ constexpr uint32_t min(const uint32_t a, const uint32_t b)
113
+ {
114
+ return (a < b) ? a : b;
115
+ }
116
+ }
117
+
118
+ #endif //_EMBEDDED_PROTO_DEFINES_H_
@@ -0,0 +1,81 @@
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 _EMPTY_ARRAY_H_
25
+ #define _EMPTY_ARRAY_H_
26
+
27
+ #include <cstdint>
28
+
29
+ namespace EmbeddedProto
30
+ {
31
+ namespace internal
32
+ {
33
+
34
+ //! Stand-in for std::array<T, 0> that is one byte on every standard library.
35
+ /*!
36
+ libc++ gives std::array<T, 0> the size of one T so that data() stays aligned, libstdc++
37
+ makes it one byte. A field with a maximum length of zero holds no element, so the fixed size
38
+ containers use this class instead of the array there. Every element access lands on one
39
+ scratch element shared by all instances for the same T. That keeps an out of range access
40
+ memory safe, but a value written to the scratch element is lost by design.
41
+ */
42
+ template<class T>
43
+ class EmptyArray
44
+ {
45
+ public:
46
+ static constexpr uint32_t size() { return 0U; }
47
+
48
+ T* data() { return &storage(); }
49
+ const T* data() const { return &storage(); }
50
+
51
+ //! Begin and end are equal, a range based loop does not run.
52
+ T* begin() { return data(); }
53
+ T* end() { return data(); }
54
+ const T* begin() const { return data(); }
55
+ const T* end() const { return data(); }
56
+
57
+ //! Any index lands on the scratch element, reset to its default value first.
58
+ T& operator[](uint32_t) { return reset(); }
59
+ const T& operator[](uint32_t) const { return reset(); }
60
+
61
+ void fill(const T&) {}
62
+
63
+ private:
64
+ static T& storage()
65
+ {
66
+ static T element = T();
67
+ return element;
68
+ }
69
+
70
+ static T& reset()
71
+ {
72
+ T& element = storage();
73
+ element = T();
74
+ return element;
75
+ }
76
+ };
77
+
78
+ } // End of namespace internal
79
+ } // End of namespace EmbeddedProto
80
+
81
+ #endif // End of _EMPTY_ARRAY_H_