xref: /aosp_15_r20/external/pigweed/pw_protobuf/docs.rst (revision 61c4878ac05f98d0ceed94b57d316916de578985)
1*61c4878aSAndroid Build Coastguard Worker.. _module-pw_protobuf:
2*61c4878aSAndroid Build Coastguard Worker
3*61c4878aSAndroid Build Coastguard Worker===========
4*61c4878aSAndroid Build Coastguard Workerpw_protobuf
5*61c4878aSAndroid Build Coastguard Worker===========
6*61c4878aSAndroid Build Coastguard Worker.. pigweed-module::
7*61c4878aSAndroid Build Coastguard Worker   :name: pw_protobuf
8*61c4878aSAndroid Build Coastguard Worker
9*61c4878aSAndroid Build Coastguard Worker``pw_protobuf`` provides an expressive interface for encoding and decoding
10*61c4878aSAndroid Build Coastguard Workerthe Protocol Buffer wire format with a lightweight code and data footprint.
11*61c4878aSAndroid Build Coastguard Worker
12*61c4878aSAndroid Build Coastguard Worker.. note::
13*61c4878aSAndroid Build Coastguard Worker
14*61c4878aSAndroid Build Coastguard Worker   The protobuf module is a work in progress. Wire format encoding and decoding
15*61c4878aSAndroid Build Coastguard Worker   is supported, though the APIs are not final. C++ code generation exists for
16*61c4878aSAndroid Build Coastguard Worker   encoding and decoding, but not yet optimized for in-memory decoding.
17*61c4878aSAndroid Build Coastguard Worker
18*61c4878aSAndroid Build Coastguard Worker--------
19*61c4878aSAndroid Build Coastguard WorkerOverview
20*61c4878aSAndroid Build Coastguard Worker--------
21*61c4878aSAndroid Build Coastguard WorkerUnlike protobuf libraries which require protobuf messages be represented by
22*61c4878aSAndroid Build Coastguard Workerin-memory data structures, ``pw_protobuf`` provides a progressive flexible API
23*61c4878aSAndroid Build Coastguard Workerthat allows the user to choose the data storage format and tradeoffs most
24*61c4878aSAndroid Build Coastguard Workersuitable for their product on top of the implementation.
25*61c4878aSAndroid Build Coastguard Worker
26*61c4878aSAndroid Build Coastguard WorkerThe API is designed in three layers, which can be freely intermixed with each
27*61c4878aSAndroid Build Coastguard Workerother in your code, depending on point of use requirements:
28*61c4878aSAndroid Build Coastguard Worker
29*61c4878aSAndroid Build Coastguard Worker1. Message Structures,
30*61c4878aSAndroid Build Coastguard Worker2. Per-Field Writers and Readers,
31*61c4878aSAndroid Build Coastguard Worker3. Direct Writers and Readers.
32*61c4878aSAndroid Build Coastguard Worker
33*61c4878aSAndroid Build Coastguard WorkerThis has a few benefits. The primary one is that it allows the core proto
34*61c4878aSAndroid Build Coastguard Workerserialization and deserialization libraries to be relatively small.
35*61c4878aSAndroid Build Coastguard Worker
36*61c4878aSAndroid Build Coastguard Worker.. include:: size_report/protobuf_overview
37*61c4878aSAndroid Build Coastguard Worker
38*61c4878aSAndroid Build Coastguard WorkerTo demonstrate these layers, we use the following protobuf message definition
39*61c4878aSAndroid Build Coastguard Workerin the examples:
40*61c4878aSAndroid Build Coastguard Worker
41*61c4878aSAndroid Build Coastguard Worker.. code-block:: protobuf
42*61c4878aSAndroid Build Coastguard Worker
43*61c4878aSAndroid Build Coastguard Worker   message Customer {
44*61c4878aSAndroid Build Coastguard Worker     enum Status {
45*61c4878aSAndroid Build Coastguard Worker       NEW = 1;
46*61c4878aSAndroid Build Coastguard Worker       ACTIVE = 2;
47*61c4878aSAndroid Build Coastguard Worker       INACTIVE = 3;
48*61c4878aSAndroid Build Coastguard Worker     }
49*61c4878aSAndroid Build Coastguard Worker     int32 age = 1;
50*61c4878aSAndroid Build Coastguard Worker     string name = 2;
51*61c4878aSAndroid Build Coastguard Worker     Status status = 3;
52*61c4878aSAndroid Build Coastguard Worker   }
53*61c4878aSAndroid Build Coastguard Worker
54*61c4878aSAndroid Build Coastguard WorkerAnd the following accompanying options file:
55*61c4878aSAndroid Build Coastguard Worker
56*61c4878aSAndroid Build Coastguard Worker.. code-block:: text
57*61c4878aSAndroid Build Coastguard Worker
58*61c4878aSAndroid Build Coastguard Worker   Customer.name max_size:32
59*61c4878aSAndroid Build Coastguard Worker
60*61c4878aSAndroid Build Coastguard Worker.. toctree::
61*61c4878aSAndroid Build Coastguard Worker   :maxdepth: 1
62*61c4878aSAndroid Build Coastguard Worker
63*61c4878aSAndroid Build Coastguard Worker   size_report
64*61c4878aSAndroid Build Coastguard Worker
65*61c4878aSAndroid Build Coastguard WorkerMessage Structures
66*61c4878aSAndroid Build Coastguard Worker==================
67*61c4878aSAndroid Build Coastguard WorkerThe highest level API is based around message structures created through C++
68*61c4878aSAndroid Build Coastguard Workercode generation, integrated with Pigweed's build system.
69*61c4878aSAndroid Build Coastguard Worker
70*61c4878aSAndroid Build Coastguard Worker.. warning::
71*61c4878aSAndroid Build Coastguard Worker
72*61c4878aSAndroid Build Coastguard Worker   Message structures only support a subset of protobuf field types. Before
73*61c4878aSAndroid Build Coastguard Worker   continuing, refer to :ref:`pw_protobuf-message-limitations` to understand
74*61c4878aSAndroid Build Coastguard Worker   what types of protobuf messages can and cannot be represented, and whether
75*61c4878aSAndroid Build Coastguard Worker   or not message structures are a suitable choice.
76*61c4878aSAndroid Build Coastguard Worker
77*61c4878aSAndroid Build Coastguard WorkerThis results in the following generated structure:
78*61c4878aSAndroid Build Coastguard Worker
79*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
80*61c4878aSAndroid Build Coastguard Worker
81*61c4878aSAndroid Build Coastguard Worker   enum class Customer::Status : uint32_t {
82*61c4878aSAndroid Build Coastguard Worker     NEW = 1,
83*61c4878aSAndroid Build Coastguard Worker     ACTIVE = 2,
84*61c4878aSAndroid Build Coastguard Worker     INACTIVE = 3,
85*61c4878aSAndroid Build Coastguard Worker
86*61c4878aSAndroid Build Coastguard Worker     kNew = NEW,
87*61c4878aSAndroid Build Coastguard Worker     kActive = ACTIVE,
88*61c4878aSAndroid Build Coastguard Worker     kInactive = INACTIVE,
89*61c4878aSAndroid Build Coastguard Worker   };
90*61c4878aSAndroid Build Coastguard Worker
91*61c4878aSAndroid Build Coastguard Worker   struct Customer::Message {
92*61c4878aSAndroid Build Coastguard Worker     int32_t age;
93*61c4878aSAndroid Build Coastguard Worker     pw::InlineString<32> name;
94*61c4878aSAndroid Build Coastguard Worker     Customer::Status status;
95*61c4878aSAndroid Build Coastguard Worker   };
96*61c4878aSAndroid Build Coastguard Worker
97*61c4878aSAndroid Build Coastguard WorkerWhich can be encoded with the code:
98*61c4878aSAndroid Build Coastguard Worker
99*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
100*61c4878aSAndroid Build Coastguard Worker
101*61c4878aSAndroid Build Coastguard Worker   #include "example_protos/customer.pwpb.h"
102*61c4878aSAndroid Build Coastguard Worker
103*61c4878aSAndroid Build Coastguard Worker   pw::Status EncodeCustomer(Customer::StreamEncoder& encoder) {
104*61c4878aSAndroid Build Coastguard Worker     return encoder.Write({
105*61c4878aSAndroid Build Coastguard Worker       age = 33,
106*61c4878aSAndroid Build Coastguard Worker       name = "Joe Bloggs",
107*61c4878aSAndroid Build Coastguard Worker       status = Customer::Status::INACTIVE
108*61c4878aSAndroid Build Coastguard Worker     });
109*61c4878aSAndroid Build Coastguard Worker   }
110*61c4878aSAndroid Build Coastguard Worker
111*61c4878aSAndroid Build Coastguard WorkerAnd decoded into a struct with the code:
112*61c4878aSAndroid Build Coastguard Worker
113*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
114*61c4878aSAndroid Build Coastguard Worker
115*61c4878aSAndroid Build Coastguard Worker   #include "example_protos/customer.pwpb.h"
116*61c4878aSAndroid Build Coastguard Worker
117*61c4878aSAndroid Build Coastguard Worker   pw::Status DecodeCustomer(Customer::StreamDecoder& decoder) {
118*61c4878aSAndroid Build Coastguard Worker     Customer::Message customer{};
119*61c4878aSAndroid Build Coastguard Worker     PW_TRY(decoder.Read(customer));
120*61c4878aSAndroid Build Coastguard Worker     // Read fields from customer
121*61c4878aSAndroid Build Coastguard Worker     return pw::OkStatus();
122*61c4878aSAndroid Build Coastguard Worker   }
123*61c4878aSAndroid Build Coastguard Worker
124*61c4878aSAndroid Build Coastguard WorkerThese structures can be moved, copied, and compared with each other for
125*61c4878aSAndroid Build Coastguard Workerequality.
126*61c4878aSAndroid Build Coastguard Worker
127*61c4878aSAndroid Build Coastguard WorkerThe encoder and decoder code is generic and implemented in the core C++ module.
128*61c4878aSAndroid Build Coastguard WorkerA small overhead for each message type used in your code describes the structure
129*61c4878aSAndroid Build Coastguard Workerto the generic encoder and decoders.
130*61c4878aSAndroid Build Coastguard Worker
131*61c4878aSAndroid Build Coastguard WorkerMessage comparison
132*61c4878aSAndroid Build Coastguard Worker------------------
133*61c4878aSAndroid Build Coastguard WorkerMessage structures implement ``operator==`` and ``operator!=`` for equality and
134*61c4878aSAndroid Build Coastguard Workerinequality comparisons. However, these can only work on trivial scalar fields
135*61c4878aSAndroid Build Coastguard Workerand fixed-size strings within the message. Fields using a callback are not
136*61c4878aSAndroid Build Coastguard Workerconsidered in the comparison.
137*61c4878aSAndroid Build Coastguard Worker
138*61c4878aSAndroid Build Coastguard WorkerTo check if the equality operator of a generated message covers all fields,
139*61c4878aSAndroid Build Coastguard Worker``pw_protobuf`` provides an ``IsTriviallyComparable`` function.
140*61c4878aSAndroid Build Coastguard Worker
141*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
142*61c4878aSAndroid Build Coastguard Worker
143*61c4878aSAndroid Build Coastguard Worker   template <typename Message>
144*61c4878aSAndroid Build Coastguard Worker   constexpr bool IsTriviallyComparable<Message>();
145*61c4878aSAndroid Build Coastguard Worker
146*61c4878aSAndroid Build Coastguard WorkerFor example, given the following protobuf definitions:
147*61c4878aSAndroid Build Coastguard Worker
148*61c4878aSAndroid Build Coastguard Worker.. code-block:: protobuf
149*61c4878aSAndroid Build Coastguard Worker
150*61c4878aSAndroid Build Coastguard Worker   message Point {
151*61c4878aSAndroid Build Coastguard Worker     int32 x = 1;
152*61c4878aSAndroid Build Coastguard Worker     int32 y = 2;
153*61c4878aSAndroid Build Coastguard Worker   }
154*61c4878aSAndroid Build Coastguard Worker
155*61c4878aSAndroid Build Coastguard Worker   message Label {
156*61c4878aSAndroid Build Coastguard Worker     Point point = 1;
157*61c4878aSAndroid Build Coastguard Worker     string label = 2;
158*61c4878aSAndroid Build Coastguard Worker   }
159*61c4878aSAndroid Build Coastguard Worker
160*61c4878aSAndroid Build Coastguard WorkerAnd the accompanying options file:
161*61c4878aSAndroid Build Coastguard Worker
162*61c4878aSAndroid Build Coastguard Worker.. code-block:: text
163*61c4878aSAndroid Build Coastguard Worker
164*61c4878aSAndroid Build Coastguard Worker   Label.label use_callback:true
165*61c4878aSAndroid Build Coastguard Worker
166*61c4878aSAndroid Build Coastguard WorkerThe ``Point`` message can be fully compared for equality, but ``Label`` cannot.
167*61c4878aSAndroid Build Coastguard Worker``Label`` still defines an ``operator==``, but it ignores the ``label`` string.
168*61c4878aSAndroid Build Coastguard Worker
169*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
170*61c4878aSAndroid Build Coastguard Worker
171*61c4878aSAndroid Build Coastguard Worker   Point::Message one = {.x = 5, .y = 11};
172*61c4878aSAndroid Build Coastguard Worker   Point::Message two = {.x = 5, .y = 11};
173*61c4878aSAndroid Build Coastguard Worker
174*61c4878aSAndroid Build Coastguard Worker   static_assert(pw::protobuf::IsTriviallyComparable<Point::Message>());
175*61c4878aSAndroid Build Coastguard Worker   ASSERT_EQ(one, two);
176*61c4878aSAndroid Build Coastguard Worker   static_assert(!pw::protobuf::IsTriviallyComparable<Label::Message>());
177*61c4878aSAndroid Build Coastguard Worker
178*61c4878aSAndroid Build Coastguard WorkerBuffer Sizes
179*61c4878aSAndroid Build Coastguard Worker------------
180*61c4878aSAndroid Build Coastguard WorkerInitializing a ``MemoryEncoder`` requires that you specify the size of the
181*61c4878aSAndroid Build Coastguard Workerbuffer to encode to. The code generation includes a ``kMaxEncodedSizeBytes``
182*61c4878aSAndroid Build Coastguard Workerconstant that represents the maximum encoded size of the protobuf message,
183*61c4878aSAndroid Build Coastguard Workerexcluding the contents of any field values which require a callback.
184*61c4878aSAndroid Build Coastguard Worker
185*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
186*61c4878aSAndroid Build Coastguard Worker
187*61c4878aSAndroid Build Coastguard Worker   #include "example_protos/customer.pwpb.h"
188*61c4878aSAndroid Build Coastguard Worker
189*61c4878aSAndroid Build Coastguard Worker   std::byte buffer[Customer::kMaxEncodedSizeBytes];
190*61c4878aSAndroid Build Coastguard Worker   Customer::MemoryEncoder encoder(buffer);
191*61c4878aSAndroid Build Coastguard Worker   const auto status = encoder.Write({
192*61c4878aSAndroid Build Coastguard Worker     age = 22,
193*61c4878aSAndroid Build Coastguard Worker     name = "Wolfgang Bjornson",
194*61c4878aSAndroid Build Coastguard Worker     status = Customer::Status::ACTIVE
195*61c4878aSAndroid Build Coastguard Worker   });
196*61c4878aSAndroid Build Coastguard Worker
197*61c4878aSAndroid Build Coastguard Worker   // Always check the encoder status or return values from Write calls.
198*61c4878aSAndroid Build Coastguard Worker   if (!status.ok()) {
199*61c4878aSAndroid Build Coastguard Worker     PW_LOG_INFO("Failed to encode proto; %s", encoder.status().str());
200*61c4878aSAndroid Build Coastguard Worker   }
201*61c4878aSAndroid Build Coastguard Worker
202*61c4878aSAndroid Build Coastguard WorkerIn the above example, because the ``name`` field has a ``max_size`` specified
203*61c4878aSAndroid Build Coastguard Workerin the accompanying options file, ``kMaxEncodedSizeBytes`` includes the maximum
204*61c4878aSAndroid Build Coastguard Workerlength of the value for that field.
205*61c4878aSAndroid Build Coastguard Worker
206*61c4878aSAndroid Build Coastguard WorkerWhere the maximum length of a field value is not known, indicated by the
207*61c4878aSAndroid Build Coastguard Workerstructure requiring a callback for that field, the constant includes
208*61c4878aSAndroid Build Coastguard Workerall relevant overhead and only requires that you add the length of the field
209*61c4878aSAndroid Build Coastguard Workervalues.
210*61c4878aSAndroid Build Coastguard Worker
211*61c4878aSAndroid Build Coastguard WorkerFor example if a ``bytes`` field length is not specified in the options file,
212*61c4878aSAndroid Build Coastguard Workerbut is known to your code (``kMaxImageDataSize`` in this example being a
213*61c4878aSAndroid Build Coastguard Workerconstant in your own code), you can simply add it to the generated constant:
214*61c4878aSAndroid Build Coastguard Worker
215*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
216*61c4878aSAndroid Build Coastguard Worker
217*61c4878aSAndroid Build Coastguard Worker   #include "example_protos/store.pwpb.h"
218*61c4878aSAndroid Build Coastguard Worker
219*61c4878aSAndroid Build Coastguard Worker   const std::byte image_data[kMaxImageDataSize] = { ... };
220*61c4878aSAndroid Build Coastguard Worker
221*61c4878aSAndroid Build Coastguard Worker   Store::Message store{};
222*61c4878aSAndroid Build Coastguard Worker   // Calling SetEncoder means we must always extend the buffer size.
223*61c4878aSAndroid Build Coastguard Worker   store.image_data.SetEncoder([](Store::StreamEncoder& encoder) {
224*61c4878aSAndroid Build Coastguard Worker     return encoder.WriteImageData(image_data);
225*61c4878aSAndroid Build Coastguard Worker   });
226*61c4878aSAndroid Build Coastguard Worker
227*61c4878aSAndroid Build Coastguard Worker   std::byte buffer[Store::kMaxEncodedSizeBytes + kMaxImageDataSize];
228*61c4878aSAndroid Build Coastguard Worker   Store::MemoryEncoder encoder(buffer);
229*61c4878aSAndroid Build Coastguard Worker   const auto status = encoder.Write(store);
230*61c4878aSAndroid Build Coastguard Worker
231*61c4878aSAndroid Build Coastguard Worker   // Always check the encoder status or return values from Write calls.
232*61c4878aSAndroid Build Coastguard Worker   if (!status.ok()) {
233*61c4878aSAndroid Build Coastguard Worker     PW_LOG_INFO("Failed to encode proto; %s", encoder.status().str());
234*61c4878aSAndroid Build Coastguard Worker   }
235*61c4878aSAndroid Build Coastguard Worker
236*61c4878aSAndroid Build Coastguard WorkerOr when using a variable number of repeated submessages, where the maximum
237*61c4878aSAndroid Build Coastguard Workernumber is known to your code but not to the proto, you can add the constants
238*61c4878aSAndroid Build Coastguard Workerfrom one message type to another:
239*61c4878aSAndroid Build Coastguard Worker
240*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
241*61c4878aSAndroid Build Coastguard Worker
242*61c4878aSAndroid Build Coastguard Worker   #include "example_protos/person.pwpb.h"
243*61c4878aSAndroid Build Coastguard Worker
244*61c4878aSAndroid Build Coastguard Worker   Person::Message grandchild{};
245*61c4878aSAndroid Build Coastguard Worker   // Calling SetEncoder means we must always extend the buffer size.
246*61c4878aSAndroid Build Coastguard Worker   grandchild.grandparent.SetEncoder([](Person::StreamEncoder& encoder) {
247*61c4878aSAndroid Build Coastguard Worker     PW_TRY(encoder.GetGrandparentEncoder().Write(maternal_grandma));
248*61c4878aSAndroid Build Coastguard Worker     PW_TRY(encoder.GetGrandparentEncoder().Write(maternal_grandpa));
249*61c4878aSAndroid Build Coastguard Worker     PW_TRY(encoder.GetGrandparentEncoder().Write(paternal_grandma));
250*61c4878aSAndroid Build Coastguard Worker     PW_TRY(encoder.GetGrandparentEncoder().Write(paternal_grandpa));
251*61c4878aSAndroid Build Coastguard Worker     return pw::OkStatus();
252*61c4878aSAndroid Build Coastguard Worker   });
253*61c4878aSAndroid Build Coastguard Worker
254*61c4878aSAndroid Build Coastguard Worker   std::byte buffer[Person::kMaxEncodedSizeBytes +
255*61c4878aSAndroid Build Coastguard Worker                    Grandparent::kMaxEncodedSizeBytes * 4];
256*61c4878aSAndroid Build Coastguard Worker   Person::MemoryEncoder encoder(buffer);
257*61c4878aSAndroid Build Coastguard Worker   const auto status = encoder.Write(grandchild);
258*61c4878aSAndroid Build Coastguard Worker
259*61c4878aSAndroid Build Coastguard Worker   // Always check the encoder status or return values from Write calls.
260*61c4878aSAndroid Build Coastguard Worker   if (!status.ok()) {
261*61c4878aSAndroid Build Coastguard Worker     PW_LOG_INFO("Failed to encode proto; %s", encoder.status().str());
262*61c4878aSAndroid Build Coastguard Worker   }
263*61c4878aSAndroid Build Coastguard Worker
264*61c4878aSAndroid Build Coastguard Worker.. warning::
265*61c4878aSAndroid Build Coastguard Worker  Encoding to a buffer that is insufficiently large will return
266*61c4878aSAndroid Build Coastguard Worker  ``Status::ResourceExhausted()`` from ``Write`` calls, and from the
267*61c4878aSAndroid Build Coastguard Worker  encoder's ``status()`` call. Always check the status of calls or the encoder,
268*61c4878aSAndroid Build Coastguard Worker  as in the case of error, the encoded data will be invalid.
269*61c4878aSAndroid Build Coastguard Worker
270*61c4878aSAndroid Build Coastguard Worker.. _pw_protobuf-message-limitations:
271*61c4878aSAndroid Build Coastguard Worker
272*61c4878aSAndroid Build Coastguard WorkerLimitations
273*61c4878aSAndroid Build Coastguard Worker-----------
274*61c4878aSAndroid Build Coastguard Worker``pw_protobuf``'s message structure API is incomplete. Generally speaking, it is
275*61c4878aSAndroid Build Coastguard Workerreasonable to use for basic messages containing simple inline fields (scalar
276*61c4878aSAndroid Build Coastguard Workertypes, bytes, and strings) and nested messages of similar form. Beyond this,
277*61c4878aSAndroid Build Coastguard Workercertain other types of protobuf specifiers can be used, but may be limited in
278*61c4878aSAndroid Build Coastguard Workerhow and when they are supported. These cases are described below.
279*61c4878aSAndroid Build Coastguard Worker
280*61c4878aSAndroid Build Coastguard WorkerIf an object representation of protobuf messages is desired, the Pigweed team
281*61c4878aSAndroid Build Coastguard Workerrecommends using `Nanopb`_, which is fully supported within Pigweed's build and
282*61c4878aSAndroid Build Coastguard WorkerRPC systems.
283*61c4878aSAndroid Build Coastguard Worker
284*61c4878aSAndroid Build Coastguard WorkerMessage structures are eventually intended to be replaced with an alternative
285*61c4878aSAndroid Build Coastguard Workerobject model. See `SEED-0103 <http://pwrev.dev/133971>`_ for additional
286*61c4878aSAndroid Build Coastguard Workerinformation about how message structures came to be and our future plans.
287*61c4878aSAndroid Build Coastguard Worker
288*61c4878aSAndroid Build Coastguard WorkerProtobuf versioning
289*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^^^^^^^^
290*61c4878aSAndroid Build Coastguard WorkerMessage structures are generated in accordance to ``proto3`` semantics only.
291*61c4878aSAndroid Build Coastguard WorkerUnset fields default to their zero values. Explicit field presence is supported
292*61c4878aSAndroid Build Coastguard Workerthrough the use of the ``optional`` specifier. Proto2-only keywords such as
293*61c4878aSAndroid Build Coastguard Worker``required`` have no effect.
294*61c4878aSAndroid Build Coastguard Worker
295*61c4878aSAndroid Build Coastguard WorkerThere is limited preliminary support for Protobuf editions, primarily to allow
296*61c4878aSAndroid Build Coastguard Workereditions-based proto files to compile. At this time, the only editions feature
297*61c4878aSAndroid Build Coastguard Workersupported by the code generator is ``field_presence``.
298*61c4878aSAndroid Build Coastguard Worker
299*61c4878aSAndroid Build Coastguard Worker``oneof`` fields
300*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^^^^^
301*61c4878aSAndroid Build Coastguard Worker``oneof`` protobuf fields cannot be inlined within a message structure: they
302*61c4878aSAndroid Build Coastguard Workermust be encoded and decoded using callbacks.
303*61c4878aSAndroid Build Coastguard Worker
304*61c4878aSAndroid Build Coastguard Worker``optional`` fields
305*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^^^^^^^^
306*61c4878aSAndroid Build Coastguard WorkerOnly scalar fields generate a ``std::optional`` wrapper in the resulting message
307*61c4878aSAndroid Build Coastguard Workerstructure. Optional submessages or variable-length fields
308*61c4878aSAndroid Build Coastguard Worker(``string`` / ``bytes``) must be processed through callbacks, requiring manual
309*61c4878aSAndroid Build Coastguard Workertracking of presence depending on whether or not the callback is invoked.
310*61c4878aSAndroid Build Coastguard Worker
311*61c4878aSAndroid Build Coastguard Worker.. _pw_protobuf-per-field-apis:
312*61c4878aSAndroid Build Coastguard Worker
313*61c4878aSAndroid Build Coastguard WorkerPer-Field Writers and Readers
314*61c4878aSAndroid Build Coastguard Worker=============================
315*61c4878aSAndroid Build Coastguard WorkerThe middle level API is based around typed methods to write and read each
316*61c4878aSAndroid Build Coastguard Workerfield of the message directly to the final serialized form, again created
317*61c4878aSAndroid Build Coastguard Workerthrough C++ code generation.
318*61c4878aSAndroid Build Coastguard Worker
319*61c4878aSAndroid Build Coastguard WorkerEncoding
320*61c4878aSAndroid Build Coastguard Worker--------
321*61c4878aSAndroid Build Coastguard WorkerGiven the same message structure, in addition to the ``Write()`` method that
322*61c4878aSAndroid Build Coastguard Workeraccepts a message structure, the following additional methods are also
323*61c4878aSAndroid Build Coastguard Workergenerated in the typed ``StreamEncoder`` class.
324*61c4878aSAndroid Build Coastguard Worker
325*61c4878aSAndroid Build Coastguard WorkerThere are lightweight wrappers around the core implementation, calling the
326*61c4878aSAndroid Build Coastguard Workerunderlying methods with the correct field numbers and value types, and result
327*61c4878aSAndroid Build Coastguard Workerin no additional binary code over correctly using the core implementation.
328*61c4878aSAndroid Build Coastguard Worker
329*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
330*61c4878aSAndroid Build Coastguard Worker
331*61c4878aSAndroid Build Coastguard Worker   class Customer::StreamEncoder : pw::protobuf::StreamEncoder {
332*61c4878aSAndroid Build Coastguard Worker    public:
333*61c4878aSAndroid Build Coastguard Worker     // Message Structure Writer.
334*61c4878aSAndroid Build Coastguard Worker     pw::Status Write(const Customer::Message&);
335*61c4878aSAndroid Build Coastguard Worker
336*61c4878aSAndroid Build Coastguard Worker     // Per-Field Typed Writers.
337*61c4878aSAndroid Build Coastguard Worker     pw::Status WriteAge(int32_t);
338*61c4878aSAndroid Build Coastguard Worker
339*61c4878aSAndroid Build Coastguard Worker     pw::Status WriteName(std::string_view);
340*61c4878aSAndroid Build Coastguard Worker     pw::Status WriteName(const char*, size_t);
341*61c4878aSAndroid Build Coastguard Worker
342*61c4878aSAndroid Build Coastguard Worker     pw::Status WriteStatus(Customer::Status);
343*61c4878aSAndroid Build Coastguard Worker   };
344*61c4878aSAndroid Build Coastguard Worker
345*61c4878aSAndroid Build Coastguard WorkerSo the same encoding method could be written as:
346*61c4878aSAndroid Build Coastguard Worker
347*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
348*61c4878aSAndroid Build Coastguard Worker
349*61c4878aSAndroid Build Coastguard Worker   #include "example_protos/customer.pwpb.h"
350*61c4878aSAndroid Build Coastguard Worker
351*61c4878aSAndroid Build Coastguard Worker   Status EncodeCustomer(Customer::StreamEncoder& encoder) {
352*61c4878aSAndroid Build Coastguard Worker     PW_TRY(encoder.WriteAge(33));
353*61c4878aSAndroid Build Coastguard Worker     PW_TRY(encoder.WriteName("Joe Bloggs"sv));
354*61c4878aSAndroid Build Coastguard Worker     PW_TRY(encoder.WriteStatus(Customer::Status::INACTIVE));
355*61c4878aSAndroid Build Coastguard Worker   }
356*61c4878aSAndroid Build Coastguard Worker
357*61c4878aSAndroid Build Coastguard WorkerPigweed's protobuf encoders encode directly to the wire format of a proto rather
358*61c4878aSAndroid Build Coastguard Workerthan staging information to a mutable datastructure. This means any writes of a
359*61c4878aSAndroid Build Coastguard Workervalue are final, and can't be referenced or modified as a later step in the
360*61c4878aSAndroid Build Coastguard Workerencode process.
361*61c4878aSAndroid Build Coastguard Worker
362*61c4878aSAndroid Build Coastguard WorkerCasting between generated StreamEncoder types
363*61c4878aSAndroid Build Coastguard Worker^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
364*61c4878aSAndroid Build Coastguard Workerpw_protobuf guarantees that all generated ``StreamEncoder`` classes can be
365*61c4878aSAndroid Build Coastguard Workerconverted among each other. It's also safe to convert any ``MemoryEncoder`` to
366*61c4878aSAndroid Build Coastguard Workerany other ``StreamEncoder``.
367*61c4878aSAndroid Build Coastguard Worker
368*61c4878aSAndroid Build Coastguard WorkerThis guarantee exists to facilitate usage of protobuf overlays. Protobuf
369*61c4878aSAndroid Build Coastguard Workeroverlays are protobuf message definitions that deliberately ensure that
370*61c4878aSAndroid Build Coastguard Workerfields defined in one message will not conflict with fields defined in other
371*61c4878aSAndroid Build Coastguard Workermessages.
372*61c4878aSAndroid Build Coastguard Worker
373*61c4878aSAndroid Build Coastguard WorkerFor example:
374*61c4878aSAndroid Build Coastguard Worker
375*61c4878aSAndroid Build Coastguard Worker.. code-block:: protobuf
376*61c4878aSAndroid Build Coastguard Worker
377*61c4878aSAndroid Build Coastguard Worker   // The first half of the overlaid message.
378*61c4878aSAndroid Build Coastguard Worker   message BaseMessage {
379*61c4878aSAndroid Build Coastguard Worker     uint32 length = 1;
380*61c4878aSAndroid Build Coastguard Worker     reserved 2;  // Reserved for Overlay
381*61c4878aSAndroid Build Coastguard Worker   }
382*61c4878aSAndroid Build Coastguard Worker
383*61c4878aSAndroid Build Coastguard Worker   // OK: The second half of the overlaid message.
384*61c4878aSAndroid Build Coastguard Worker   message Overlay {
385*61c4878aSAndroid Build Coastguard Worker     reserved 1;  // Reserved for BaseMessage
386*61c4878aSAndroid Build Coastguard Worker     uint32 height = 2;
387*61c4878aSAndroid Build Coastguard Worker   }
388*61c4878aSAndroid Build Coastguard Worker
389*61c4878aSAndroid Build Coastguard Worker   // OK: A message that overlays and bundles both types together.
390*61c4878aSAndroid Build Coastguard Worker   message Both {
391*61c4878aSAndroid Build Coastguard Worker     uint32 length = 1;  // Defined independently by BaseMessage
392*61c4878aSAndroid Build Coastguard Worker     uint32 height = 2;  // Defined independently by Overlay
393*61c4878aSAndroid Build Coastguard Worker   }
394*61c4878aSAndroid Build Coastguard Worker
395*61c4878aSAndroid Build Coastguard Worker   // BAD: Diverges from BaseMessage's definition, and can cause decode
396*61c4878aSAndroid Build Coastguard Worker   // errors/corruption.
397*61c4878aSAndroid Build Coastguard Worker   message InvalidOverlay {
398*61c4878aSAndroid Build Coastguard Worker     fixed32 length = 1;
399*61c4878aSAndroid Build Coastguard Worker   }
400*61c4878aSAndroid Build Coastguard Worker
401*61c4878aSAndroid Build Coastguard WorkerThe ``StreamEncoderCast<>()`` helper template reduces very messy casting into
402*61c4878aSAndroid Build Coastguard Workera much easier to read syntax:
403*61c4878aSAndroid Build Coastguard Worker
404*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
405*61c4878aSAndroid Build Coastguard Worker
406*61c4878aSAndroid Build Coastguard Worker   #include "pw_protobuf/encoder.h"
407*61c4878aSAndroid Build Coastguard Worker   #include "pw_protobuf_test_protos/full_test.pwpb.h"
408*61c4878aSAndroid Build Coastguard Worker
409*61c4878aSAndroid Build Coastguard Worker   Result<ConstByteSpan> EncodeOverlaid(uint32_t height,
410*61c4878aSAndroid Build Coastguard Worker                                        uint32_t length,
411*61c4878aSAndroid Build Coastguard Worker                                        ConstByteSpan encode_buffer) {
412*61c4878aSAndroid Build Coastguard Worker     BaseMessage::MemoryEncoder base(encode_buffer);
413*61c4878aSAndroid Build Coastguard Worker
414*61c4878aSAndroid Build Coastguard Worker     // Without StreamEncoderCast<>(), this line would be:
415*61c4878aSAndroid Build Coastguard Worker     //   Overlay::StreamEncoder& overlay =
416*61c4878aSAndroid Build Coastguard Worker     //       *static_cast<Overlay::StreamEncoder*>(
417*61c4878aSAndroid Build Coastguard Worker     //           static_cast<pw::protobuf::StreamEncoder*>(&base)
418*61c4878aSAndroid Build Coastguard Worker     Overlay::StreamEncoder& overlay =
419*61c4878aSAndroid Build Coastguard Worker         StreamEncoderCast<Overlay::StreamEncoder>(base);
420*61c4878aSAndroid Build Coastguard Worker     if (!overlay.WriteHeight(height).ok()) {
421*61c4878aSAndroid Build Coastguard Worker       return overlay.status();
422*61c4878aSAndroid Build Coastguard Worker     }
423*61c4878aSAndroid Build Coastguard Worker     if (!base.WriteLength(length).ok()) {
424*61c4878aSAndroid Build Coastguard Worker       return base.status();
425*61c4878aSAndroid Build Coastguard Worker     }
426*61c4878aSAndroid Build Coastguard Worker     return ConstByteSpan(base);
427*61c4878aSAndroid Build Coastguard Worker   }
428*61c4878aSAndroid Build Coastguard Worker
429*61c4878aSAndroid Build Coastguard WorkerWhile this use case is somewhat uncommon, it's a core supported use case of
430*61c4878aSAndroid Build Coastguard Workerpw_protobuf.
431*61c4878aSAndroid Build Coastguard Worker
432*61c4878aSAndroid Build Coastguard Worker.. warning::
433*61c4878aSAndroid Build Coastguard Worker
434*61c4878aSAndroid Build Coastguard Worker   Using this to convert one stream encoder to another when the messages
435*61c4878aSAndroid Build Coastguard Worker   themselves do not safely overlay will result in corrupt protos. Be careful
436*61c4878aSAndroid Build Coastguard Worker   when doing this as there's no compile-time way to detect whether or not two
437*61c4878aSAndroid Build Coastguard Worker   messages are meant to overlay.
438*61c4878aSAndroid Build Coastguard Worker
439*61c4878aSAndroid Build Coastguard WorkerDecoding
440*61c4878aSAndroid Build Coastguard Worker--------
441*61c4878aSAndroid Build Coastguard WorkerFor decoding, in addition to the ``Read()`` method that populates a message
442*61c4878aSAndroid Build Coastguard Workerstructure, the following additional methods are also generated in the typed
443*61c4878aSAndroid Build Coastguard Worker``StreamDecoder`` class.
444*61c4878aSAndroid Build Coastguard Worker
445*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
446*61c4878aSAndroid Build Coastguard Worker
447*61c4878aSAndroid Build Coastguard Worker   class Customer::StreamDecoder : pw::protobuf::StreamDecoder {
448*61c4878aSAndroid Build Coastguard Worker    public:
449*61c4878aSAndroid Build Coastguard Worker     // Message Structure Reader.
450*61c4878aSAndroid Build Coastguard Worker     pw::Status Read(Customer::Message&);
451*61c4878aSAndroid Build Coastguard Worker
452*61c4878aSAndroid Build Coastguard Worker     // Returns the identity of the current field.
453*61c4878aSAndroid Build Coastguard Worker     ::pw::Result<Fields> Field();
454*61c4878aSAndroid Build Coastguard Worker
455*61c4878aSAndroid Build Coastguard Worker     // Per-Field Typed Readers.
456*61c4878aSAndroid Build Coastguard Worker     pw::Result<int32_t> ReadAge();
457*61c4878aSAndroid Build Coastguard Worker
458*61c4878aSAndroid Build Coastguard Worker     pw::StatusWithSize ReadName(pw::span<char>);
459*61c4878aSAndroid Build Coastguard Worker     BytesReader GetNameReader(); // Read name as a stream of bytes.
460*61c4878aSAndroid Build Coastguard Worker
461*61c4878aSAndroid Build Coastguard Worker     pw::Result<Customer::Status> ReadStatus();
462*61c4878aSAndroid Build Coastguard Worker   };
463*61c4878aSAndroid Build Coastguard Worker
464*61c4878aSAndroid Build Coastguard WorkerComplete and correct decoding requires looping through the fields, so is more
465*61c4878aSAndroid Build Coastguard Workercomplex than encoding or using the message structure.
466*61c4878aSAndroid Build Coastguard Worker
467*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
468*61c4878aSAndroid Build Coastguard Worker
469*61c4878aSAndroid Build Coastguard Worker   pw::Status DecodeCustomer(Customer::StreamDecoder& decoder) {
470*61c4878aSAndroid Build Coastguard Worker     uint32_t age;
471*61c4878aSAndroid Build Coastguard Worker     char name[32];
472*61c4878aSAndroid Build Coastguard Worker     Customer::Status status;
473*61c4878aSAndroid Build Coastguard Worker
474*61c4878aSAndroid Build Coastguard Worker     while ((status = decoder.Next()).ok()) {
475*61c4878aSAndroid Build Coastguard Worker       switch (decoder.Field().value()) {
476*61c4878aSAndroid Build Coastguard Worker         case Customer::Fields::kAge: {
477*61c4878aSAndroid Build Coastguard Worker           PW_TRY_ASSIGN(age, decoder.ReadAge());
478*61c4878aSAndroid Build Coastguard Worker           break;
479*61c4878aSAndroid Build Coastguard Worker         }
480*61c4878aSAndroid Build Coastguard Worker         case Customer::Fields::kName: {
481*61c4878aSAndroid Build Coastguard Worker           PW_TRY(decoder.ReadName(name));
482*61c4878aSAndroid Build Coastguard Worker           break;
483*61c4878aSAndroid Build Coastguard Worker         }
484*61c4878aSAndroid Build Coastguard Worker         case Customer::Fields::kStatus: {
485*61c4878aSAndroid Build Coastguard Worker           PW_TRY_ASSIGN(status, decoder.ReadStatus());
486*61c4878aSAndroid Build Coastguard Worker           break;
487*61c4878aSAndroid Build Coastguard Worker         }
488*61c4878aSAndroid Build Coastguard Worker       }
489*61c4878aSAndroid Build Coastguard Worker     }
490*61c4878aSAndroid Build Coastguard Worker
491*61c4878aSAndroid Build Coastguard Worker     return status.IsOutOfRange() ? OkStatus() : status;
492*61c4878aSAndroid Build Coastguard Worker   }
493*61c4878aSAndroid Build Coastguard Worker
494*61c4878aSAndroid Build Coastguard Worker.. warning:: ``Fields::SNAKE_CASE`` is deprecated. Use ``Fields::kCamelCase``.
495*61c4878aSAndroid Build Coastguard Worker
496*61c4878aSAndroid Build Coastguard Worker   Transitional support for ``Fields::SNAKE_CASE`` will soon only be available by
497*61c4878aSAndroid Build Coastguard Worker   explicitly setting the following GN variable in your project:
498*61c4878aSAndroid Build Coastguard Worker   ``pw_protobuf_compiler_GENERATE_LEGACY_ENUM_SNAKE_CASE_NAMES=true``
499*61c4878aSAndroid Build Coastguard Worker
500*61c4878aSAndroid Build Coastguard Worker   This support will be removed after downstream projects have been migrated.
501*61c4878aSAndroid Build Coastguard Worker
502*61c4878aSAndroid Build Coastguard Worker.. _module-pw_protobuf-read:
503*61c4878aSAndroid Build Coastguard Worker
504*61c4878aSAndroid Build Coastguard WorkerReading a single field
505*61c4878aSAndroid Build Coastguard Worker----------------------
506*61c4878aSAndroid Build Coastguard WorkerSometimes, only a single field from a serialized message needs to be read. In
507*61c4878aSAndroid Build Coastguard Workerthese cases, setting up a decoder and iterating through the message is a lot of
508*61c4878aSAndroid Build Coastguard Workerboilerplate. ``pw_protobuf`` generates convenient ``Find*()`` functions for
509*61c4878aSAndroid Build Coastguard Workermost fields in a message which handle this for you.
510*61c4878aSAndroid Build Coastguard Worker
511*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
512*61c4878aSAndroid Build Coastguard Worker
513*61c4878aSAndroid Build Coastguard Worker   pw::Status ReadCustomerData(pw::ConstByteSpan serialized_customer) {
514*61c4878aSAndroid Build Coastguard Worker     pw::Result<uint32_t> age = Customer::FindAge(serialized_customer);
515*61c4878aSAndroid Build Coastguard Worker     if (!age.ok()) {
516*61c4878aSAndroid Build Coastguard Worker       return age.status();
517*61c4878aSAndroid Build Coastguard Worker     }
518*61c4878aSAndroid Build Coastguard Worker
519*61c4878aSAndroid Build Coastguard Worker     // This will scan the buffer again from the start, which is less efficient
520*61c4878aSAndroid Build Coastguard Worker     // than writing a custom decoder loop.
521*61c4878aSAndroid Build Coastguard Worker     pw::Result<std::string_view> name = Customer::FindName(serialized_customer);
522*61c4878aSAndroid Build Coastguard Worker     if (!age.ok()) {
523*61c4878aSAndroid Build Coastguard Worker       return age.status();
524*61c4878aSAndroid Build Coastguard Worker     }
525*61c4878aSAndroid Build Coastguard Worker
526*61c4878aSAndroid Build Coastguard Worker     DoStuff(age, name);
527*61c4878aSAndroid Build Coastguard Worker     return pw::OkStatus();
528*61c4878aSAndroid Build Coastguard Worker   }
529*61c4878aSAndroid Build Coastguard Worker
530*61c4878aSAndroid Build Coastguard WorkerThe ``Find`` APIs also work with streamed data, as shown below.
531*61c4878aSAndroid Build Coastguard Worker
532*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
533*61c4878aSAndroid Build Coastguard Worker
534*61c4878aSAndroid Build Coastguard Worker   pw::Status ReadCustomerData(pw::stream::Reader& customer_stream) {
535*61c4878aSAndroid Build Coastguard Worker     pw::Result<uint32_t> age = Customer::FindAge(customer_stream);
536*61c4878aSAndroid Build Coastguard Worker     if (!age.ok()) {
537*61c4878aSAndroid Build Coastguard Worker       return age.status();
538*61c4878aSAndroid Build Coastguard Worker     }
539*61c4878aSAndroid Build Coastguard Worker
540*61c4878aSAndroid Build Coastguard Worker     // This will begin scanning for `name` from the current position of the
541*61c4878aSAndroid Build Coastguard Worker     // stream (following the `age` field). If `name` appeared before `age` in
542*61c4878aSAndroid Build Coastguard Worker     // the serialized data, it will not be found.
543*61c4878aSAndroid Build Coastguard Worker     //
544*61c4878aSAndroid Build Coastguard Worker     // Note that unlike with the buffer APIs, stream Find methods copy `string`
545*61c4878aSAndroid Build Coastguard Worker     // and `bytes` fields into a user-provided buffer.
546*61c4878aSAndroid Build Coastguard Worker     char name[32];
547*61c4878aSAndroid Build Coastguard Worker     pw::StatusWithSize sws = Customer::FindName(serialized_customer, name);
548*61c4878aSAndroid Build Coastguard Worker     if (!sws.ok()) {
549*61c4878aSAndroid Build Coastguard Worker       return sws.status();
550*61c4878aSAndroid Build Coastguard Worker     }
551*61c4878aSAndroid Build Coastguard Worker     if (sws.size() >= sizeof(name)) {
552*61c4878aSAndroid Build Coastguard Worker       return pw::Status::OutOfRange();
553*61c4878aSAndroid Build Coastguard Worker     }
554*61c4878aSAndroid Build Coastguard Worker     name[sws.size()] = '\0';
555*61c4878aSAndroid Build Coastguard Worker
556*61c4878aSAndroid Build Coastguard Worker     DoStuff(age, name);
557*61c4878aSAndroid Build Coastguard Worker     return pw::OkStatus();
558*61c4878aSAndroid Build Coastguard Worker   }
559*61c4878aSAndroid Build Coastguard Worker
560*61c4878aSAndroid Build Coastguard Worker``Find`` APIs can also be used to iterate over occurrences of a repeated field.
561*61c4878aSAndroid Build Coastguard WorkerFor example, given the protobuf definition:
562*61c4878aSAndroid Build Coastguard Worker
563*61c4878aSAndroid Build Coastguard Worker.. code-block:: proto
564*61c4878aSAndroid Build Coastguard Worker
565*61c4878aSAndroid Build Coastguard Worker   message Samples {
566*61c4878aSAndroid Build Coastguard Worker     repeated uint32 raw_values = 1;
567*61c4878aSAndroid Build Coastguard Worker   }
568*61c4878aSAndroid Build Coastguard Worker
569*61c4878aSAndroid Build Coastguard WorkerThe ``raw_values`` field can be iterated over as follows:
570*61c4878aSAndroid Build Coastguard Worker
571*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
572*61c4878aSAndroid Build Coastguard Worker
573*61c4878aSAndroid Build Coastguard Worker   pw::Status ReadSamples(pw::ConstByteSpan serialized_samples) {
574*61c4878aSAndroid Build Coastguard Worker     pw::protobuf::Uint32Finder raw_values =
575*61c4878aSAndroid Build Coastguard Worker         Samples::FindRawValues(serialized_samples);
576*61c4878aSAndroid Build Coastguard Worker     for (Result<int32_t> val = finder.Next(); val.ok(); val = finder.Next()) {
577*61c4878aSAndroid Build Coastguard Worker       ConsumeValue(*val);
578*61c4878aSAndroid Build Coastguard Worker     }
579*61c4878aSAndroid Build Coastguard Worker   }
580*61c4878aSAndroid Build Coastguard Worker
581*61c4878aSAndroid Build Coastguard Worker.. note::
582*61c4878aSAndroid Build Coastguard Worker
583*61c4878aSAndroid Build Coastguard Worker   Each call to ``Find*()`` linearly scans through the message. If you have to
584*61c4878aSAndroid Build Coastguard Worker   read multiple fields, it is more efficient to instantiate your own decoder as
585*61c4878aSAndroid Build Coastguard Worker   described above.
586*61c4878aSAndroid Build Coastguard Worker
587*61c4878aSAndroid Build Coastguard Worker
588*61c4878aSAndroid Build Coastguard WorkerDirect Writers and Readers
589*61c4878aSAndroid Build Coastguard Worker==========================
590*61c4878aSAndroid Build Coastguard WorkerThe lowest level API is provided by the core C++ implementation, and requires
591*61c4878aSAndroid Build Coastguard Workerthe caller to provide the correct field number and value types for encoding, or
592*61c4878aSAndroid Build Coastguard Workercheck the same when decoding.
593*61c4878aSAndroid Build Coastguard Worker
594*61c4878aSAndroid Build Coastguard WorkerEncoding
595*61c4878aSAndroid Build Coastguard Worker--------
596*61c4878aSAndroid Build Coastguard WorkerThe two fundamental classes are ``MemoryEncoder`` which directly encodes a proto
597*61c4878aSAndroid Build Coastguard Workerto an in-memory buffer, and ``StreamEncoder`` that operates on
598*61c4878aSAndroid Build Coastguard Worker``pw::stream::Writer`` objects to serialize proto data.
599*61c4878aSAndroid Build Coastguard Worker
600*61c4878aSAndroid Build Coastguard Worker``StreamEncoder`` allows you encode a proto to something like ``pw::sys_io``
601*61c4878aSAndroid Build Coastguard Workerwithout needing to build the complete message in memory
602*61c4878aSAndroid Build Coastguard Worker
603*61c4878aSAndroid Build Coastguard WorkerTo encode the same message we've used in the examples thus far, we would use
604*61c4878aSAndroid Build Coastguard Workerthe following parts of the core API:
605*61c4878aSAndroid Build Coastguard Worker
606*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
607*61c4878aSAndroid Build Coastguard Worker
608*61c4878aSAndroid Build Coastguard Worker   class pw::protobuf::StreamEncoder {
609*61c4878aSAndroid Build Coastguard Worker    public:
610*61c4878aSAndroid Build Coastguard Worker     Status WriteInt32(uint32_t field_number, int32_t);
611*61c4878aSAndroid Build Coastguard Worker     Status WriteUint32(uint32_t field_number, uint32_t);
612*61c4878aSAndroid Build Coastguard Worker
613*61c4878aSAndroid Build Coastguard Worker     Status WriteString(uint32_t field_number, std::string_view);
614*61c4878aSAndroid Build Coastguard Worker     Status WriteString(uint32_t field_number, const char*, size_t);
615*61c4878aSAndroid Build Coastguard Worker
616*61c4878aSAndroid Build Coastguard Worker     // And many other methods, see pw_protobuf/encoder.h
617*61c4878aSAndroid Build Coastguard Worker   };
618*61c4878aSAndroid Build Coastguard Worker
619*61c4878aSAndroid Build Coastguard WorkerEncoding the same message requires that we specify the field numbers, which we
620*61c4878aSAndroid Build Coastguard Workercan hardcode, or supplement using the C++ code generated ``Fields`` enum, and
621*61c4878aSAndroid Build Coastguard Workercast the enumerated type.
622*61c4878aSAndroid Build Coastguard Worker
623*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
624*61c4878aSAndroid Build Coastguard Worker
625*61c4878aSAndroid Build Coastguard Worker   #include "pw_protobuf/encoder.h"
626*61c4878aSAndroid Build Coastguard Worker   #include "example_protos/customer.pwpb.h"
627*61c4878aSAndroid Build Coastguard Worker
628*61c4878aSAndroid Build Coastguard Worker   Status EncodeCustomer(pw::protobuf::StreamEncoder& encoder) {
629*61c4878aSAndroid Build Coastguard Worker     PW_TRY(encoder.WriteInt32(static_cast<uint32_t>(Customer::Fields::kAge),
630*61c4878aSAndroid Build Coastguard Worker                               33));
631*61c4878aSAndroid Build Coastguard Worker     PW_TRY(encoder.WriteString(static_cast<uint32_t>(Customer::Fields::kName),
632*61c4878aSAndroid Build Coastguard Worker                                "Joe Bloggs"sv));
633*61c4878aSAndroid Build Coastguard Worker     PW_TRY(encoder.WriteUint32(
634*61c4878aSAndroid Build Coastguard Worker         static_cast<uint32_t>(Customer::Fields::kStatus),
635*61c4878aSAndroid Build Coastguard Worker         static_cast<uint32_t>(Customer::Status::INACTIVE)));
636*61c4878aSAndroid Build Coastguard Worker   }
637*61c4878aSAndroid Build Coastguard Worker
638*61c4878aSAndroid Build Coastguard WorkerDecoding
639*61c4878aSAndroid Build Coastguard Worker--------
640*61c4878aSAndroid Build Coastguard Worker``StreamDecoder`` reads data from a ``pw::stream::Reader`` and mirrors the API
641*61c4878aSAndroid Build Coastguard Workerof the encoders.
642*61c4878aSAndroid Build Coastguard Worker
643*61c4878aSAndroid Build Coastguard WorkerTo decode the same message we would use the following parts of the core API:
644*61c4878aSAndroid Build Coastguard Worker
645*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
646*61c4878aSAndroid Build Coastguard Worker
647*61c4878aSAndroid Build Coastguard Worker   class pw::protobuf::StreamDecoder {
648*61c4878aSAndroid Build Coastguard Worker    public:
649*61c4878aSAndroid Build Coastguard Worker     // Returns the identity of the current field.
650*61c4878aSAndroid Build Coastguard Worker     ::pw::Result<uint32_t> FieldNumber();
651*61c4878aSAndroid Build Coastguard Worker
652*61c4878aSAndroid Build Coastguard Worker     Result<int32_t> ReadInt32();
653*61c4878aSAndroid Build Coastguard Worker     Result<uint32_t> ReadUint32();
654*61c4878aSAndroid Build Coastguard Worker
655*61c4878aSAndroid Build Coastguard Worker     StatusWithSize ReadString(pw::span<char>);
656*61c4878aSAndroid Build Coastguard Worker
657*61c4878aSAndroid Build Coastguard Worker     // And many other methods, see pw_protobuf/stream_decoder.h
658*61c4878aSAndroid Build Coastguard Worker   };
659*61c4878aSAndroid Build Coastguard Worker
660*61c4878aSAndroid Build Coastguard WorkerAs with the typed per-field API, complete and correct decoding requires looping
661*61c4878aSAndroid Build Coastguard Workerthrough the fields and checking the field numbers, along with casting types.
662*61c4878aSAndroid Build Coastguard Worker
663*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
664*61c4878aSAndroid Build Coastguard Worker
665*61c4878aSAndroid Build Coastguard Worker   pw::Status DecodeCustomer(pw::protobuf::StreamDecoder& decoder) {
666*61c4878aSAndroid Build Coastguard Worker     uint32_t age;
667*61c4878aSAndroid Build Coastguard Worker     char name[32];
668*61c4878aSAndroid Build Coastguard Worker     Customer::Status status;
669*61c4878aSAndroid Build Coastguard Worker
670*61c4878aSAndroid Build Coastguard Worker     while ((status = decoder.Next()).ok()) {
671*61c4878aSAndroid Build Coastguard Worker       switch (decoder.FieldNumber().value()) {
672*61c4878aSAndroid Build Coastguard Worker         case static_cast<uint32_t>(Customer::Fields::kAge): {
673*61c4878aSAndroid Build Coastguard Worker           PW_TRY_ASSIGN(age, decoder.ReadInt32());
674*61c4878aSAndroid Build Coastguard Worker           break;
675*61c4878aSAndroid Build Coastguard Worker         }
676*61c4878aSAndroid Build Coastguard Worker         case static_cast<uint32_t>(Customer::Fields::kName): {
677*61c4878aSAndroid Build Coastguard Worker           PW_TRY(decoder.ReadString(name));
678*61c4878aSAndroid Build Coastguard Worker           break;
679*61c4878aSAndroid Build Coastguard Worker         }
680*61c4878aSAndroid Build Coastguard Worker         case static_cast<uint32_t>(Customer::Fields::kStatus): {
681*61c4878aSAndroid Build Coastguard Worker           uint32_t status_value;
682*61c4878aSAndroid Build Coastguard Worker           PW_TRY_ASSIGN(status_value, decoder.ReadUint32());
683*61c4878aSAndroid Build Coastguard Worker           status = static_cast<Customer::Status>(status_value);
684*61c4878aSAndroid Build Coastguard Worker           break;
685*61c4878aSAndroid Build Coastguard Worker         }
686*61c4878aSAndroid Build Coastguard Worker       }
687*61c4878aSAndroid Build Coastguard Worker     }
688*61c4878aSAndroid Build Coastguard Worker
689*61c4878aSAndroid Build Coastguard Worker     return status.IsOutOfRange() ? OkStatus() : status;
690*61c4878aSAndroid Build Coastguard Worker   }
691*61c4878aSAndroid Build Coastguard Worker
692*61c4878aSAndroid Build Coastguard WorkerFind APIs
693*61c4878aSAndroid Build Coastguard Worker---------
694*61c4878aSAndroid Build Coastguard Worker
695*61c4878aSAndroid Build Coastguard Worker.. doxygenfile:: pw_protobuf/public/pw_protobuf/find.h
696*61c4878aSAndroid Build Coastguard Worker
697*61c4878aSAndroid Build Coastguard Worker
698*61c4878aSAndroid Build Coastguard WorkerHandling of packages
699*61c4878aSAndroid Build Coastguard Worker====================
700*61c4878aSAndroid Build Coastguard Worker
701*61c4878aSAndroid Build Coastguard WorkerPackage declarations in ``.proto`` files are converted to namespace
702*61c4878aSAndroid Build Coastguard Workerdeclarations. Unlike ``protoc``'s native C++ codegen, pw_protobuf appends an
703*61c4878aSAndroid Build Coastguard Workeradditional ``::pwpb`` namespace after the user-specified package name: for
704*61c4878aSAndroid Build Coastguard Workerexample, ``package my.cool.project`` becomes ``namespace
705*61c4878aSAndroid Build Coastguard Workermy::cool::project::pwpb``. We emit a different package name than stated, in
706*61c4878aSAndroid Build Coastguard Workerorder to avoid clashes for projects that link against multiple C++ proto
707*61c4878aSAndroid Build Coastguard Workerlibraries in the same library.
708*61c4878aSAndroid Build Coastguard Worker
709*61c4878aSAndroid Build Coastguard Worker..
710*61c4878aSAndroid Build Coastguard Worker  TODO: b/258832150 - Remove this section, if possible
711*61c4878aSAndroid Build Coastguard Worker
712*61c4878aSAndroid Build Coastguard WorkerIn some cases, pw_protobuf codegen may encounter external message references
713*61c4878aSAndroid Build Coastguard Workerduring parsing, where it is unable to resolve the package name of the message.
714*61c4878aSAndroid Build Coastguard WorkerIn these situations, the codegen is instead forced to emit the package name as
715*61c4878aSAndroid Build Coastguard Worker``pw::pwpb_xxx::my::cool::project``, where "pwpb_xxx" is the name of some
716*61c4878aSAndroid Build Coastguard Workerunspecified private namespace. Users are expected to manually identify the
717*61c4878aSAndroid Build Coastguard Workerintended namespace name of that symbol, as described above, and must not rely
718*61c4878aSAndroid Build Coastguard Workeron any such private namespaces, even if they appear in codegen output.
719*61c4878aSAndroid Build Coastguard Worker
720*61c4878aSAndroid Build Coastguard Worker-------
721*61c4878aSAndroid Build Coastguard WorkerCodegen
722*61c4878aSAndroid Build Coastguard Worker-------
723*61c4878aSAndroid Build Coastguard Workerpw_protobuf codegen integration is supported in GN, Bazel, and CMake.
724*61c4878aSAndroid Build Coastguard Worker
725*61c4878aSAndroid Build Coastguard Worker``pw_protobuf`` only supports targeting ``proto3`` syntax and its semantics.
726*61c4878aSAndroid Build Coastguard WorkerFiles which specify ``syntax = "proto2"`` will be treated as proto3, and any
727*61c4878aSAndroid Build Coastguard Workerproto2-specific options will be ignored.
728*61c4878aSAndroid Build Coastguard Worker
729*61c4878aSAndroid Build Coastguard Worker.. admonition:: Protobuf edition support
730*61c4878aSAndroid Build Coastguard Worker
731*61c4878aSAndroid Build Coastguard Worker   `Protobuf editions <https://protobuf.dev/editions/overview>`_ are the future
732*61c4878aSAndroid Build Coastguard Worker   of Protobuf versioning, replacing proto2 and proto3 with more granular code
733*61c4878aSAndroid Build Coastguard Worker   generation options. ``pw_protobuf`` has some basic support for editions, but
734*61c4878aSAndroid Build Coastguard Worker   it is still a work in progress.
735*61c4878aSAndroid Build Coastguard Worker
736*61c4878aSAndroid Build Coastguard WorkerThis module's codegen is available through the ``*.pwpb`` sub-target of a
737*61c4878aSAndroid Build Coastguard Worker``pw_proto_library`` in GN, CMake, and Bazel. See :ref:`pw_protobuf_compiler's
738*61c4878aSAndroid Build Coastguard Workerdocumentation <module-pw_protobuf_compiler>` for more information on build
739*61c4878aSAndroid Build Coastguard Workersystem integration for pw_protobuf codegen.
740*61c4878aSAndroid Build Coastguard Worker
741*61c4878aSAndroid Build Coastguard WorkerExample ``BUILD.gn``:
742*61c4878aSAndroid Build Coastguard Worker
743*61c4878aSAndroid Build Coastguard Worker.. code-block::
744*61c4878aSAndroid Build Coastguard Worker
745*61c4878aSAndroid Build Coastguard Worker   import("//build_overrides/pigweed.gni")
746*61c4878aSAndroid Build Coastguard Worker
747*61c4878aSAndroid Build Coastguard Worker   import("$dir_pw_build/target_types.gni")
748*61c4878aSAndroid Build Coastguard Worker   import("$dir_pw_protobuf_compiler/proto.gni")
749*61c4878aSAndroid Build Coastguard Worker
750*61c4878aSAndroid Build Coastguard Worker   # This target controls where the *.pwpb.h headers end up on the include path.
751*61c4878aSAndroid Build Coastguard Worker   # In this example, it's at "pet_daycare_protos/client.pwpb.h".
752*61c4878aSAndroid Build Coastguard Worker   pw_proto_library("pet_daycare_protos") {
753*61c4878aSAndroid Build Coastguard Worker     sources = [
754*61c4878aSAndroid Build Coastguard Worker       "pet_daycare_protos/client.proto",
755*61c4878aSAndroid Build Coastguard Worker     ]
756*61c4878aSAndroid Build Coastguard Worker   }
757*61c4878aSAndroid Build Coastguard Worker
758*61c4878aSAndroid Build Coastguard Worker   pw_source_set("example_client") {
759*61c4878aSAndroid Build Coastguard Worker     sources = [ "example_client.cc" ]
760*61c4878aSAndroid Build Coastguard Worker     deps = [
761*61c4878aSAndroid Build Coastguard Worker       ":pet_daycare_protos.pwpb",
762*61c4878aSAndroid Build Coastguard Worker       dir_pw_bytes,
763*61c4878aSAndroid Build Coastguard Worker       dir_pw_stream,
764*61c4878aSAndroid Build Coastguard Worker     ]
765*61c4878aSAndroid Build Coastguard Worker   }
766*61c4878aSAndroid Build Coastguard Worker
767*61c4878aSAndroid Build Coastguard Worker-------------
768*61c4878aSAndroid Build Coastguard WorkerConfiguration
769*61c4878aSAndroid Build Coastguard Worker-------------
770*61c4878aSAndroid Build Coastguard Worker``pw_protobuf`` supports the following configuration options.
771*61c4878aSAndroid Build Coastguard Worker
772*61c4878aSAndroid Build Coastguard Worker* ``PW_PROTOBUF_CFG_MAX_VARINT_SIZE``:
773*61c4878aSAndroid Build Coastguard Worker  When encoding nested messages, the number of bytes to reserve for the varint
774*61c4878aSAndroid Build Coastguard Worker  submessage length. Nested messages are limited in size to the maximum value
775*61c4878aSAndroid Build Coastguard Worker  that can be varint-encoded into this reserved space.
776*61c4878aSAndroid Build Coastguard Worker
777*61c4878aSAndroid Build Coastguard Worker  The values that can be set, and their corresponding maximum submessage
778*61c4878aSAndroid Build Coastguard Worker  lengths, are outlined below.
779*61c4878aSAndroid Build Coastguard Worker
780*61c4878aSAndroid Build Coastguard Worker  +-------------------+----------------------------------------+
781*61c4878aSAndroid Build Coastguard Worker  | MAX_VARINT_SIZE   | Maximum submessage length              |
782*61c4878aSAndroid Build Coastguard Worker  +===================+========================================+
783*61c4878aSAndroid Build Coastguard Worker  | 1 byte            | 127                                    |
784*61c4878aSAndroid Build Coastguard Worker  +-------------------+----------------------------------------+
785*61c4878aSAndroid Build Coastguard Worker  | 2 bytes           | 16,383 or < 16KiB                      |
786*61c4878aSAndroid Build Coastguard Worker  +-------------------+----------------------------------------+
787*61c4878aSAndroid Build Coastguard Worker  | 3 bytes           | 2,097,151 or < 2048KiB                 |
788*61c4878aSAndroid Build Coastguard Worker  +-------------------+----------------------------------------+
789*61c4878aSAndroid Build Coastguard Worker  | 4 bytes (default) | 268,435,455 or < 256MiB                |
790*61c4878aSAndroid Build Coastguard Worker  +-------------------+----------------------------------------+
791*61c4878aSAndroid Build Coastguard Worker  | 5 bytes           | 4,294,967,295 or < 4GiB (max uint32_t) |
792*61c4878aSAndroid Build Coastguard Worker  +-------------------+----------------------------------------+
793*61c4878aSAndroid Build Coastguard Worker
794*61c4878aSAndroid Build Coastguard WorkerField Options
795*61c4878aSAndroid Build Coastguard Worker=============
796*61c4878aSAndroid Build Coastguard Worker``pw_protobuf`` supports the following field options for specifying
797*61c4878aSAndroid Build Coastguard Workerprotocol-level limitations, rather than code generation parameters (although
798*61c4878aSAndroid Build Coastguard Workerthey do influence code generation):
799*61c4878aSAndroid Build Coastguard Worker
800*61c4878aSAndroid Build Coastguard Worker
801*61c4878aSAndroid Build Coastguard Worker* ``max_count``:
802*61c4878aSAndroid Build Coastguard Worker  Maximum number of entries for repeated fields.
803*61c4878aSAndroid Build Coastguard Worker
804*61c4878aSAndroid Build Coastguard Worker* ``max_size``:
805*61c4878aSAndroid Build Coastguard Worker  Maximum size of `bytes` or `string` fields.
806*61c4878aSAndroid Build Coastguard Worker
807*61c4878aSAndroid Build Coastguard WorkerEven though other proto codegen implementations do not respect these field
808*61c4878aSAndroid Build Coastguard Workeroptions, they can still compile protos which use these options. This is
809*61c4878aSAndroid Build Coastguard Workerespecially useful for host builds using upstream protoc code generation, where
810*61c4878aSAndroid Build Coastguard Workerhost software can use the reflection API to query for the options and validate
811*61c4878aSAndroid Build Coastguard Workermessages comply with the specified limitations.
812*61c4878aSAndroid Build Coastguard Worker
813*61c4878aSAndroid Build Coastguard Worker.. code-block:: text
814*61c4878aSAndroid Build Coastguard Worker
815*61c4878aSAndroid Build Coastguard Worker   import "pw_protobuf_protos/field_options.proto";
816*61c4878aSAndroid Build Coastguard Worker
817*61c4878aSAndroid Build Coastguard Worker   message Demo {
818*61c4878aSAndroid Build Coastguard Worker     string size_limited_string = 1 [(pw.protobuf.pwpb).max_size = 16];
819*61c4878aSAndroid Build Coastguard Worker   };
820*61c4878aSAndroid Build Coastguard Worker
821*61c4878aSAndroid Build Coastguard WorkerOptions Files
822*61c4878aSAndroid Build Coastguard Worker=============
823*61c4878aSAndroid Build Coastguard WorkerCode generation can be configured using a separate ``.pwpb_options`` file placed
824*61c4878aSAndroid Build Coastguard Workeralongside the relevant ``.proto`` file.
825*61c4878aSAndroid Build Coastguard Worker
826*61c4878aSAndroid Build Coastguard WorkerThe format of this file is a series of fully qualified field names, or patterns,
827*61c4878aSAndroid Build Coastguard Workerfollowed by one or more options. Lines starting with ``#`` or ``//`` are
828*61c4878aSAndroid Build Coastguard Workercomments, and blank lines are ignored.
829*61c4878aSAndroid Build Coastguard Worker
830*61c4878aSAndroid Build Coastguard WorkerExample:
831*61c4878aSAndroid Build Coastguard Worker
832*61c4878aSAndroid Build Coastguard Worker.. code-block::
833*61c4878aSAndroid Build Coastguard Worker
834*61c4878aSAndroid Build Coastguard Worker   // Set an option for a specific field.
835*61c4878aSAndroid Build Coastguard Worker   fuzzy_friends.Client.visit_dates max_count:16
836*61c4878aSAndroid Build Coastguard Worker
837*61c4878aSAndroid Build Coastguard Worker   // Set options for multiple fields by wildcard matching.
838*61c4878aSAndroid Build Coastguard Worker   fuzzy_friends.Pet.* max_size:32
839*61c4878aSAndroid Build Coastguard Worker
840*61c4878aSAndroid Build Coastguard Worker   // Set multiple options in one go.
841*61c4878aSAndroid Build Coastguard Worker   fuzzy_friends.Dog.paws max_count:4 fixed_count:true
842*61c4878aSAndroid Build Coastguard Worker
843*61c4878aSAndroid Build Coastguard WorkerOptions files should be listed as ``inputs`` when defining ``pw_proto_library``,
844*61c4878aSAndroid Build Coastguard Workere.g.
845*61c4878aSAndroid Build Coastguard Worker
846*61c4878aSAndroid Build Coastguard Worker.. code-block::
847*61c4878aSAndroid Build Coastguard Worker
848*61c4878aSAndroid Build Coastguard Worker   pw_proto_library("pet_daycare_protos") {
849*61c4878aSAndroid Build Coastguard Worker     sources = [
850*61c4878aSAndroid Build Coastguard Worker       "pet_daycare_protos/client.proto",
851*61c4878aSAndroid Build Coastguard Worker     ]
852*61c4878aSAndroid Build Coastguard Worker     inputs = [
853*61c4878aSAndroid Build Coastguard Worker       "pet_daycare_protos/client.pwpb_options",
854*61c4878aSAndroid Build Coastguard Worker     ]
855*61c4878aSAndroid Build Coastguard Worker   }
856*61c4878aSAndroid Build Coastguard Worker
857*61c4878aSAndroid Build Coastguard WorkerValid options are:
858*61c4878aSAndroid Build Coastguard Worker
859*61c4878aSAndroid Build Coastguard Worker* ``max_count``:
860*61c4878aSAndroid Build Coastguard Worker  Maximum number of entries for repeated fields. When set, repeated scalar
861*61c4878aSAndroid Build Coastguard Worker  fields will use the ``pw::Vector`` container type instead of a callback.
862*61c4878aSAndroid Build Coastguard Worker
863*61c4878aSAndroid Build Coastguard Worker* ``fixed_count``:
864*61c4878aSAndroid Build Coastguard Worker  Specified with ``max_count`` to use a fixed length ``std::array`` container
865*61c4878aSAndroid Build Coastguard Worker  instead of ``pw::Vector``.
866*61c4878aSAndroid Build Coastguard Worker
867*61c4878aSAndroid Build Coastguard Worker* ``max_size``:
868*61c4878aSAndroid Build Coastguard Worker  Maximum size of `bytes` or `string` fields. When set, `bytes` fields use
869*61c4878aSAndroid Build Coastguard Worker  ``pw::Vector`` and `string` fields use ``pw::InlineString`` instead of a
870*61c4878aSAndroid Build Coastguard Worker  callback.
871*61c4878aSAndroid Build Coastguard Worker
872*61c4878aSAndroid Build Coastguard Worker* ``fixed_size``:
873*61c4878aSAndroid Build Coastguard Worker  Specified with ``max_size`` to use a fixed length ``std::array`` container
874*61c4878aSAndroid Build Coastguard Worker  instead of ``pw::Vector`` for `bytes` fields.
875*61c4878aSAndroid Build Coastguard Worker
876*61c4878aSAndroid Build Coastguard Worker* ``use_callback``:
877*61c4878aSAndroid Build Coastguard Worker  Replaces the structure member for the field with a callback function even
878*61c4878aSAndroid Build Coastguard Worker  where a simpler type could be used. This can be useful to ignore fields, to
879*61c4878aSAndroid Build Coastguard Worker  stop decoding of complex structures if certain values are not as expected, or
880*61c4878aSAndroid Build Coastguard Worker  to provide special handling for nested messages.
881*61c4878aSAndroid Build Coastguard Worker
882*61c4878aSAndroid Build Coastguard Worker.. admonition:: Rationale
883*61c4878aSAndroid Build Coastguard Worker
884*61c4878aSAndroid Build Coastguard Worker  The choice of a separate options file, over embedding options within the proto
885*61c4878aSAndroid Build Coastguard Worker  file, are driven by the need for proto files to be shared across multiple
886*61c4878aSAndroid Build Coastguard Worker  contexts.
887*61c4878aSAndroid Build Coastguard Worker
888*61c4878aSAndroid Build Coastguard Worker  A typical product would require the same proto be used on a hardware
889*61c4878aSAndroid Build Coastguard Worker  component, running Pigweed; a server-side component, running on a cloud
890*61c4878aSAndroid Build Coastguard Worker  platform; and an app component, running on a Phone OS.
891*61c4878aSAndroid Build Coastguard Worker
892*61c4878aSAndroid Build Coastguard Worker  While related, each of these will likely have different source projects and
893*61c4878aSAndroid Build Coastguard Worker  build systems.
894*61c4878aSAndroid Build Coastguard Worker
895*61c4878aSAndroid Build Coastguard Worker  Were the Pigweed options embedded in the protos, it would be necessary for
896*61c4878aSAndroid Build Coastguard Worker  both the cloud platform and Phone OS to be able to ``"import pigweed"`` ---
897*61c4878aSAndroid Build Coastguard Worker  and equivalently for options relevant to their platforms in the embedded
898*61c4878aSAndroid Build Coastguard Worker  software project.
899*61c4878aSAndroid Build Coastguard Worker
900*61c4878aSAndroid Build Coastguard Worker------------------
901*61c4878aSAndroid Build Coastguard WorkerMessage Structures
902*61c4878aSAndroid Build Coastguard Worker------------------
903*61c4878aSAndroid Build Coastguard WorkerThe C++ code generator creates a ``struct Message`` for each protobuf message
904*61c4878aSAndroid Build Coastguard Workerthat can hold the set of values encoded by it, following these rules.
905*61c4878aSAndroid Build Coastguard Worker
906*61c4878aSAndroid Build Coastguard Worker* Scalar fields are represented by their appropriate C++ type.
907*61c4878aSAndroid Build Coastguard Worker
908*61c4878aSAndroid Build Coastguard Worker  .. code-block:: protobuf
909*61c4878aSAndroid Build Coastguard Worker
910*61c4878aSAndroid Build Coastguard Worker     message Customer {
911*61c4878aSAndroid Build Coastguard Worker       int32 age = 1;
912*61c4878aSAndroid Build Coastguard Worker       uint32 birth_year = 2;
913*61c4878aSAndroid Build Coastguard Worker       sint64 rating = 3;
914*61c4878aSAndroid Build Coastguard Worker       bool is_active = 4;
915*61c4878aSAndroid Build Coastguard Worker     }
916*61c4878aSAndroid Build Coastguard Worker
917*61c4878aSAndroid Build Coastguard Worker  .. code-block:: c++
918*61c4878aSAndroid Build Coastguard Worker
919*61c4878aSAndroid Build Coastguard Worker     struct Customer::Message {
920*61c4878aSAndroid Build Coastguard Worker       int32_t age;
921*61c4878aSAndroid Build Coastguard Worker       uint32_t birth_year;
922*61c4878aSAndroid Build Coastguard Worker       int64_t rating;
923*61c4878aSAndroid Build Coastguard Worker       bool is_active;
924*61c4878aSAndroid Build Coastguard Worker     };
925*61c4878aSAndroid Build Coastguard Worker
926*61c4878aSAndroid Build Coastguard Worker* Enumerations are represented by a code generated namespaced proto enum.
927*61c4878aSAndroid Build Coastguard Worker
928*61c4878aSAndroid Build Coastguard Worker  .. code-block:: protobuf
929*61c4878aSAndroid Build Coastguard Worker
930*61c4878aSAndroid Build Coastguard Worker     message Award {
931*61c4878aSAndroid Build Coastguard Worker       enum Service {
932*61c4878aSAndroid Build Coastguard Worker         BRONZE = 1;
933*61c4878aSAndroid Build Coastguard Worker         SILVER = 2;
934*61c4878aSAndroid Build Coastguard Worker         GOLD = 3;
935*61c4878aSAndroid Build Coastguard Worker       }
936*61c4878aSAndroid Build Coastguard Worker       Service service = 1;
937*61c4878aSAndroid Build Coastguard Worker     }
938*61c4878aSAndroid Build Coastguard Worker
939*61c4878aSAndroid Build Coastguard Worker  .. code-block:: c++
940*61c4878aSAndroid Build Coastguard Worker
941*61c4878aSAndroid Build Coastguard Worker     enum class Award::Service : uint32_t {
942*61c4878aSAndroid Build Coastguard Worker       BRONZE = 1,
943*61c4878aSAndroid Build Coastguard Worker       SILVER = 2,
944*61c4878aSAndroid Build Coastguard Worker       GOLD = 3,
945*61c4878aSAndroid Build Coastguard Worker
946*61c4878aSAndroid Build Coastguard Worker       kBronze = BRONZE,
947*61c4878aSAndroid Build Coastguard Worker       kSilver = SILVER,
948*61c4878aSAndroid Build Coastguard Worker       kGold = GOLD,
949*61c4878aSAndroid Build Coastguard Worker     };
950*61c4878aSAndroid Build Coastguard Worker
951*61c4878aSAndroid Build Coastguard Worker     struct Award::Message {
952*61c4878aSAndroid Build Coastguard Worker       Award::Service service;
953*61c4878aSAndroid Build Coastguard Worker     };
954*61c4878aSAndroid Build Coastguard Worker
955*61c4878aSAndroid Build Coastguard Worker  Aliases to the enum values are also included in the "constant" style to match
956*61c4878aSAndroid Build Coastguard Worker  your preferred coding style. These aliases have any common prefix to the
957*61c4878aSAndroid Build Coastguard Worker  enumeration values removed, such that:
958*61c4878aSAndroid Build Coastguard Worker
959*61c4878aSAndroid Build Coastguard Worker  .. code-block:: protobuf
960*61c4878aSAndroid Build Coastguard Worker
961*61c4878aSAndroid Build Coastguard Worker     enum Activity {
962*61c4878aSAndroid Build Coastguard Worker       ACTIVITY_CYCLING = 1;
963*61c4878aSAndroid Build Coastguard Worker       ACTIVITY_RUNNING = 2;
964*61c4878aSAndroid Build Coastguard Worker       ACTIVITY_SWIMMING = 3;
965*61c4878aSAndroid Build Coastguard Worker     }
966*61c4878aSAndroid Build Coastguard Worker
967*61c4878aSAndroid Build Coastguard Worker  .. code-block:: c++
968*61c4878aSAndroid Build Coastguard Worker
969*61c4878aSAndroid Build Coastguard Worker     enum class Activity : uint32_t {
970*61c4878aSAndroid Build Coastguard Worker       ACTIVITY_CYCLING = 1,
971*61c4878aSAndroid Build Coastguard Worker       ACTIVITY_RUNNING = 2,
972*61c4878aSAndroid Build Coastguard Worker       ACTIVITY_SWIMMING = 3,
973*61c4878aSAndroid Build Coastguard Worker
974*61c4878aSAndroid Build Coastguard Worker       kCycling = ACTIVITY_CYCLING,
975*61c4878aSAndroid Build Coastguard Worker       kRunning = ACTIVITY_RUNNING,
976*61c4878aSAndroid Build Coastguard Worker       kSwimming = ACTIVITY_SWIMMING,
977*61c4878aSAndroid Build Coastguard Worker     };
978*61c4878aSAndroid Build Coastguard Worker
979*61c4878aSAndroid Build Coastguard Worker
980*61c4878aSAndroid Build Coastguard Worker* Nested messages are represented by their own ``struct Message`` provided that
981*61c4878aSAndroid Build Coastguard Worker  a reference cycle does not exist.
982*61c4878aSAndroid Build Coastguard Worker
983*61c4878aSAndroid Build Coastguard Worker  .. code-block:: protobuf
984*61c4878aSAndroid Build Coastguard Worker
985*61c4878aSAndroid Build Coastguard Worker     message Sale {
986*61c4878aSAndroid Build Coastguard Worker       Customer customer = 1;
987*61c4878aSAndroid Build Coastguard Worker       Product product = 2;
988*61c4878aSAndroid Build Coastguard Worker     }
989*61c4878aSAndroid Build Coastguard Worker
990*61c4878aSAndroid Build Coastguard Worker  .. code-block:: c++
991*61c4878aSAndroid Build Coastguard Worker
992*61c4878aSAndroid Build Coastguard Worker     struct Sale::Message {
993*61c4878aSAndroid Build Coastguard Worker       Customer::Message customer;
994*61c4878aSAndroid Build Coastguard Worker       Product::Message product;
995*61c4878aSAndroid Build Coastguard Worker     };
996*61c4878aSAndroid Build Coastguard Worker
997*61c4878aSAndroid Build Coastguard Worker* Optional scalar fields are represented by the appropriate C++ type wrapped in
998*61c4878aSAndroid Build Coastguard Worker  ``std::optional``. Optional fields are not encoded when the value is not
999*61c4878aSAndroid Build Coastguard Worker  present.
1000*61c4878aSAndroid Build Coastguard Worker
1001*61c4878aSAndroid Build Coastguard Worker  .. code-block:: protobuf
1002*61c4878aSAndroid Build Coastguard Worker
1003*61c4878aSAndroid Build Coastguard Worker     message Loyalty {
1004*61c4878aSAndroid Build Coastguard Worker       optional int32 points = 1;
1005*61c4878aSAndroid Build Coastguard Worker     }
1006*61c4878aSAndroid Build Coastguard Worker
1007*61c4878aSAndroid Build Coastguard Worker  .. code-block:: c++
1008*61c4878aSAndroid Build Coastguard Worker
1009*61c4878aSAndroid Build Coastguard Worker     struct Loyalty::Message {
1010*61c4878aSAndroid Build Coastguard Worker       std::optional<int32_t> points;
1011*61c4878aSAndroid Build Coastguard Worker     };
1012*61c4878aSAndroid Build Coastguard Worker
1013*61c4878aSAndroid Build Coastguard Worker* Repeated scalar fields are represented by ``pw::Vector`` when the
1014*61c4878aSAndroid Build Coastguard Worker  ``max_count`` option is set for that field, or by ``std::array`` when both
1015*61c4878aSAndroid Build Coastguard Worker  ``max_count`` and ``fixed_count:true`` are set.
1016*61c4878aSAndroid Build Coastguard Worker
1017*61c4878aSAndroid Build Coastguard Worker  The max count is exposed as an UpperCamelCase constant ``k{FieldName}MaxSize``.
1018*61c4878aSAndroid Build Coastguard Worker
1019*61c4878aSAndroid Build Coastguard Worker  .. code-block:: protobuf
1020*61c4878aSAndroid Build Coastguard Worker
1021*61c4878aSAndroid Build Coastguard Worker     message Register {
1022*61c4878aSAndroid Build Coastguard Worker       repeated int32 cash_in = 1;
1023*61c4878aSAndroid Build Coastguard Worker       repeated int32 cash_out = 2;
1024*61c4878aSAndroid Build Coastguard Worker     }
1025*61c4878aSAndroid Build Coastguard Worker
1026*61c4878aSAndroid Build Coastguard Worker  .. code-block:: text
1027*61c4878aSAndroid Build Coastguard Worker
1028*61c4878aSAndroid Build Coastguard Worker     Register.cash_in max_count:32 fixed_count:true
1029*61c4878aSAndroid Build Coastguard Worker     Register.cash_out max_count:64
1030*61c4878aSAndroid Build Coastguard Worker
1031*61c4878aSAndroid Build Coastguard Worker  .. code-block:: c++
1032*61c4878aSAndroid Build Coastguard Worker
1033*61c4878aSAndroid Build Coastguard Worker     namespace Register {
1034*61c4878aSAndroid Build Coastguard Worker       static constexpr size_t kCashInMaxSize = 32;
1035*61c4878aSAndroid Build Coastguard Worker       static constexpr size_t kCashOutMaxSize = 64;
1036*61c4878aSAndroid Build Coastguard Worker     }
1037*61c4878aSAndroid Build Coastguard Worker
1038*61c4878aSAndroid Build Coastguard Worker     struct Register::Message {
1039*61c4878aSAndroid Build Coastguard Worker       std::array<int32_t, kCashInMaxSize> cash_in;
1040*61c4878aSAndroid Build Coastguard Worker       pw::Vector<int32_t, kCashOutMaxSize> cash_out;
1041*61c4878aSAndroid Build Coastguard Worker     };
1042*61c4878aSAndroid Build Coastguard Worker
1043*61c4878aSAndroid Build Coastguard Worker* `bytes` fields are represented by ``pw::Vector`` when the ``max_size`` option
1044*61c4878aSAndroid Build Coastguard Worker  is set for that field, or by ``std::array`` when both ``max_size`` and
1045*61c4878aSAndroid Build Coastguard Worker  ``fixed_size:true`` are set.
1046*61c4878aSAndroid Build Coastguard Worker
1047*61c4878aSAndroid Build Coastguard Worker  The max size is exposed as an UpperCamelCase constant ``k{FieldName}MaxSize``.
1048*61c4878aSAndroid Build Coastguard Worker
1049*61c4878aSAndroid Build Coastguard Worker  .. code-block:: protobuf
1050*61c4878aSAndroid Build Coastguard Worker
1051*61c4878aSAndroid Build Coastguard Worker     message Product {
1052*61c4878aSAndroid Build Coastguard Worker       bytes sku = 1;
1053*61c4878aSAndroid Build Coastguard Worker       bytes serial_number = 2;
1054*61c4878aSAndroid Build Coastguard Worker     }
1055*61c4878aSAndroid Build Coastguard Worker
1056*61c4878aSAndroid Build Coastguard Worker  .. code-block:: text
1057*61c4878aSAndroid Build Coastguard Worker
1058*61c4878aSAndroid Build Coastguard Worker     Product.sku max_size:8 fixed_size:true
1059*61c4878aSAndroid Build Coastguard Worker     Product.serial_number max_size:64
1060*61c4878aSAndroid Build Coastguard Worker
1061*61c4878aSAndroid Build Coastguard Worker  .. code-block:: c++
1062*61c4878aSAndroid Build Coastguard Worker
1063*61c4878aSAndroid Build Coastguard Worker     namespace Product {
1064*61c4878aSAndroid Build Coastguard Worker       static constexpr size_t kSkuMaxSize = 8;
1065*61c4878aSAndroid Build Coastguard Worker       static constexpr size_t kSerialNumberMaxSize = 64;
1066*61c4878aSAndroid Build Coastguard Worker     }
1067*61c4878aSAndroid Build Coastguard Worker
1068*61c4878aSAndroid Build Coastguard Worker     struct Product::Message {
1069*61c4878aSAndroid Build Coastguard Worker       std::array<std::byte, kSkuMaxSize> sku;
1070*61c4878aSAndroid Build Coastguard Worker       pw::Vector<std::byte, kSerialNumberMaxSize> serial_number;
1071*61c4878aSAndroid Build Coastguard Worker     };
1072*61c4878aSAndroid Build Coastguard Worker
1073*61c4878aSAndroid Build Coastguard Worker* `string` fields are represented by a :cpp:type:`pw::InlineString` when the
1074*61c4878aSAndroid Build Coastguard Worker  ``max_size`` option is set for that field. The string can hold up to
1075*61c4878aSAndroid Build Coastguard Worker  ``max_size`` characters, and is always null terminated. The null terminator is
1076*61c4878aSAndroid Build Coastguard Worker  not counted in ``max_size``.
1077*61c4878aSAndroid Build Coastguard Worker
1078*61c4878aSAndroid Build Coastguard Worker  The max size is exposed as an UpperCamelCase constant ``k{FieldName}MaxSize``.
1079*61c4878aSAndroid Build Coastguard Worker
1080*61c4878aSAndroid Build Coastguard Worker  .. code-block:: protobuf
1081*61c4878aSAndroid Build Coastguard Worker
1082*61c4878aSAndroid Build Coastguard Worker     message Employee {
1083*61c4878aSAndroid Build Coastguard Worker       string name = 1;
1084*61c4878aSAndroid Build Coastguard Worker     }
1085*61c4878aSAndroid Build Coastguard Worker
1086*61c4878aSAndroid Build Coastguard Worker  .. code-block:: text
1087*61c4878aSAndroid Build Coastguard Worker
1088*61c4878aSAndroid Build Coastguard Worker     Employee.name max_size:128
1089*61c4878aSAndroid Build Coastguard Worker
1090*61c4878aSAndroid Build Coastguard Worker  .. code-block:: c++
1091*61c4878aSAndroid Build Coastguard Worker
1092*61c4878aSAndroid Build Coastguard Worker     namespace Employee {
1093*61c4878aSAndroid Build Coastguard Worker       static constexpr size_t kNameMaxSize = 128;
1094*61c4878aSAndroid Build Coastguard Worker     }
1095*61c4878aSAndroid Build Coastguard Worker
1096*61c4878aSAndroid Build Coastguard Worker     struct Employee::Message {
1097*61c4878aSAndroid Build Coastguard Worker       pw::InlineString<kNameMaxSize> name;
1098*61c4878aSAndroid Build Coastguard Worker     };
1099*61c4878aSAndroid Build Coastguard Worker
1100*61c4878aSAndroid Build Coastguard Worker* Nested messages with a dependency cycle, repeated scalar fields without a
1101*61c4878aSAndroid Build Coastguard Worker  ``max_count`` option set, `bytes` and `strings` fields without a ``max_size``
1102*61c4878aSAndroid Build Coastguard Worker  option set, and repeated nested messages, repeated `bytes`, and repeated
1103*61c4878aSAndroid Build Coastguard Worker  `strings` fields, are represented by a callback.
1104*61c4878aSAndroid Build Coastguard Worker
1105*61c4878aSAndroid Build Coastguard Worker  You set the callback to a custom function for encoding or decoding
1106*61c4878aSAndroid Build Coastguard Worker  before passing the structure to ``Write()`` or ``Read()`` appropriately.
1107*61c4878aSAndroid Build Coastguard Worker
1108*61c4878aSAndroid Build Coastguard Worker  .. code-block:: protobuf
1109*61c4878aSAndroid Build Coastguard Worker
1110*61c4878aSAndroid Build Coastguard Worker     message Store {
1111*61c4878aSAndroid Build Coastguard Worker       Store nearest_store = 1;
1112*61c4878aSAndroid Build Coastguard Worker       repeated int32 employee_numbers = 2;
1113*61c4878aSAndroid Build Coastguard Worker       string directions = 3;
1114*61c4878aSAndroid Build Coastguard Worker       repeated string address = 4;
1115*61c4878aSAndroid Build Coastguard Worker       repeated Employee employees = 5;
1116*61c4878aSAndroid Build Coastguard Worker     }
1117*61c4878aSAndroid Build Coastguard Worker
1118*61c4878aSAndroid Build Coastguard Worker  .. code-block::
1119*61c4878aSAndroid Build Coastguard Worker
1120*61c4878aSAndroid Build Coastguard Worker     // No options set.
1121*61c4878aSAndroid Build Coastguard Worker
1122*61c4878aSAndroid Build Coastguard Worker  .. code-block:: c++
1123*61c4878aSAndroid Build Coastguard Worker
1124*61c4878aSAndroid Build Coastguard Worker     struct Store::Message {
1125*61c4878aSAndroid Build Coastguard Worker       pw::protobuf::Callback<Store::StreamEncoder, Store::StreamDecoder> nearest_store;
1126*61c4878aSAndroid Build Coastguard Worker       pw::protobuf::Callback<Store::StreamEncoder, Store::StreamDecoder> employee_numbers;
1127*61c4878aSAndroid Build Coastguard Worker       pw::protobuf::Callback<Store::StreamEncoder, Store::StreamDecoder> directions;
1128*61c4878aSAndroid Build Coastguard Worker       pw::protobuf::Callback<Store::StreamEncoder, Store::StreamDecoder> address;
1129*61c4878aSAndroid Build Coastguard Worker       pw::protobuf::Callback<Store::StreamEncoder, Store::StreamDecoder> employees;
1130*61c4878aSAndroid Build Coastguard Worker     };
1131*61c4878aSAndroid Build Coastguard Worker
1132*61c4878aSAndroid Build Coastguard Worker  A Callback object can be converted to a ``bool`` indicating whether a callback
1133*61c4878aSAndroid Build Coastguard Worker  is set.
1134*61c4878aSAndroid Build Coastguard Worker
1135*61c4878aSAndroid Build Coastguard Worker* Fields defined within a ``oneof`` group are represented by a ``OneOf``
1136*61c4878aSAndroid Build Coastguard Worker  callback.
1137*61c4878aSAndroid Build Coastguard Worker
1138*61c4878aSAndroid Build Coastguard Worker  .. code-block:: protobuf
1139*61c4878aSAndroid Build Coastguard Worker
1140*61c4878aSAndroid Build Coastguard Worker     message OnlineOrder {
1141*61c4878aSAndroid Build Coastguard Worker       Product product = 1;
1142*61c4878aSAndroid Build Coastguard Worker       Customer customer = 2;
1143*61c4878aSAndroid Build Coastguard Worker
1144*61c4878aSAndroid Build Coastguard Worker       oneof delivery {
1145*61c4878aSAndroid Build Coastguard Worker         Address shipping_address = 3;
1146*61c4878aSAndroid Build Coastguard Worker         Date pickup_date = 4;
1147*61c4878aSAndroid Build Coastguard Worker       }
1148*61c4878aSAndroid Build Coastguard Worker     }
1149*61c4878aSAndroid Build Coastguard Worker
1150*61c4878aSAndroid Build Coastguard Worker  .. code-block::
1151*61c4878aSAndroid Build Coastguard Worker
1152*61c4878aSAndroid Build Coastguard Worker     // No options set.
1153*61c4878aSAndroid Build Coastguard Worker
1154*61c4878aSAndroid Build Coastguard Worker  .. code-block:: c++
1155*61c4878aSAndroid Build Coastguard Worker
1156*61c4878aSAndroid Build Coastguard Worker     struct OnlineOrder::Message {
1157*61c4878aSAndroid Build Coastguard Worker       Product::Message product;
1158*61c4878aSAndroid Build Coastguard Worker       Customer::Message customer;
1159*61c4878aSAndroid Build Coastguard Worker       pw::protobuf::OneOf<OnlineOrder::StreamEncoder,
1160*61c4878aSAndroid Build Coastguard Worker                           OnlineOrder::StreamDecoder,
1161*61c4878aSAndroid Build Coastguard Worker                           OnlineOrder::Fields>
1162*61c4878aSAndroid Build Coastguard Worker         delivery;
1163*61c4878aSAndroid Build Coastguard Worker     };
1164*61c4878aSAndroid Build Coastguard Worker
1165*61c4878aSAndroid Build Coastguard Worker  Encoding a ``oneof`` field is identical to using a regular field callback.
1166*61c4878aSAndroid Build Coastguard Worker  The encode callback will be invoked once when the message is written. Users
1167*61c4878aSAndroid Build Coastguard Worker  must ensure that only a single field is written to the encoder within the
1168*61c4878aSAndroid Build Coastguard Worker  callback.
1169*61c4878aSAndroid Build Coastguard Worker
1170*61c4878aSAndroid Build Coastguard Worker  .. code-block:: c++
1171*61c4878aSAndroid Build Coastguard Worker
1172*61c4878aSAndroid Build Coastguard Worker     OnlineOrder::Message message;
1173*61c4878aSAndroid Build Coastguard Worker     message.delivery.SetEncoder(
1174*61c4878aSAndroid Build Coastguard Worker         [&pickup_date](OnlineOrder::StreamEncoder& encoder) {
1175*61c4878aSAndroid Build Coastguard Worker           return encoder.GetPickupDateEncoder().Write(pickup_date);
1176*61c4878aSAndroid Build Coastguard Worker         });
1177*61c4878aSAndroid Build Coastguard Worker
1178*61c4878aSAndroid Build Coastguard Worker  The ``OneOf`` decoder callback is invoked when reading a message structure
1179*61c4878aSAndroid Build Coastguard Worker  when a field within the ``oneof`` group is encountered. The found field is
1180*61c4878aSAndroid Build Coastguard Worker  passed to the callback.
1181*61c4878aSAndroid Build Coastguard Worker
1182*61c4878aSAndroid Build Coastguard Worker  If multiple fields from the ``oneof`` group are encountered within a ``Read``,
1183*61c4878aSAndroid Build Coastguard Worker  it will fail with a ``DATA_LOSS`` status.
1184*61c4878aSAndroid Build Coastguard Worker
1185*61c4878aSAndroid Build Coastguard Worker  .. code-block:: c++
1186*61c4878aSAndroid Build Coastguard Worker
1187*61c4878aSAndroid Build Coastguard Worker     OnlineOrder::Message message;
1188*61c4878aSAndroid Build Coastguard Worker     message.delivery.SetDecoder(
1189*61c4878aSAndroid Build Coastguard Worker         [this](OnlineOrder::Fields field, OnlineOrder::StreamDecoder& decoder) {
1190*61c4878aSAndroid Build Coastguard Worker           switch (field) {
1191*61c4878aSAndroid Build Coastguard Worker             case OnlineOrder::Fields::kShippingAddress:
1192*61c4878aSAndroid Build Coastguard Worker               PW_TRY(decoder.GetShippingAddressDecoder().Read(&this->shipping_address));
1193*61c4878aSAndroid Build Coastguard Worker               break;
1194*61c4878aSAndroid Build Coastguard Worker             case OnlineOrder::Fields::kPickupDate:
1195*61c4878aSAndroid Build Coastguard Worker               PW_TRY(decoder.GetPickupDateDecoder().Read(&this->pickup_date));
1196*61c4878aSAndroid Build Coastguard Worker               break;
1197*61c4878aSAndroid Build Coastguard Worker             default:
1198*61c4878aSAndroid Build Coastguard Worker               return pw::Status::DataLoss();
1199*61c4878aSAndroid Build Coastguard Worker           }
1200*61c4878aSAndroid Build Coastguard Worker
1201*61c4878aSAndroid Build Coastguard Worker           return pw::OkStatus();
1202*61c4878aSAndroid Build Coastguard Worker         });
1203*61c4878aSAndroid Build Coastguard Worker
1204*61c4878aSAndroid Build Coastguard WorkerMessage structures can be copied, but doing so will clear any assigned
1205*61c4878aSAndroid Build Coastguard Workercallbacks. To preserve functions applied to callbacks, ensure that the message
1206*61c4878aSAndroid Build Coastguard Workerstructure is moved.
1207*61c4878aSAndroid Build Coastguard Worker
1208*61c4878aSAndroid Build Coastguard WorkerMessage structures can also be compared with each other for equality. This
1209*61c4878aSAndroid Build Coastguard Workerincludes all repeated and nested fields represented by value types, but does not
1210*61c4878aSAndroid Build Coastguard Workercompare any field represented by a callback.
1211*61c4878aSAndroid Build Coastguard Worker
1212*61c4878aSAndroid Build Coastguard WorkerReserved-Word Conflicts
1213*61c4878aSAndroid Build Coastguard Worker=======================
1214*61c4878aSAndroid Build Coastguard WorkerGenerated symbols whose names conflict with reserved C++ keywords or
1215*61c4878aSAndroid Build Coastguard Workerstandard-library macros are suffixed with underscores to avoid compilation
1216*61c4878aSAndroid Build Coastguard Workerfailures. This can be seen below in ``Channel.operator``, which is mapped to
1217*61c4878aSAndroid Build Coastguard Worker``Channel::Message::operator_`` to avoid conflicting with the ``operator``
1218*61c4878aSAndroid Build Coastguard Workerkeyword.
1219*61c4878aSAndroid Build Coastguard Worker
1220*61c4878aSAndroid Build Coastguard Worker.. code-block:: protobuf
1221*61c4878aSAndroid Build Coastguard Worker
1222*61c4878aSAndroid Build Coastguard Worker   message Channel {
1223*61c4878aSAndroid Build Coastguard Worker     int32 bitrate = 1;
1224*61c4878aSAndroid Build Coastguard Worker     float signal_to_noise_ratio = 2;
1225*61c4878aSAndroid Build Coastguard Worker     Company operator = 3;
1226*61c4878aSAndroid Build Coastguard Worker   }
1227*61c4878aSAndroid Build Coastguard Worker
1228*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
1229*61c4878aSAndroid Build Coastguard Worker
1230*61c4878aSAndroid Build Coastguard Worker   struct Channel::Message {
1231*61c4878aSAndroid Build Coastguard Worker     int32_t bitrate;
1232*61c4878aSAndroid Build Coastguard Worker     float signal_to_noise_ratio;
1233*61c4878aSAndroid Build Coastguard Worker     Company::Message operator_;
1234*61c4878aSAndroid Build Coastguard Worker   };
1235*61c4878aSAndroid Build Coastguard Worker
1236*61c4878aSAndroid Build Coastguard WorkerSimilarly, as shown in the example below, some POSIX-signal names conflict with
1237*61c4878aSAndroid Build Coastguard Workermacros defined by the standard-library header ``<csignal>`` and therefore
1238*61c4878aSAndroid Build Coastguard Workerrequire underscore suffixes in the generated code. Note, however, that some
1239*61c4878aSAndroid Build Coastguard Workersignal names are left alone. This is because ``<csignal>`` only defines a subset
1240*61c4878aSAndroid Build Coastguard Workerof the POSIX signals as macros; the rest are perfectly valid identifiers that
1241*61c4878aSAndroid Build Coastguard Workerwon't cause any problems unless the user defines custom macros for them. Any
1242*61c4878aSAndroid Build Coastguard Workernaming conflicts caused by user-defined macros are the user's responsibility
1243*61c4878aSAndroid Build Coastguard Worker(https://google.github.io/styleguide/cppguide.html#Preprocessor_Macros).
1244*61c4878aSAndroid Build Coastguard Worker
1245*61c4878aSAndroid Build Coastguard Worker.. code-block:: protobuf
1246*61c4878aSAndroid Build Coastguard Worker
1247*61c4878aSAndroid Build Coastguard Worker   enum PosixSignal {
1248*61c4878aSAndroid Build Coastguard Worker     NONE = 0;
1249*61c4878aSAndroid Build Coastguard Worker     SIGHUP = 1;
1250*61c4878aSAndroid Build Coastguard Worker     SIGINT = 2;
1251*61c4878aSAndroid Build Coastguard Worker     SIGQUIT = 3;
1252*61c4878aSAndroid Build Coastguard Worker     SIGILL = 4;
1253*61c4878aSAndroid Build Coastguard Worker     SIGTRAP = 5;
1254*61c4878aSAndroid Build Coastguard Worker     SIGABRT = 6;
1255*61c4878aSAndroid Build Coastguard Worker     SIGFPE = 8;
1256*61c4878aSAndroid Build Coastguard Worker     SIGKILL = 9;
1257*61c4878aSAndroid Build Coastguard Worker     SIGSEGV = 11;
1258*61c4878aSAndroid Build Coastguard Worker     SIGPIPE = 13;
1259*61c4878aSAndroid Build Coastguard Worker     SIGALRM = 14;
1260*61c4878aSAndroid Build Coastguard Worker     SIGTERM = 15;
1261*61c4878aSAndroid Build Coastguard Worker   }
1262*61c4878aSAndroid Build Coastguard Worker
1263*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
1264*61c4878aSAndroid Build Coastguard Worker
1265*61c4878aSAndroid Build Coastguard Worker   enum class PosixSignal : uint32_t {
1266*61c4878aSAndroid Build Coastguard Worker     NONE = 0,
1267*61c4878aSAndroid Build Coastguard Worker     SIGHUP = 1,
1268*61c4878aSAndroid Build Coastguard Worker     SIGINT_ = 2,
1269*61c4878aSAndroid Build Coastguard Worker     SIGQUIT = 3,
1270*61c4878aSAndroid Build Coastguard Worker     SIGILL_ = 4,
1271*61c4878aSAndroid Build Coastguard Worker     SIGTRAP = 5,
1272*61c4878aSAndroid Build Coastguard Worker     SIGABRT_ = 6,
1273*61c4878aSAndroid Build Coastguard Worker     SIGFPE_ = 8,
1274*61c4878aSAndroid Build Coastguard Worker     SIGKILL = 9,
1275*61c4878aSAndroid Build Coastguard Worker     SIGSEGV_ = 11,
1276*61c4878aSAndroid Build Coastguard Worker     SIGPIPE = 13,
1277*61c4878aSAndroid Build Coastguard Worker     SIGALRM = 14,
1278*61c4878aSAndroid Build Coastguard Worker     SIGTERM_ = 15,
1279*61c4878aSAndroid Build Coastguard Worker
1280*61c4878aSAndroid Build Coastguard Worker     kNone = NONE,
1281*61c4878aSAndroid Build Coastguard Worker     kSighup = SIGHUP,
1282*61c4878aSAndroid Build Coastguard Worker     kSigint = SIGINT_,
1283*61c4878aSAndroid Build Coastguard Worker     kSigquit = SIGQUIT,
1284*61c4878aSAndroid Build Coastguard Worker     kSigill = SIGILL_,
1285*61c4878aSAndroid Build Coastguard Worker     kSigtrap = SIGTRAP,
1286*61c4878aSAndroid Build Coastguard Worker     kSigabrt = SIGABRT_,
1287*61c4878aSAndroid Build Coastguard Worker     kSigfpe = SIGFPE_,
1288*61c4878aSAndroid Build Coastguard Worker     kSigkill = SIGKILL,
1289*61c4878aSAndroid Build Coastguard Worker     kSigsegv = SIGSEGV_,
1290*61c4878aSAndroid Build Coastguard Worker     kSigpipe = SIGPIPE,
1291*61c4878aSAndroid Build Coastguard Worker     kSigalrm = SIGALRM,
1292*61c4878aSAndroid Build Coastguard Worker     kSigterm = SIGTERM_,
1293*61c4878aSAndroid Build Coastguard Worker   };
1294*61c4878aSAndroid Build Coastguard Worker
1295*61c4878aSAndroid Build Coastguard WorkerMuch like reserved words and macros, the names ``Message`` and ``Fields`` are
1296*61c4878aSAndroid Build Coastguard Workersuffixed with underscores in generated C++ code. This is to prevent name
1297*61c4878aSAndroid Build Coastguard Workerconflicts with the codegen internals if they're used in a nested context as in
1298*61c4878aSAndroid Build Coastguard Workerthe example below.
1299*61c4878aSAndroid Build Coastguard Worker
1300*61c4878aSAndroid Build Coastguard Worker.. code-block:: protobuf
1301*61c4878aSAndroid Build Coastguard Worker
1302*61c4878aSAndroid Build Coastguard Worker   message Function {
1303*61c4878aSAndroid Build Coastguard Worker     message Message {
1304*61c4878aSAndroid Build Coastguard Worker       string content = 1;
1305*61c4878aSAndroid Build Coastguard Worker     }
1306*61c4878aSAndroid Build Coastguard Worker
1307*61c4878aSAndroid Build Coastguard Worker     enum Fields {
1308*61c4878aSAndroid Build Coastguard Worker       NONE = 0;
1309*61c4878aSAndroid Build Coastguard Worker       COMPLEX_NUMBERS = 1;
1310*61c4878aSAndroid Build Coastguard Worker       INTEGERS_MOD_5 = 2;
1311*61c4878aSAndroid Build Coastguard Worker       MEROMORPHIC_FUNCTIONS_ON_COMPLEX_PLANE = 3;
1312*61c4878aSAndroid Build Coastguard Worker       OTHER = 4;
1313*61c4878aSAndroid Build Coastguard Worker     }
1314*61c4878aSAndroid Build Coastguard Worker
1315*61c4878aSAndroid Build Coastguard Worker     Message description = 1;
1316*61c4878aSAndroid Build Coastguard Worker     Fields domain = 2;
1317*61c4878aSAndroid Build Coastguard Worker     Fields codomain = 3;
1318*61c4878aSAndroid Build Coastguard Worker   }
1319*61c4878aSAndroid Build Coastguard Worker
1320*61c4878aSAndroid Build Coastguard Worker.. code-block::
1321*61c4878aSAndroid Build Coastguard Worker
1322*61c4878aSAndroid Build Coastguard Worker   Function.Message.content max_size:128
1323*61c4878aSAndroid Build Coastguard Worker
1324*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
1325*61c4878aSAndroid Build Coastguard Worker
1326*61c4878aSAndroid Build Coastguard Worker   struct Function::Message_::Message {
1327*61c4878aSAndroid Build Coastguard Worker     pw::InlineString<128> content;
1328*61c4878aSAndroid Build Coastguard Worker   };
1329*61c4878aSAndroid Build Coastguard Worker
1330*61c4878aSAndroid Build Coastguard Worker   enum class Function::Message_::Fields : uint32_t {
1331*61c4878aSAndroid Build Coastguard Worker     CONTENT = 1,
1332*61c4878aSAndroid Build Coastguard Worker   };
1333*61c4878aSAndroid Build Coastguard Worker
1334*61c4878aSAndroid Build Coastguard Worker   enum class Function::Fields_ uint32_t {
1335*61c4878aSAndroid Build Coastguard Worker     NONE = 0,
1336*61c4878aSAndroid Build Coastguard Worker     COMPLEX_NUMBERS = 1,
1337*61c4878aSAndroid Build Coastguard Worker     INTEGERS_MOD_5 = 2,
1338*61c4878aSAndroid Build Coastguard Worker     MEROMORPHIC_FUNCTIONS_ON_COMPLEX_PLANE = 3,
1339*61c4878aSAndroid Build Coastguard Worker     OTHER = 4,
1340*61c4878aSAndroid Build Coastguard Worker
1341*61c4878aSAndroid Build Coastguard Worker     kNone = NONE,
1342*61c4878aSAndroid Build Coastguard Worker     kComplexNumbers = COMPLEX_NUMBERS,
1343*61c4878aSAndroid Build Coastguard Worker     kIntegersMod5 = INTEGERS_MOD_5,
1344*61c4878aSAndroid Build Coastguard Worker     kMeromorphicFunctionsOnComplexPlane =
1345*61c4878aSAndroid Build Coastguard Worker         MEROMORPHIC_FUNCTIONS_ON_COMPLEX_PLANE,
1346*61c4878aSAndroid Build Coastguard Worker     kOther = OTHER,
1347*61c4878aSAndroid Build Coastguard Worker   };
1348*61c4878aSAndroid Build Coastguard Worker
1349*61c4878aSAndroid Build Coastguard Worker   struct Function::Message {
1350*61c4878aSAndroid Build Coastguard Worker     Function::Message_::Message description;
1351*61c4878aSAndroid Build Coastguard Worker     Function::Fields_ domain;
1352*61c4878aSAndroid Build Coastguard Worker     Function::Fields_ codomain;
1353*61c4878aSAndroid Build Coastguard Worker   };
1354*61c4878aSAndroid Build Coastguard Worker
1355*61c4878aSAndroid Build Coastguard Worker   enum class Function::Fields : uint32_t {
1356*61c4878aSAndroid Build Coastguard Worker     DESCRIPTION = 1,
1357*61c4878aSAndroid Build Coastguard Worker     DOMAIN = 2,
1358*61c4878aSAndroid Build Coastguard Worker     CODOMAIN = 3,
1359*61c4878aSAndroid Build Coastguard Worker   };
1360*61c4878aSAndroid Build Coastguard Worker
1361*61c4878aSAndroid Build Coastguard Worker.. warning::
1362*61c4878aSAndroid Build Coastguard Worker   Note that the C++ spec also reserves two categories of identifiers for the
1363*61c4878aSAndroid Build Coastguard Worker   compiler to use in ways that may conflict with generated code:
1364*61c4878aSAndroid Build Coastguard Worker
1365*61c4878aSAndroid Build Coastguard Worker   * Any identifier that contains two consecutive underscores anywhere in it.
1366*61c4878aSAndroid Build Coastguard Worker   * Any identifier that starts with an underscore followed by a capital letter.
1367*61c4878aSAndroid Build Coastguard Worker
1368*61c4878aSAndroid Build Coastguard Worker   Appending underscores to symbols in these categories wouldn't change the fact
1369*61c4878aSAndroid Build Coastguard Worker   that they match patterns reserved for the compiler, so the codegen does not
1370*61c4878aSAndroid Build Coastguard Worker   currently attempt to fix them. Such names will therefore result in
1371*61c4878aSAndroid Build Coastguard Worker   non-portable code that may or may not work depending on the compiler. These
1372*61c4878aSAndroid Build Coastguard Worker   naming patterns are of course strongly discouraged in any protobufs that will
1373*61c4878aSAndroid Build Coastguard Worker   be used with ``pw_protobuf`` codegen.
1374*61c4878aSAndroid Build Coastguard Worker
1375*61c4878aSAndroid Build Coastguard WorkerOverhead
1376*61c4878aSAndroid Build Coastguard Worker========
1377*61c4878aSAndroid Build Coastguard WorkerA single encoder and decoder is used for these structures, with a one-time code
1378*61c4878aSAndroid Build Coastguard Workercost. When the code generator creates the ``struct Message``, it also creates
1379*61c4878aSAndroid Build Coastguard Workera description of this structure that the shared encoder and decoder use.
1380*61c4878aSAndroid Build Coastguard Worker
1381*61c4878aSAndroid Build Coastguard WorkerThe cost of this description is a shared table for each protobuf message
1382*61c4878aSAndroid Build Coastguard Workerdefinition used, with four words per field within the protobuf message, and an
1383*61c4878aSAndroid Build Coastguard Workeraddition word to store the size of the table.
1384*61c4878aSAndroid Build Coastguard Worker
1385*61c4878aSAndroid Build Coastguard Worker--------
1386*61c4878aSAndroid Build Coastguard WorkerEncoding
1387*61c4878aSAndroid Build Coastguard Worker--------
1388*61c4878aSAndroid Build Coastguard WorkerThe simplest way to use ``MemoryEncoder`` to encode a proto is from its code
1389*61c4878aSAndroid Build Coastguard Workergenerated ``Message`` structure into an in-memory buffer.
1390*61c4878aSAndroid Build Coastguard Worker
1391*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
1392*61c4878aSAndroid Build Coastguard Worker
1393*61c4878aSAndroid Build Coastguard Worker   #include "my_protos/my_proto.pwpb.h"
1394*61c4878aSAndroid Build Coastguard Worker   #include "pw_bytes/span.h"
1395*61c4878aSAndroid Build Coastguard Worker   #include "pw_protobuf/encoder.h"
1396*61c4878aSAndroid Build Coastguard Worker   #include "pw_status/status_with_size.h"
1397*61c4878aSAndroid Build Coastguard Worker
1398*61c4878aSAndroid Build Coastguard Worker   // Writes a proto response to the provided buffer, returning the encode
1399*61c4878aSAndroid Build Coastguard Worker   // status and number of bytes written.
1400*61c4878aSAndroid Build Coastguard Worker   pw::StatusWithSize WriteProtoResponse(pw::ByteSpan response) {
1401*61c4878aSAndroid Build Coastguard Worker     MyProto::Message message{}
1402*61c4878aSAndroid Build Coastguard Worker     message.magic_number = 0x1a1a2b2b;
1403*61c4878aSAndroid Build Coastguard Worker     message.favorite_food = "cookies";
1404*61c4878aSAndroid Build Coastguard Worker     message.calories = 600;
1405*61c4878aSAndroid Build Coastguard Worker
1406*61c4878aSAndroid Build Coastguard Worker     // All proto writes are directly written to the `response` buffer.
1407*61c4878aSAndroid Build Coastguard Worker     MyProto::MemoryEncoder encoder(response);
1408*61c4878aSAndroid Build Coastguard Worker     encoder.Write(message);
1409*61c4878aSAndroid Build Coastguard Worker
1410*61c4878aSAndroid Build Coastguard Worker     return pw::StatusWithSize(encoder.status(), encoder.size());
1411*61c4878aSAndroid Build Coastguard Worker   }
1412*61c4878aSAndroid Build Coastguard Worker
1413*61c4878aSAndroid Build Coastguard WorkerAll fields of a message are written, including those initialized to their
1414*61c4878aSAndroid Build Coastguard Workerdefault values.
1415*61c4878aSAndroid Build Coastguard Worker
1416*61c4878aSAndroid Build Coastguard WorkerAlternatively, for example if only a subset of fields are required to be
1417*61c4878aSAndroid Build Coastguard Workerencoded, fields can be written a field at a time through the code generated
1418*61c4878aSAndroid Build Coastguard Workeror lower-level APIs. This can be more convenient if finer grained control or
1419*61c4878aSAndroid Build Coastguard Workerother custom handling is required.
1420*61c4878aSAndroid Build Coastguard Worker
1421*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
1422*61c4878aSAndroid Build Coastguard Worker
1423*61c4878aSAndroid Build Coastguard Worker   #include "my_protos/my_proto.pwpb.h"
1424*61c4878aSAndroid Build Coastguard Worker   #include "pw_bytes/span.h"
1425*61c4878aSAndroid Build Coastguard Worker   #include "pw_protobuf/encoder.h"
1426*61c4878aSAndroid Build Coastguard Worker   #include "pw_status/status_with_size.h"
1427*61c4878aSAndroid Build Coastguard Worker
1428*61c4878aSAndroid Build Coastguard Worker   // Writes a proto response to the provided buffer, returning the encode
1429*61c4878aSAndroid Build Coastguard Worker   // status and number of bytes written.
1430*61c4878aSAndroid Build Coastguard Worker   pw::StatusWithSize WriteProtoResponse(pw::ByteSpan response) {
1431*61c4878aSAndroid Build Coastguard Worker     // All proto writes are directly written to the `response` buffer.
1432*61c4878aSAndroid Build Coastguard Worker     MyProto::MemoryEncoder encoder(response);
1433*61c4878aSAndroid Build Coastguard Worker     encoder.WriteMagicNumber(0x1a1a2b2b);
1434*61c4878aSAndroid Build Coastguard Worker     encoder.WriteFavoriteFood("cookies");
1435*61c4878aSAndroid Build Coastguard Worker     // Only conditionally write calories.
1436*61c4878aSAndroid Build Coastguard Worker     if (on_diet) {
1437*61c4878aSAndroid Build Coastguard Worker       encoder.WriteCalories(600);
1438*61c4878aSAndroid Build Coastguard Worker     }
1439*61c4878aSAndroid Build Coastguard Worker     return pw::StatusWithSize(encoder.status(), encoder.size());
1440*61c4878aSAndroid Build Coastguard Worker   }
1441*61c4878aSAndroid Build Coastguard Worker
1442*61c4878aSAndroid Build Coastguard WorkerStreamEncoder
1443*61c4878aSAndroid Build Coastguard Worker=============
1444*61c4878aSAndroid Build Coastguard Worker``StreamEncoder`` is constructed with the destination stream, and a scratch
1445*61c4878aSAndroid Build Coastguard Workerbuffer used to handle nested submessages.
1446*61c4878aSAndroid Build Coastguard Worker
1447*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
1448*61c4878aSAndroid Build Coastguard Worker
1449*61c4878aSAndroid Build Coastguard Worker   #include "my_protos/my_proto.pwpb.h"
1450*61c4878aSAndroid Build Coastguard Worker   #include "pw_bytes/span.h"
1451*61c4878aSAndroid Build Coastguard Worker   #include "pw_protobuf/encoder.h"
1452*61c4878aSAndroid Build Coastguard Worker   #include "pw_stream/sys_io_stream.h"
1453*61c4878aSAndroid Build Coastguard Worker
1454*61c4878aSAndroid Build Coastguard Worker   pw::stream::SysIoWriter sys_io_writer;
1455*61c4878aSAndroid Build Coastguard Worker   MyProto::StreamEncoder encoder(sys_io_writer, pw::ByteSpan());
1456*61c4878aSAndroid Build Coastguard Worker
1457*61c4878aSAndroid Build Coastguard Worker   // Once this line returns, the field has been written to the Writer.
1458*61c4878aSAndroid Build Coastguard Worker   encoder.WriteTimestamp(system::GetUnixEpoch());
1459*61c4878aSAndroid Build Coastguard Worker
1460*61c4878aSAndroid Build Coastguard Worker   // There's no intermediate buffering when writing a string directly to a
1461*61c4878aSAndroid Build Coastguard Worker   // StreamEncoder.
1462*61c4878aSAndroid Build Coastguard Worker   encoder.WriteWelcomeMessage("Welcome to Pigweed!");
1463*61c4878aSAndroid Build Coastguard Worker
1464*61c4878aSAndroid Build Coastguard Worker   if (!encoder.status().ok()) {
1465*61c4878aSAndroid Build Coastguard Worker     PW_LOG_INFO("Failed to encode proto; %s", encoder.status().str());
1466*61c4878aSAndroid Build Coastguard Worker   }
1467*61c4878aSAndroid Build Coastguard Worker
1468*61c4878aSAndroid Build Coastguard WorkerCallbacks
1469*61c4878aSAndroid Build Coastguard Worker=========
1470*61c4878aSAndroid Build Coastguard WorkerWhen using the ``Write()`` method with a ``struct Message``, certain fields may
1471*61c4878aSAndroid Build Coastguard Workerrequire a callback function be set to encode the values for those fields.
1472*61c4878aSAndroid Build Coastguard WorkerOtherwise the values will be treated as an empty repeated field and not encoded.
1473*61c4878aSAndroid Build Coastguard Worker
1474*61c4878aSAndroid Build Coastguard WorkerThe callback is called with the cursor at the field in question, and passed
1475*61c4878aSAndroid Build Coastguard Workera reference to the typed encoder that can write the required values to the
1476*61c4878aSAndroid Build Coastguard Workerstream or buffer.
1477*61c4878aSAndroid Build Coastguard Worker
1478*61c4878aSAndroid Build Coastguard WorkerCallback implementations may use any level of API. For example a callback for a
1479*61c4878aSAndroid Build Coastguard Workernested submessage (with a dependency cycle, or repeated) can be implemented by
1480*61c4878aSAndroid Build Coastguard Workercalling ``Write()`` on a nested encoder.
1481*61c4878aSAndroid Build Coastguard Worker
1482*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
1483*61c4878aSAndroid Build Coastguard Worker
1484*61c4878aSAndroid Build Coastguard Worker   Store::Message store{};
1485*61c4878aSAndroid Build Coastguard Worker   store.employees.SetEncoder([](Store::StreamEncoder& encoder) {
1486*61c4878aSAndroid Build Coastguard Worker     Employee::Message employee{};
1487*61c4878aSAndroid Build Coastguard Worker     // Populate `employee`.
1488*61c4878aSAndroid Build Coastguard Worker     return encoder.GetEmployeesEncoder().Write(employee);
1489*61c4878aSAndroid Build Coastguard Worker   ));
1490*61c4878aSAndroid Build Coastguard Worker
1491*61c4878aSAndroid Build Coastguard WorkerNested submessages
1492*61c4878aSAndroid Build Coastguard Worker==================
1493*61c4878aSAndroid Build Coastguard WorkerCode generated ``GetFieldEncoder`` methods are provided that return a correctly
1494*61c4878aSAndroid Build Coastguard Workertyped ``StreamEncoder`` or ``MemoryEncoder`` for the message.
1495*61c4878aSAndroid Build Coastguard Worker
1496*61c4878aSAndroid Build Coastguard Worker.. code-block:: protobuf
1497*61c4878aSAndroid Build Coastguard Worker
1498*61c4878aSAndroid Build Coastguard Worker   message Owner {
1499*61c4878aSAndroid Build Coastguard Worker     Animal pet = 1;
1500*61c4878aSAndroid Build Coastguard Worker   }
1501*61c4878aSAndroid Build Coastguard Worker
1502*61c4878aSAndroid Build Coastguard WorkerNote that the accessor method is named for the field, while the returned encoder
1503*61c4878aSAndroid Build Coastguard Workeris named for the message type.
1504*61c4878aSAndroid Build Coastguard Worker
1505*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Animal::StreamEncoder Owner::StreamEncoder::GetPetEncoder()
1506*61c4878aSAndroid Build Coastguard Worker
1507*61c4878aSAndroid Build Coastguard WorkerA lower-level API method returns an untyped encoder, which only provides the
1508*61c4878aSAndroid Build Coastguard Workerlower-level API methods. This can be cast to a typed encoder if needed.
1509*61c4878aSAndroid Build Coastguard Worker
1510*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: pw::protobuf::StreamEncoder pw::protobuf::StreamEncoder::GetNestedEncoder(uint32_t field_number, EmptyEncoderBehavior empty_encoder_behavior = EmptyEncoderBehavior::kWriteFieldNumber)
1511*61c4878aSAndroid Build Coastguard Worker
1512*61c4878aSAndroid Build Coastguard Worker(The optional `empty_encoder_behavior` parameter allows the user to disable
1513*61c4878aSAndroid Build Coastguard Workerwriting the tag number for the nested encoder, if no data was written to
1514*61c4878aSAndroid Build Coastguard Workerthat nested decoder.)
1515*61c4878aSAndroid Build Coastguard Worker
1516*61c4878aSAndroid Build Coastguard Worker.. warning::
1517*61c4878aSAndroid Build Coastguard Worker   When a nested submessage is created, any use of the parent encoder that
1518*61c4878aSAndroid Build Coastguard Worker   created the nested encoder will trigger a crash. To resume using the parent
1519*61c4878aSAndroid Build Coastguard Worker   encoder, destroy the submessage encoder first.
1520*61c4878aSAndroid Build Coastguard Worker
1521*61c4878aSAndroid Build Coastguard WorkerBuffering
1522*61c4878aSAndroid Build Coastguard Worker---------
1523*61c4878aSAndroid Build Coastguard WorkerWriting proto messages with nested submessages requires buffering due to
1524*61c4878aSAndroid Build Coastguard Workerlimitations of the proto format. Every proto submessage must know the size of
1525*61c4878aSAndroid Build Coastguard Workerthe submessage before its final serialization can begin. A streaming encoder can
1526*61c4878aSAndroid Build Coastguard Workerbe passed a scratch buffer to use when constructing nested messages. All
1527*61c4878aSAndroid Build Coastguard Workersubmessage data is buffered to this scratch buffer until the submessage is
1528*61c4878aSAndroid Build Coastguard Workerfinalized. Note that the contents of this scratch buffer is not necessarily
1529*61c4878aSAndroid Build Coastguard Workervalid proto data, so don't try to use it directly.
1530*61c4878aSAndroid Build Coastguard Worker
1531*61c4878aSAndroid Build Coastguard WorkerThe code generation includes a ``kScratchBufferSizeBytes`` constant that
1532*61c4878aSAndroid Build Coastguard Workerrepresents the size of the largest submessage and all necessary overhead,
1533*61c4878aSAndroid Build Coastguard Workerexcluding the contents of any field values which require a callback.
1534*61c4878aSAndroid Build Coastguard Worker
1535*61c4878aSAndroid Build Coastguard WorkerIf a submessage field requires a callback, due to a dependency cycle, or a
1536*61c4878aSAndroid Build Coastguard Workerrepeated field of unknown length, the size of the submessage cannot be included
1537*61c4878aSAndroid Build Coastguard Workerin the ``kScratchBufferSizeBytes`` constant. If you encode a submessage of this
1538*61c4878aSAndroid Build Coastguard Workertype (which you'll know you're doing because you set an encoder callback for it)
1539*61c4878aSAndroid Build Coastguard Workersimply add the appropriate structure's ``kMaxEncodedSizeBytes`` constant to the
1540*61c4878aSAndroid Build Coastguard Workerscratch buffer size to guarantee enough space.
1541*61c4878aSAndroid Build Coastguard Worker
1542*61c4878aSAndroid Build Coastguard WorkerWhen calculating yourself, the ``MaxScratchBufferSize()`` helper function can
1543*61c4878aSAndroid Build Coastguard Workeralso be useful in estimating how much space to allocate to account for nested
1544*61c4878aSAndroid Build Coastguard Workersubmessage encoding overhead.
1545*61c4878aSAndroid Build Coastguard Worker
1546*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
1547*61c4878aSAndroid Build Coastguard Worker
1548*61c4878aSAndroid Build Coastguard Worker   #include "my_protos/pets.pwpb.h"
1549*61c4878aSAndroid Build Coastguard Worker   #include "pw_bytes/span.h"
1550*61c4878aSAndroid Build Coastguard Worker   #include "pw_protobuf/encoder.h"
1551*61c4878aSAndroid Build Coastguard Worker   #include "pw_stream/sys_io_stream.h"
1552*61c4878aSAndroid Build Coastguard Worker
1553*61c4878aSAndroid Build Coastguard Worker   pw::stream::SysIoWriter sys_io_writer;
1554*61c4878aSAndroid Build Coastguard Worker   // The scratch buffer should be at least as big as the largest nested
1555*61c4878aSAndroid Build Coastguard Worker   // submessage. It's a good idea to be a little generous.
1556*61c4878aSAndroid Build Coastguard Worker   std::byte submessage_scratch_buffer[Owner::kScratchBufferSizeBytes];
1557*61c4878aSAndroid Build Coastguard Worker
1558*61c4878aSAndroid Build Coastguard Worker   // Provide the scratch buffer to the proto encoder. The buffer's lifetime must
1559*61c4878aSAndroid Build Coastguard Worker   // match the lifetime of the encoder.
1560*61c4878aSAndroid Build Coastguard Worker   Owner::StreamEncoder owner_encoder(sys_io_writer, submessage_scratch_buffer);
1561*61c4878aSAndroid Build Coastguard Worker
1562*61c4878aSAndroid Build Coastguard Worker   {
1563*61c4878aSAndroid Build Coastguard Worker     // Note that the parent encoder, owner_encoder, cannot be used until the
1564*61c4878aSAndroid Build Coastguard Worker     // nested encoder, pet_encoder, has been destroyed.
1565*61c4878aSAndroid Build Coastguard Worker     Animal::StreamEncoder pet_encoder = owner_encoder.GetPetEncoder();
1566*61c4878aSAndroid Build Coastguard Worker
1567*61c4878aSAndroid Build Coastguard Worker     // There's intermediate buffering when writing to a nested encoder.
1568*61c4878aSAndroid Build Coastguard Worker     pet_encoder.WriteName("Spot");
1569*61c4878aSAndroid Build Coastguard Worker     pet_encoder.WriteType(Pet::Type::DOG);
1570*61c4878aSAndroid Build Coastguard Worker
1571*61c4878aSAndroid Build Coastguard Worker     // When this scope ends, the nested encoder is serialized to the Writer.
1572*61c4878aSAndroid Build Coastguard Worker     // In addition, the parent encoder, owner_encoder, can be used again.
1573*61c4878aSAndroid Build Coastguard Worker   }
1574*61c4878aSAndroid Build Coastguard Worker
1575*61c4878aSAndroid Build Coastguard Worker   // If an encode error occurs when encoding the nested messages, it will be
1576*61c4878aSAndroid Build Coastguard Worker   // reflected at the root encoder.
1577*61c4878aSAndroid Build Coastguard Worker   if (!owner_encoder.status().ok()) {
1578*61c4878aSAndroid Build Coastguard Worker     PW_LOG_INFO("Failed to encode proto; %s", owner_encoder.status().str());
1579*61c4878aSAndroid Build Coastguard Worker   }
1580*61c4878aSAndroid Build Coastguard Worker
1581*61c4878aSAndroid Build Coastguard WorkerMemoryEncoder objects use the final destination buffer rather than relying on a
1582*61c4878aSAndroid Build Coastguard Workerscratch buffer.  The ``kMaxEncodedSizeBytes`` constant takes into account the
1583*61c4878aSAndroid Build Coastguard Workeroverhead required for nesting submessages. If you calculate the buffer size
1584*61c4878aSAndroid Build Coastguard Workeryourself, your destination buffer might need additional space.
1585*61c4878aSAndroid Build Coastguard Worker
1586*61c4878aSAndroid Build Coastguard Worker.. warning::
1587*61c4878aSAndroid Build Coastguard Worker   If the scratch buffer size is not sufficient, the encoding will fail with
1588*61c4878aSAndroid Build Coastguard Worker   ``Status::ResourceExhausted()``. Always check the results of ``Write`` calls
1589*61c4878aSAndroid Build Coastguard Worker   or the encoder status to ensure success, as otherwise the encoded data will
1590*61c4878aSAndroid Build Coastguard Worker   be invalid.
1591*61c4878aSAndroid Build Coastguard Worker
1592*61c4878aSAndroid Build Coastguard WorkerScalar Fields
1593*61c4878aSAndroid Build Coastguard Worker=============
1594*61c4878aSAndroid Build Coastguard WorkerAs shown, scalar fields are written using code generated ``WriteFoo``
1595*61c4878aSAndroid Build Coastguard Workermethods that accept the appropriate type and automatically writes the correct
1596*61c4878aSAndroid Build Coastguard Workerfield number.
1597*61c4878aSAndroid Build Coastguard Worker
1598*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status MyProto::StreamEncoder::WriteFoo(T)
1599*61c4878aSAndroid Build Coastguard Worker
1600*61c4878aSAndroid Build Coastguard WorkerThese can be freely intermixed with the lower-level API that provides a method
1601*61c4878aSAndroid Build Coastguard Workerper field type, requiring that the field number be passed in. The code
1602*61c4878aSAndroid Build Coastguard Workergeneration includes a ``Fields`` enum to provide the field number values.
1603*61c4878aSAndroid Build Coastguard Worker
1604*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamEncoder::WriteUint64(uint32_t field_number, uint64_t)
1605*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamEncoder::WriteSint64(uint32_t field_number, int64_t)
1606*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamEncoder::WriteInt64(uint32_t field_number, int64_t)
1607*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamEncoder::WriteUint32(uint32_t field_number, uint32_t)
1608*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamEncoder::WriteSint32(uint32_t field_number, int32_t)
1609*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamEncoder::WriteInt32(uint32_t field_number, int32_t)
1610*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamEncoder::WriteFixed64(uint32_t field_number, uint64_t)
1611*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamEncoder::WriteFixed32(uint32_t field_number, uint64_t)
1612*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamEncoder::WriteDouble(uint32_t field_number, double)
1613*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamEncoder::WriteFloat(uint32_t field_number, float)
1614*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamEncoder::WriteBool(uint32_t field_number, bool)
1615*61c4878aSAndroid Build Coastguard Worker
1616*61c4878aSAndroid Build Coastguard WorkerThe following two method calls are equivalent, where the first is using the
1617*61c4878aSAndroid Build Coastguard Workercode generated API, and the second implemented by hand.
1618*61c4878aSAndroid Build Coastguard Worker
1619*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
1620*61c4878aSAndroid Build Coastguard Worker
1621*61c4878aSAndroid Build Coastguard Worker   my_proto_encoder.WriteAge(42);
1622*61c4878aSAndroid Build Coastguard Worker   my_proto_encoder.WriteInt32(static_cast<uint32_t>(MyProto::Fields::kAge), 42);
1623*61c4878aSAndroid Build Coastguard Worker
1624*61c4878aSAndroid Build Coastguard WorkerRepeated Fields
1625*61c4878aSAndroid Build Coastguard Worker---------------
1626*61c4878aSAndroid Build Coastguard WorkerFor repeated scalar fields, multiple code generated ``WriteFoos`` methods
1627*61c4878aSAndroid Build Coastguard Workerare provided.
1628*61c4878aSAndroid Build Coastguard Worker
1629*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status MyProto::StreamEncoder::WriteFoos(T)
1630*61c4878aSAndroid Build Coastguard Worker
1631*61c4878aSAndroid Build Coastguard Worker   This writes a single unpacked value.
1632*61c4878aSAndroid Build Coastguard Worker
1633*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status MyProto::StreamEncoder::WriteFoos(pw::span<const T>)
1634*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status MyProto::StreamEncoder::WriteFoos(const pw::Vector<T>&)
1635*61c4878aSAndroid Build Coastguard Worker
1636*61c4878aSAndroid Build Coastguard Worker   These write a packed field containing all of the values in the provided span
1637*61c4878aSAndroid Build Coastguard Worker   or vector.
1638*61c4878aSAndroid Build Coastguard Worker
1639*61c4878aSAndroid Build Coastguard WorkerThese too can be freely intermixed with the lower-level API methods, both to
1640*61c4878aSAndroid Build Coastguard Workerwrite a single value, or to write packed values from either a ``pw::span`` or
1641*61c4878aSAndroid Build Coastguard Worker``pw::Vector`` source.
1642*61c4878aSAndroid Build Coastguard Worker
1643*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamEncoder::WritePackedUint64(uint32_t field_number, pw::span<const uint64_t>)
1644*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamEncoder::WriteRepeatedUint64(uint32_t field_number, const pw::Vector<uint64_t>&)
1645*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamEncoder::WritePackedSint64(uint32_t field_number, pw::span<const int64_t>)
1646*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamEncoder::WriteRepeatedSint64(uint32_t field_number, const pw::Vector<int64_t>&)
1647*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamEncoder::WritePackedInt64(uint32_t field_number, pw::span<const int64_t>)
1648*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamEncoder::WriteRepeatedInt64(uint32_t field_number, const pw::Vector<int64_t>&)
1649*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamEncoder::WritePackedUint32(uint32_t field_number, pw::span<const uint32_t>)
1650*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamEncoder::WriteRepeatedUint32(uint32_t field_number, const pw::Vector<uint32_t>&)
1651*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamEncoder::WritePackedSint32(uint32_t field_number, pw::span<const int32_t>)
1652*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamEncoder::WriteRepeatedSint32(uint32_t field_number, const pw::Vector<int32_t>&)
1653*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamEncoder::WritePackedInt32(uint32_t field_number, pw::span<const int32_t>)
1654*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamEncoder::WriteRepeatedInt32(uint32_t field_number, const pw::Vector<int32_t>&)
1655*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamEncoder::WritePackedFixed64(uint32_t field_number, pw::span<const uint64_t>)
1656*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamEncoder::WriteRepeatedFixed64(uint32_t field_number, const pw::Vector<uint64_t>&)
1657*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamEncoder::WritePackedFixed32(uint32_t field_number, pw::span<const uint64_t>)
1658*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamEncoder::WriteRepeatedFixed32(uint32_t field_number, const pw::Vector<uint64_t>&)
1659*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamEncoder::WritePackedDouble(uint32_t field_number, pw::span<const double>)
1660*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamEncoder::WriteRepeatedDouble(uint32_t field_number, const pw::Vector<double>&)
1661*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamEncoder::WritePackedFloat(uint32_t field_number, pw::span<const float>)
1662*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamEncoder::WriteRepeatedFloat(uint32_t field_number, const pw::Vector<float>&)
1663*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamEncoder::WritePackedBool(uint32_t field_number, pw::span<const bool>)
1664*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamEncoder::WriteRepeatedBool(uint32_t field_number, const pw::Vector<bool>&)
1665*61c4878aSAndroid Build Coastguard Worker
1666*61c4878aSAndroid Build Coastguard WorkerThe following two method calls are equivalent, where the first is using the
1667*61c4878aSAndroid Build Coastguard Workercode generated API, and the second implemented by hand.
1668*61c4878aSAndroid Build Coastguard Worker
1669*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
1670*61c4878aSAndroid Build Coastguard Worker
1671*61c4878aSAndroid Build Coastguard Worker   constexpr std::array<int32_t, 5> numbers = { 4, 8, 15, 16, 23, 42 };
1672*61c4878aSAndroid Build Coastguard Worker
1673*61c4878aSAndroid Build Coastguard Worker   my_proto_encoder.WriteNumbers(numbers);
1674*61c4878aSAndroid Build Coastguard Worker   my_proto_encoder.WritePackedInt32(
1675*61c4878aSAndroid Build Coastguard Worker       static_cast<uint32_t>(MyProto::Fields::kNumbers),
1676*61c4878aSAndroid Build Coastguard Worker       numbers);
1677*61c4878aSAndroid Build Coastguard Worker
1678*61c4878aSAndroid Build Coastguard WorkerEnumerations
1679*61c4878aSAndroid Build Coastguard Worker============
1680*61c4878aSAndroid Build Coastguard WorkerEnumerations are written using code generated ``WriteEnum`` methods that
1681*61c4878aSAndroid Build Coastguard Workeraccept the code generated enumeration as the appropriate type and automatically
1682*61c4878aSAndroid Build Coastguard Workerwrites both the correct field number and corresponding value.
1683*61c4878aSAndroid Build Coastguard Worker
1684*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status MyProto::StreamEncoder::WriteEnum(MyProto::Enum)
1685*61c4878aSAndroid Build Coastguard Worker
1686*61c4878aSAndroid Build Coastguard WorkerTo write enumerations with the lower-level API, you would need to cast both
1687*61c4878aSAndroid Build Coastguard Workerthe field number and value to the ``uint32_t`` type.
1688*61c4878aSAndroid Build Coastguard Worker
1689*61c4878aSAndroid Build Coastguard WorkerThe following two methods are equivalent, where the first is code generated,
1690*61c4878aSAndroid Build Coastguard Workerand the second implemented by hand.
1691*61c4878aSAndroid Build Coastguard Worker
1692*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
1693*61c4878aSAndroid Build Coastguard Worker
1694*61c4878aSAndroid Build Coastguard Worker   my_proto_encoder.WriteAward(MyProto::Award::SILVER);
1695*61c4878aSAndroid Build Coastguard Worker   my_proto_encoder.WriteUint32(
1696*61c4878aSAndroid Build Coastguard Worker       static_cast<uint32_t>(MyProto::Fields::kAward),
1697*61c4878aSAndroid Build Coastguard Worker       static_cast<uint32_t>(MyProto::Award::SILVER));
1698*61c4878aSAndroid Build Coastguard Worker
1699*61c4878aSAndroid Build Coastguard WorkerRepeated Fields
1700*61c4878aSAndroid Build Coastguard Worker---------------
1701*61c4878aSAndroid Build Coastguard WorkerFor repeated enum fields, multiple code generated ``WriteEnums`` methods
1702*61c4878aSAndroid Build Coastguard Workerare provided.
1703*61c4878aSAndroid Build Coastguard Worker
1704*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status MyProto::StreamEncoder::WriteEnums(MyProto::Enums)
1705*61c4878aSAndroid Build Coastguard Worker
1706*61c4878aSAndroid Build Coastguard Worker   This writes a single unpacked value.
1707*61c4878aSAndroid Build Coastguard Worker
1708*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status MyProto::StreamEncoder::WriteEnums(pw::span<const MyProto::Enums>)
1709*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status MyProto::StreamEncoder::WriteEnums(const pw::Vector<MyProto::Enums>&)
1710*61c4878aSAndroid Build Coastguard Worker
1711*61c4878aSAndroid Build Coastguard Worker   These write a packed field containing all of the values in the provided span
1712*61c4878aSAndroid Build Coastguard Worker   or vector.
1713*61c4878aSAndroid Build Coastguard Worker
1714*61c4878aSAndroid Build Coastguard WorkerTheir use is as scalar fields.
1715*61c4878aSAndroid Build Coastguard Worker
1716*61c4878aSAndroid Build Coastguard WorkerStrings
1717*61c4878aSAndroid Build Coastguard Worker=======
1718*61c4878aSAndroid Build Coastguard WorkerStrings fields have multiple code generated methods provided.
1719*61c4878aSAndroid Build Coastguard Worker
1720*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status MyProto::StreamEncoder::WriteName(std::string_view)
1721*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status MyProto::StreamEncoder::WriteName(const char*, size_t)
1722*61c4878aSAndroid Build Coastguard Worker
1723*61c4878aSAndroid Build Coastguard WorkerThese can be freely intermixed with the lower-level API methods.
1724*61c4878aSAndroid Build Coastguard Worker
1725*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamEncoder::WriteString(uint32_t field_number, std::string_view)
1726*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamEncoder::WriteString(uint32_t field_number, const char*, size_t)
1727*61c4878aSAndroid Build Coastguard Worker
1728*61c4878aSAndroid Build Coastguard WorkerA lower level API method is provided that can write a string from another
1729*61c4878aSAndroid Build Coastguard Workerstream.
1730*61c4878aSAndroid Build Coastguard Worker
1731*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamEncoder::WriteStringFromStream(uint32_t field_number, stream::Reader& bytes_reader, size_t num_bytes, ByteSpan stream_pipe_buffer)
1732*61c4878aSAndroid Build Coastguard Worker
1733*61c4878aSAndroid Build Coastguard Worker   The payload for the value is provided through the stream::Reader
1734*61c4878aSAndroid Build Coastguard Worker   ``bytes_reader``. The method reads a chunk of the data from the reader using
1735*61c4878aSAndroid Build Coastguard Worker   the ``stream_pipe_buffer`` and writes it to the encoder.
1736*61c4878aSAndroid Build Coastguard Worker
1737*61c4878aSAndroid Build Coastguard WorkerBytes
1738*61c4878aSAndroid Build Coastguard Worker=====
1739*61c4878aSAndroid Build Coastguard WorkerBytes fields provide the ``WriteData`` code generated method.
1740*61c4878aSAndroid Build Coastguard Worker
1741*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status MyProto::StreamEncoder::WriteData(ConstByteSpan)
1742*61c4878aSAndroid Build Coastguard Worker
1743*61c4878aSAndroid Build Coastguard WorkerThis can be freely intermixed with the lower-level API method.
1744*61c4878aSAndroid Build Coastguard Worker
1745*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamEncoder::WriteBytes(uint32_t field_number, ConstByteSpan)
1746*61c4878aSAndroid Build Coastguard Worker
1747*61c4878aSAndroid Build Coastguard WorkerAnd with the API method that can write bytes from another stream.
1748*61c4878aSAndroid Build Coastguard Worker
1749*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamEncoder::WriteBytesFromStream(uint32_t field_number, stream::Reader& bytes_reader, size_t num_bytes, ByteSpan stream_pipe_buffer)
1750*61c4878aSAndroid Build Coastguard Worker
1751*61c4878aSAndroid Build Coastguard Worker   The payload for the value is provided through the stream::Reader
1752*61c4878aSAndroid Build Coastguard Worker   ``bytes_reader``. The method reads a chunk of the data from the reader using
1753*61c4878aSAndroid Build Coastguard Worker   the ``stream_pipe_buffer`` and writes it to the encoder.
1754*61c4878aSAndroid Build Coastguard Worker
1755*61c4878aSAndroid Build Coastguard WorkerError Handling
1756*61c4878aSAndroid Build Coastguard Worker==============
1757*61c4878aSAndroid Build Coastguard WorkerWhile individual write calls on a proto encoder return ``pw::Status`` objects,
1758*61c4878aSAndroid Build Coastguard Workerthe encoder tracks all status returns and "latches" onto the first error
1759*61c4878aSAndroid Build Coastguard Workerencountered. This status can be accessed via ``StreamEncoder::status()``.
1760*61c4878aSAndroid Build Coastguard Worker
1761*61c4878aSAndroid Build Coastguard WorkerProto map encoding utils
1762*61c4878aSAndroid Build Coastguard Worker========================
1763*61c4878aSAndroid Build Coastguard WorkerSome additional helpers for encoding more complex but common protobuf
1764*61c4878aSAndroid Build Coastguard Workersubmessages (e.g. ``map<string, bytes>``) are provided in
1765*61c4878aSAndroid Build Coastguard Worker``pw_protobuf/map_utils.h``.
1766*61c4878aSAndroid Build Coastguard Worker
1767*61c4878aSAndroid Build Coastguard Worker.. note::
1768*61c4878aSAndroid Build Coastguard Worker   The helper API are currently in-development and may not remain stable.
1769*61c4878aSAndroid Build Coastguard Worker
1770*61c4878aSAndroid Build Coastguard Worker--------
1771*61c4878aSAndroid Build Coastguard WorkerDecoding
1772*61c4878aSAndroid Build Coastguard Worker--------
1773*61c4878aSAndroid Build Coastguard WorkerThe simplest way to use ``StreamDecoder`` is to decode a proto from the stream
1774*61c4878aSAndroid Build Coastguard Workerinto its code generated ``Message`` structure.
1775*61c4878aSAndroid Build Coastguard Worker
1776*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
1777*61c4878aSAndroid Build Coastguard Worker
1778*61c4878aSAndroid Build Coastguard Worker   #include "my_protos/my_proto.pwpb.h"
1779*61c4878aSAndroid Build Coastguard Worker   #include "pw_protobuf/stream_decoder.h"
1780*61c4878aSAndroid Build Coastguard Worker   #include "pw_status/status.h"
1781*61c4878aSAndroid Build Coastguard Worker   #include "pw_stream/stream.h"
1782*61c4878aSAndroid Build Coastguard Worker
1783*61c4878aSAndroid Build Coastguard Worker   pw::Status DecodeProtoFromStream(pw::stream::Reader& reader) {
1784*61c4878aSAndroid Build Coastguard Worker     MyProto::Message message{};
1785*61c4878aSAndroid Build Coastguard Worker     MyProto::StreamDecoder decoder(reader);
1786*61c4878aSAndroid Build Coastguard Worker     decoder.Read(message);
1787*61c4878aSAndroid Build Coastguard Worker     return decoder.status();
1788*61c4878aSAndroid Build Coastguard Worker   }
1789*61c4878aSAndroid Build Coastguard Worker
1790*61c4878aSAndroid Build Coastguard WorkerIn the case of errors, the decoding will stop and return with the cursor on the
1791*61c4878aSAndroid Build Coastguard Workerfield that caused the error. It is valid in some cases to inspect the error and
1792*61c4878aSAndroid Build Coastguard Workercontinue decoding by calling ``Read()`` again on the same structure, or fall
1793*61c4878aSAndroid Build Coastguard Workerback to using the lower-level APIs.
1794*61c4878aSAndroid Build Coastguard Worker
1795*61c4878aSAndroid Build Coastguard WorkerUnknown fields in the wire encoding are skipped.
1796*61c4878aSAndroid Build Coastguard Worker
1797*61c4878aSAndroid Build Coastguard WorkerIf finer-grained control is required, the ``StreamDecoder`` class provides an
1798*61c4878aSAndroid Build Coastguard Workeriterator-style API for processing a message a field at a time where calling
1799*61c4878aSAndroid Build Coastguard Worker``Next()`` advances the decoder to the next proto field.
1800*61c4878aSAndroid Build Coastguard Worker
1801*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamDecoder::Next()
1802*61c4878aSAndroid Build Coastguard Worker
1803*61c4878aSAndroid Build Coastguard WorkerIn the code generated classes the ``Field()`` method returns the current field
1804*61c4878aSAndroid Build Coastguard Workeras a typed ``Fields`` enumeration member, while the lower-level API provides a
1805*61c4878aSAndroid Build Coastguard Worker``FieldNumber()`` method that returns the number of the field.
1806*61c4878aSAndroid Build Coastguard Worker
1807*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Result<MyProto::Fields> MyProto::StreamDecoder::Field()
1808*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Result<uint32_t> pw::protobuf::StreamDecoder::FieldNumber()
1809*61c4878aSAndroid Build Coastguard Worker
1810*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
1811*61c4878aSAndroid Build Coastguard Worker
1812*61c4878aSAndroid Build Coastguard Worker   #include "my_protos/my_proto.pwpb.h"
1813*61c4878aSAndroid Build Coastguard Worker   #include "pw_protobuf/strema_decoder.h"
1814*61c4878aSAndroid Build Coastguard Worker   #include "pw_status/status.h"
1815*61c4878aSAndroid Build Coastguard Worker   #include "pw_status/try.h"
1816*61c4878aSAndroid Build Coastguard Worker   #include "pw_stream/stream.h"
1817*61c4878aSAndroid Build Coastguard Worker
1818*61c4878aSAndroid Build Coastguard Worker   pw::Status DecodeProtoFromStream(pw::stream::Reader& reader) {
1819*61c4878aSAndroid Build Coastguard Worker     MyProto::StreamDecoder decoder(reader);
1820*61c4878aSAndroid Build Coastguard Worker     pw::Status status;
1821*61c4878aSAndroid Build Coastguard Worker
1822*61c4878aSAndroid Build Coastguard Worker     uint32_t age;
1823*61c4878aSAndroid Build Coastguard Worker     char name[16];
1824*61c4878aSAndroid Build Coastguard Worker
1825*61c4878aSAndroid Build Coastguard Worker     // Iterate over the fields in the message. A return value of OK indicates
1826*61c4878aSAndroid Build Coastguard Worker     // that a valid field has been found and can be read. When the decoder
1827*61c4878aSAndroid Build Coastguard Worker     // reaches the end of the message, Next() will return OUT_OF_RANGE.
1828*61c4878aSAndroid Build Coastguard Worker     // Other return values indicate an error trying to decode the message.
1829*61c4878aSAndroid Build Coastguard Worker     while ((status = decoder.Next()).ok()) {
1830*61c4878aSAndroid Build Coastguard Worker       // Field() returns a Result<Fields> as it may fail sometimes.
1831*61c4878aSAndroid Build Coastguard Worker       // However, Field() is guaranteed to be valid after a call to Next()
1832*61c4878aSAndroid Build Coastguard Worker       // that returns OK, so the value can be used directly here.
1833*61c4878aSAndroid Build Coastguard Worker       switch (decoder.Field().value()) {
1834*61c4878aSAndroid Build Coastguard Worker         case MyProto::Fields::kAge: {
1835*61c4878aSAndroid Build Coastguard Worker           PW_TRY_ASSIGN(age, decoder.ReadAge());
1836*61c4878aSAndroid Build Coastguard Worker           break;
1837*61c4878aSAndroid Build Coastguard Worker         }
1838*61c4878aSAndroid Build Coastguard Worker         case MyProto::Fields::kName:
1839*61c4878aSAndroid Build Coastguard Worker           // The string field is copied into the provided buffer. If the buffer
1840*61c4878aSAndroid Build Coastguard Worker           // is too small to fit the string, RESOURCE_EXHAUSTED is returned and
1841*61c4878aSAndroid Build Coastguard Worker           // the decoder is not advanced, allowing the field to be re-read.
1842*61c4878aSAndroid Build Coastguard Worker           PW_TRY(decoder.ReadName(name));
1843*61c4878aSAndroid Build Coastguard Worker           break;
1844*61c4878aSAndroid Build Coastguard Worker       }
1845*61c4878aSAndroid Build Coastguard Worker     }
1846*61c4878aSAndroid Build Coastguard Worker
1847*61c4878aSAndroid Build Coastguard Worker     // Do something with the fields...
1848*61c4878aSAndroid Build Coastguard Worker
1849*61c4878aSAndroid Build Coastguard Worker     return status.IsOutOfRange() ? OkStatus() : status;
1850*61c4878aSAndroid Build Coastguard Worker   }
1851*61c4878aSAndroid Build Coastguard Worker
1852*61c4878aSAndroid Build Coastguard WorkerCallbacks
1853*61c4878aSAndroid Build Coastguard Worker=========
1854*61c4878aSAndroid Build Coastguard WorkerWhen using the ``Read()`` method with a ``struct Message``, certain fields may
1855*61c4878aSAndroid Build Coastguard Workerrequire a callback function be set, otherwise a ``DataLoss`` error will be
1856*61c4878aSAndroid Build Coastguard Workerreturned should that field be encountered in the wire encoding.
1857*61c4878aSAndroid Build Coastguard Worker
1858*61c4878aSAndroid Build Coastguard WorkerThe callback is called with the cursor at the field in question, and passed
1859*61c4878aSAndroid Build Coastguard Workera reference to the typed decoder that can examine the field and be used to
1860*61c4878aSAndroid Build Coastguard Workerdecode it.
1861*61c4878aSAndroid Build Coastguard Worker
1862*61c4878aSAndroid Build Coastguard WorkerCallback implementations may use any level of API. For example a callback for a
1863*61c4878aSAndroid Build Coastguard Workernested submessage (with a dependency cycle, or repeated) can be implemented by
1864*61c4878aSAndroid Build Coastguard Workercalling ``Read()`` on a nested decoder.
1865*61c4878aSAndroid Build Coastguard Worker
1866*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
1867*61c4878aSAndroid Build Coastguard Worker
1868*61c4878aSAndroid Build Coastguard Worker   Store::Message store{};
1869*61c4878aSAndroid Build Coastguard Worker   store.employees.SetDecoder([](Store::StreamDecoder& decoder) {
1870*61c4878aSAndroid Build Coastguard Worker     PW_ASSERT(decoder.Field().value() == Store::Fields::kEmployees);
1871*61c4878aSAndroid Build Coastguard Worker
1872*61c4878aSAndroid Build Coastguard Worker     Employee::Message employee{};
1873*61c4878aSAndroid Build Coastguard Worker     // Set any callbacks on `employee`.
1874*61c4878aSAndroid Build Coastguard Worker     PW_TRY(decoder.GetEmployeesDecoder().Read(employee));
1875*61c4878aSAndroid Build Coastguard Worker     // Do things with `employee`.
1876*61c4878aSAndroid Build Coastguard Worker     return OkStatus();
1877*61c4878aSAndroid Build Coastguard Worker   ));
1878*61c4878aSAndroid Build Coastguard Worker
1879*61c4878aSAndroid Build Coastguard WorkerNested submessages
1880*61c4878aSAndroid Build Coastguard Worker==================
1881*61c4878aSAndroid Build Coastguard WorkerCode generated ``GetFieldDecoder`` methods are provided that return a correctly
1882*61c4878aSAndroid Build Coastguard Workertyped ``StreamDecoder`` for the message.
1883*61c4878aSAndroid Build Coastguard Worker
1884*61c4878aSAndroid Build Coastguard Worker.. code-block:: protobuf
1885*61c4878aSAndroid Build Coastguard Worker
1886*61c4878aSAndroid Build Coastguard Worker   message Owner {
1887*61c4878aSAndroid Build Coastguard Worker     Animal pet = 1;
1888*61c4878aSAndroid Build Coastguard Worker   }
1889*61c4878aSAndroid Build Coastguard Worker
1890*61c4878aSAndroid Build Coastguard WorkerAs with encoding, note that the accessor method is named for the field, while
1891*61c4878aSAndroid Build Coastguard Workerthe returned decoder is named for the message type.
1892*61c4878aSAndroid Build Coastguard Worker
1893*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Animal::StreamDecoder Owner::StreamDecoder::GetPetDecoder()
1894*61c4878aSAndroid Build Coastguard Worker
1895*61c4878aSAndroid Build Coastguard WorkerA lower-level API method returns an untyped decoder, which only provides the
1896*61c4878aSAndroid Build Coastguard Workerlower-level API methods. This can be moved to a typed decoder later.
1897*61c4878aSAndroid Build Coastguard Worker
1898*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: pw::protobuf::StreamDecoder pw::protobuf::StreamDecoder::GetNestedDecoder()
1899*61c4878aSAndroid Build Coastguard Worker
1900*61c4878aSAndroid Build Coastguard Worker.. warning::
1901*61c4878aSAndroid Build Coastguard Worker   When a nested submessage is being decoded, any use of the parent decoder that
1902*61c4878aSAndroid Build Coastguard Worker   created the nested decoder will trigger a crash. To resume using the parent
1903*61c4878aSAndroid Build Coastguard Worker   decoder, destroy the submessage decoder first.
1904*61c4878aSAndroid Build Coastguard Worker
1905*61c4878aSAndroid Build Coastguard Worker
1906*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
1907*61c4878aSAndroid Build Coastguard Worker
1908*61c4878aSAndroid Build Coastguard Worker   case Owner::Fields::kPet: {
1909*61c4878aSAndroid Build Coastguard Worker     // Note that the parent decoder, owner_decoder, cannot be used until the
1910*61c4878aSAndroid Build Coastguard Worker     // nested decoder, pet_decoder, has been destroyed.
1911*61c4878aSAndroid Build Coastguard Worker     Animal::StreamDecoder pet_decoder = owner_decoder.GetPetDecoder();
1912*61c4878aSAndroid Build Coastguard Worker
1913*61c4878aSAndroid Build Coastguard Worker     while ((status = pet_decoder.Next()).ok()) {
1914*61c4878aSAndroid Build Coastguard Worker       switch (pet_decoder.Field().value()) {
1915*61c4878aSAndroid Build Coastguard Worker         // Decode pet fields...
1916*61c4878aSAndroid Build Coastguard Worker       }
1917*61c4878aSAndroid Build Coastguard Worker     }
1918*61c4878aSAndroid Build Coastguard Worker
1919*61c4878aSAndroid Build Coastguard Worker     // When this scope ends, the nested decoder is destroyed and the
1920*61c4878aSAndroid Build Coastguard Worker     // parent decoder, owner_decoder, can be used again.
1921*61c4878aSAndroid Build Coastguard Worker     break;
1922*61c4878aSAndroid Build Coastguard Worker   }
1923*61c4878aSAndroid Build Coastguard Worker
1924*61c4878aSAndroid Build Coastguard WorkerScalar Fields
1925*61c4878aSAndroid Build Coastguard Worker=============
1926*61c4878aSAndroid Build Coastguard WorkerScalar fields are read using code generated ``ReadFoo`` methods that return the
1927*61c4878aSAndroid Build Coastguard Workerappropriate type and assert that the correct field number ie being read.
1928*61c4878aSAndroid Build Coastguard Worker
1929*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Result<T> MyProto::StreamDecoder::ReadFoo()
1930*61c4878aSAndroid Build Coastguard Worker
1931*61c4878aSAndroid Build Coastguard WorkerThese can be freely intermixed with the lower-level API that provides a method
1932*61c4878aSAndroid Build Coastguard Workerper field type, requiring that the caller first check the field number.
1933*61c4878aSAndroid Build Coastguard Worker
1934*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Result<uint64_t> pw::protobuf::StreamDecoder::ReadUint64()
1935*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Result<int64_t> pw::protobuf::StreamDecoder::ReadSint64()
1936*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Result<int64_t> pw::protobuf::StreamDecoder::ReadInt64()
1937*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Result<uint32_t> pw::protobuf::StreamDecoder::ReadUint32()
1938*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Result<int32_t> pw::protobuf::StreamDecoder::ReadSint32()
1939*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Result<int32_t> pw::protobuf::StreamDecoder::ReadInt32()
1940*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Result<uint64_t> pw::protobuf::StreamDecoder::ReadFixed64()
1941*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Result<uint64_t> pw::protobuf::StreamDecoder::ReadFixed32()
1942*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Result<double> pw::protobuf::StreamDecoder::ReadDouble()
1943*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Result<float> pw::protobuf::StreamDecoder::ReadFloat()
1944*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Result<bool> pw::protobuf::StreamDecoder::ReadBool()
1945*61c4878aSAndroid Build Coastguard Worker
1946*61c4878aSAndroid Build Coastguard WorkerThe following two code snippets are equivalent, where the first uses the code
1947*61c4878aSAndroid Build Coastguard Workergenerated API, and the second implemented by hand.
1948*61c4878aSAndroid Build Coastguard Worker
1949*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
1950*61c4878aSAndroid Build Coastguard Worker
1951*61c4878aSAndroid Build Coastguard Worker   pw::Result<int32_t> age = my_proto_decoder.ReadAge();
1952*61c4878aSAndroid Build Coastguard Worker
1953*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
1954*61c4878aSAndroid Build Coastguard Worker
1955*61c4878aSAndroid Build Coastguard Worker   PW_ASSERT(my_proto_decoder.FieldNumber().value() ==
1956*61c4878aSAndroid Build Coastguard Worker       static_cast<uint32_t>(MyProto::Fields::kAge));
1957*61c4878aSAndroid Build Coastguard Worker   pw::Result<int32_t> my_proto_decoder.ReadInt32();
1958*61c4878aSAndroid Build Coastguard Worker
1959*61c4878aSAndroid Build Coastguard WorkerRepeated Fields
1960*61c4878aSAndroid Build Coastguard Worker---------------
1961*61c4878aSAndroid Build Coastguard WorkerFor repeated scalar fields, multiple code generated ``ReadFoos`` methods
1962*61c4878aSAndroid Build Coastguard Workerare provided.
1963*61c4878aSAndroid Build Coastguard Worker
1964*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Result<T> MyProto::StreamDecoder::ReadFoos()
1965*61c4878aSAndroid Build Coastguard Worker
1966*61c4878aSAndroid Build Coastguard Worker   This reads a single unpacked value.
1967*61c4878aSAndroid Build Coastguard Worker
1968*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: StatusWithSize MyProto::StreamDecoder::ReadFoos(pw::span<T>)
1969*61c4878aSAndroid Build Coastguard Worker
1970*61c4878aSAndroid Build Coastguard Worker   This reads a packed field containing all of the values into the provided span.
1971*61c4878aSAndroid Build Coastguard Worker
1972*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status MyProto::StreamDecoder::ReadFoos(pw::Vector<T>&)
1973*61c4878aSAndroid Build Coastguard Worker
1974*61c4878aSAndroid Build Coastguard Worker   Protobuf encoders are permitted to choose either repeating single unpacked
1975*61c4878aSAndroid Build Coastguard Worker   values, or a packed field, including splitting repeated fields up into
1976*61c4878aSAndroid Build Coastguard Worker   multiple packed fields.
1977*61c4878aSAndroid Build Coastguard Worker
1978*61c4878aSAndroid Build Coastguard Worker   This method supports either format, appending values to the provided
1979*61c4878aSAndroid Build Coastguard Worker   ``pw::Vector``.
1980*61c4878aSAndroid Build Coastguard Worker
1981*61c4878aSAndroid Build Coastguard WorkerThese too can be freely intermixed with the lower-level API methods, to read a
1982*61c4878aSAndroid Build Coastguard Workersingle value, a field of packed values into a ``pw::span``, or support both
1983*61c4878aSAndroid Build Coastguard Workerformats appending to a ``pw::Vector`` source.
1984*61c4878aSAndroid Build Coastguard Worker
1985*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: StatusWithSize pw::protobuf::StreamDecoder::ReadPackedUint64(pw::span<uint64_t>)
1986*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamDecoder::ReadRepeatedUint64(pw::Vector<uint64_t>&)
1987*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: StatusWithSize pw::protobuf::StreamDecoder::ReadPackedSint64(pw::span<int64_t>)
1988*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamDecoder::ReadRepeatedSint64(pw::Vector<int64_t>&)
1989*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: StatusWithSize pw::protobuf::StreamDecoder::ReadPackedInt64(pw::span<int64_t>)
1990*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamDecoder::ReadRepeatedInt64(pw::Vector<int64_t>&)
1991*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: StatusWithSize pw::protobuf::StreamDecoder::ReadPackedUint32(pw::span<uint32_t>)
1992*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamDecoder::ReadRepeatedUint32(pw::Vector<uint32_t>&)
1993*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: StatusWithSize pw::protobuf::StreamDecoder::ReadPackedSint32(pw::span<int32_t>)
1994*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamDecoder::ReadRepeatedSint32(pw::Vector<int32_t>&)
1995*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: StatusWithSize pw::protobuf::StreamDecoder::ReadPackedInt32(pw::span<int32_t>)
1996*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamDecoder::ReadRepeatedInt32(pw::Vector<int32_t>&)
1997*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: StatusWithSize pw::protobuf::StreamDecoder::ReadPackedFixed64(pw::span<uint64_t>)
1998*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamDecoder::ReadRepeatedFixed64(pw::Vector<uint64_t>&)
1999*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: StatusWithSize pw::protobuf::StreamDecoder::ReadPackedFixed32(pw::span<uint64_t>)
2000*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamDecoder::ReadRepeatedFixed32(pw::Vector<uint64_t>&)
2001*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: StatusWithSize pw::protobuf::StreamDecoder::ReadPackedDouble(pw::span<double>)
2002*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamDecoder::ReadRepeatedDouble(pw::Vector<double>&)
2003*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: StatusWithSize pw::protobuf::StreamDecoder::ReadPackedFloat(pw::span<float>)
2004*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamDecoder::ReadRepeatedFloat(pw::Vector<float>&)
2005*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: StatusWithSize pw::protobuf::StreamDecoder::ReadPackedBool(pw::span<bool>)
2006*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status pw::protobuf::StreamDecoder::ReadRepeatedBool(pw::Vector<bool>&)
2007*61c4878aSAndroid Build Coastguard Worker
2008*61c4878aSAndroid Build Coastguard WorkerThe following two code blocks are equivalent, where the first uses the code
2009*61c4878aSAndroid Build Coastguard Workergenerated API, and the second is implemented by hand.
2010*61c4878aSAndroid Build Coastguard Worker
2011*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
2012*61c4878aSAndroid Build Coastguard Worker
2013*61c4878aSAndroid Build Coastguard Worker   pw::Vector<int32_t, 8> numbers;
2014*61c4878aSAndroid Build Coastguard Worker
2015*61c4878aSAndroid Build Coastguard Worker   my_proto_decoder.ReadNumbers(numbers);
2016*61c4878aSAndroid Build Coastguard Worker
2017*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
2018*61c4878aSAndroid Build Coastguard Worker
2019*61c4878aSAndroid Build Coastguard Worker   pw::Vector<int32_t, 8> numbers;
2020*61c4878aSAndroid Build Coastguard Worker
2021*61c4878aSAndroid Build Coastguard Worker   PW_ASSERT(my_proto_decoder.FieldNumber().value() ==
2022*61c4878aSAndroid Build Coastguard Worker       static_cast<uint32_t>(MyProto::Fields::kNumbers));
2023*61c4878aSAndroid Build Coastguard Worker   my_proto_decoder.ReadRepeatedInt32(numbers);
2024*61c4878aSAndroid Build Coastguard Worker
2025*61c4878aSAndroid Build Coastguard WorkerEnumerations
2026*61c4878aSAndroid Build Coastguard Worker============
2027*61c4878aSAndroid Build Coastguard Worker``pw_protobuf`` generates a few functions for working with enumerations.
2028*61c4878aSAndroid Build Coastguard WorkerMost importantly, enumerations are read using generated ``ReadEnum`` methods
2029*61c4878aSAndroid Build Coastguard Workerthat return the enumeration as the appropriate generated type.
2030*61c4878aSAndroid Build Coastguard Worker
2031*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Result<MyProto::Enum> MyProto::StreamDecoder::ReadEnum()
2032*61c4878aSAndroid Build Coastguard Worker
2033*61c4878aSAndroid Build Coastguard Worker   Decodes an enum from the stream.
2034*61c4878aSAndroid Build Coastguard Worker
2035*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: constexpr bool MyProto::IsValidEnum(MyProto::Enum value)
2036*61c4878aSAndroid Build Coastguard Worker
2037*61c4878aSAndroid Build Coastguard Worker   Validates the value encoded in the wire format against the known set of
2038*61c4878aSAndroid Build Coastguard Worker   enumerates.
2039*61c4878aSAndroid Build Coastguard Worker
2040*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: constexpr const char* MyProto::EnumToString(MyProto::Enum value)
2041*61c4878aSAndroid Build Coastguard Worker
2042*61c4878aSAndroid Build Coastguard Worker   Returns the string representation of the enum value. For example,
2043*61c4878aSAndroid Build Coastguard Worker   ``FooToString(Foo::kBarBaz)`` returns ``"BAR_BAZ"``. Returns the empty string
2044*61c4878aSAndroid Build Coastguard Worker   if the value is not a valid value.
2045*61c4878aSAndroid Build Coastguard Worker
2046*61c4878aSAndroid Build Coastguard WorkerTo read enumerations with the lower-level API, you would need to cast the
2047*61c4878aSAndroid Build Coastguard Workerretured value from the ``uint32_t``.
2048*61c4878aSAndroid Build Coastguard Worker
2049*61c4878aSAndroid Build Coastguard WorkerThe following two code blocks are equivalent, where the first is using the code
2050*61c4878aSAndroid Build Coastguard Workergenerated API, and the second implemented by hand.
2051*61c4878aSAndroid Build Coastguard Worker
2052*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
2053*61c4878aSAndroid Build Coastguard Worker
2054*61c4878aSAndroid Build Coastguard Worker   pw::Result<MyProto::Award> award = my_proto_decoder.ReadAward();
2055*61c4878aSAndroid Build Coastguard Worker   if (!MyProto::IsValidAward(award)) {
2056*61c4878aSAndroid Build Coastguard Worker     PW_LOG_DBG("Unknown award");
2057*61c4878aSAndroid Build Coastguard Worker   }
2058*61c4878aSAndroid Build Coastguard Worker
2059*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
2060*61c4878aSAndroid Build Coastguard Worker
2061*61c4878aSAndroid Build Coastguard Worker   PW_ASSERT(my_proto_decoder.FieldNumber().value() ==
2062*61c4878aSAndroid Build Coastguard Worker       static_cast<uint32_t>(MyProto::Fields::kAward));
2063*61c4878aSAndroid Build Coastguard Worker   pw::Result<uint32_t> award_value = my_proto_decoder.ReadUint32();
2064*61c4878aSAndroid Build Coastguard Worker   if (award_value.ok()) {
2065*61c4878aSAndroid Build Coastguard Worker     MyProto::Award award = static_cast<MyProto::Award>(award_value);
2066*61c4878aSAndroid Build Coastguard Worker   }
2067*61c4878aSAndroid Build Coastguard Worker
2068*61c4878aSAndroid Build Coastguard WorkerRepeated Fields
2069*61c4878aSAndroid Build Coastguard Worker---------------
2070*61c4878aSAndroid Build Coastguard WorkerFor repeated enum fields, multiple code generated ``ReadEnums`` methods
2071*61c4878aSAndroid Build Coastguard Workerare provided.
2072*61c4878aSAndroid Build Coastguard Worker
2073*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Result<MyProto::Enums> MyProto::StreamDecoder::ReadEnums()
2074*61c4878aSAndroid Build Coastguard Worker
2075*61c4878aSAndroid Build Coastguard Worker   This reads a single unpacked value.
2076*61c4878aSAndroid Build Coastguard Worker
2077*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: StatusWithSize MyProto::StreamDecoder::ReadEnums(pw::span<MyProto::Enums>)
2078*61c4878aSAndroid Build Coastguard Worker
2079*61c4878aSAndroid Build Coastguard Worker   This reads a packed field containing all of the checked values into the
2080*61c4878aSAndroid Build Coastguard Worker   provided span.
2081*61c4878aSAndroid Build Coastguard Worker
2082*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: Status MyProto::StreamDecoder::ReadEnums(pw::Vector<MyProto::Enums>&)
2083*61c4878aSAndroid Build Coastguard Worker
2084*61c4878aSAndroid Build Coastguard Worker   This method supports either repeated unpacked or packed formats, appending
2085*61c4878aSAndroid Build Coastguard Worker   checked values to the provided ``pw::Vector``.
2086*61c4878aSAndroid Build Coastguard Worker
2087*61c4878aSAndroid Build Coastguard WorkerTheir use is as scalar fields.
2088*61c4878aSAndroid Build Coastguard Worker
2089*61c4878aSAndroid Build Coastguard WorkerStrings
2090*61c4878aSAndroid Build Coastguard Worker=======
2091*61c4878aSAndroid Build Coastguard WorkerStrings fields provide a code generated method to read the string into the
2092*61c4878aSAndroid Build Coastguard Workerprovided span. Since the span is updated with the size of the string, the string
2093*61c4878aSAndroid Build Coastguard Workeris not automatically null-terminated. :ref:`module-pw_string` provides utility
2094*61c4878aSAndroid Build Coastguard Workermethods to copy string data from spans into other targets.
2095*61c4878aSAndroid Build Coastguard Worker
2096*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: StatusWithSize MyProto::StreamDecoder::ReadName(pw::span<char>)
2097*61c4878aSAndroid Build Coastguard Worker
2098*61c4878aSAndroid Build Coastguard WorkerAn additional code generated method is provided to return a nested
2099*61c4878aSAndroid Build Coastguard Worker``BytesReader`` to access the data as a stream. As with nested submessage
2100*61c4878aSAndroid Build Coastguard Workerdecoders, any use of the parent decoder that created the bytes reader will
2101*61c4878aSAndroid Build Coastguard Workertrigger a crash. To resume using the parent decoder, destroy the bytes reader
2102*61c4878aSAndroid Build Coastguard Workerfirst.
2103*61c4878aSAndroid Build Coastguard Worker
2104*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: pw::protobuf::StreamDecoder::BytesReader MyProto::StreamDecoder::GetNameReader()
2105*61c4878aSAndroid Build Coastguard Worker
2106*61c4878aSAndroid Build Coastguard WorkerThese can be freely intermixed with the lower-level API method:
2107*61c4878aSAndroid Build Coastguard Worker
2108*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: StatusWithSize pw::protobuf::StreamDecoder::ReadString(pw::span<char>)
2109*61c4878aSAndroid Build Coastguard Worker
2110*61c4878aSAndroid Build Coastguard WorkerThe lower-level ``GetBytesReader()`` method can also be used to read string data
2111*61c4878aSAndroid Build Coastguard Workeras bytes.
2112*61c4878aSAndroid Build Coastguard Worker
2113*61c4878aSAndroid Build Coastguard WorkerBytes
2114*61c4878aSAndroid Build Coastguard Worker=====
2115*61c4878aSAndroid Build Coastguard WorkerBytes fields provide the ``WriteData`` code generated method to read the bytes
2116*61c4878aSAndroid Build Coastguard Workerinto the provided span.
2117*61c4878aSAndroid Build Coastguard Worker
2118*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: StatusWithSize MyProto::StreamDecoder::ReadData(ByteSpan)
2119*61c4878aSAndroid Build Coastguard Worker
2120*61c4878aSAndroid Build Coastguard WorkerAn additional code generated method is provided to return a nested
2121*61c4878aSAndroid Build Coastguard Worker``BytesReader`` to access the data as a stream. As with nested submessage
2122*61c4878aSAndroid Build Coastguard Workerdecoders, any use of the parent decoder that created the bytes reader will
2123*61c4878aSAndroid Build Coastguard Workertrigger a crash. To resume using the parent decoder, destroy the bytes reader
2124*61c4878aSAndroid Build Coastguard Workerfirst.
2125*61c4878aSAndroid Build Coastguard Worker
2126*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: pw::protobuf::StreamDecoder::BytesReader MyProto::StreamDecoder::GetDataReader()
2127*61c4878aSAndroid Build Coastguard Worker
2128*61c4878aSAndroid Build Coastguard WorkerThese can be freely intermixed with the lower-level API methods.
2129*61c4878aSAndroid Build Coastguard Worker
2130*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: StatusWithSize pw::protobuf::StreamDecoder::ReadBytes(ByteSpan)
2131*61c4878aSAndroid Build Coastguard Worker.. cpp:function:: pw::protobuf::StreamDecoder::BytesReader pw::protobuf::StreamDecoder::GetBytesReader()
2132*61c4878aSAndroid Build Coastguard Worker
2133*61c4878aSAndroid Build Coastguard WorkerThe ``BytesReader`` supports seeking only if the ``StreamDecoder``'s reader
2134*61c4878aSAndroid Build Coastguard Workersupports seeking.
2135*61c4878aSAndroid Build Coastguard Worker
2136*61c4878aSAndroid Build Coastguard WorkerError Handling
2137*61c4878aSAndroid Build Coastguard Worker==============
2138*61c4878aSAndroid Build Coastguard WorkerWhile individual read calls on a proto decoder return ``pw::Result``,
2139*61c4878aSAndroid Build Coastguard Worker``pw::StatusWithSize``, or ``pw::Status`` objects, the decoder tracks all status
2140*61c4878aSAndroid Build Coastguard Workerreturns and "latches" onto the first error encountered. This status can be
2141*61c4878aSAndroid Build Coastguard Workeraccessed via ``StreamDecoder::status()``.
2142*61c4878aSAndroid Build Coastguard Worker
2143*61c4878aSAndroid Build Coastguard WorkerLength Limited Decoding
2144*61c4878aSAndroid Build Coastguard Worker=======================
2145*61c4878aSAndroid Build Coastguard WorkerWhere the length of the protobuf message is known in advance, the decoder can
2146*61c4878aSAndroid Build Coastguard Workerbe prevented from reading from the stream beyond the known bounds by specifying
2147*61c4878aSAndroid Build Coastguard Workerthe known length to the decoder:
2148*61c4878aSAndroid Build Coastguard Worker
2149*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
2150*61c4878aSAndroid Build Coastguard Worker
2151*61c4878aSAndroid Build Coastguard Worker   pw::protobuf::StreamDecoder decoder(reader, message_length);
2152*61c4878aSAndroid Build Coastguard Worker
2153*61c4878aSAndroid Build Coastguard WorkerWhen a decoder constructed in this way goes out of scope, it will consume any
2154*61c4878aSAndroid Build Coastguard Workerremaining bytes in ``message_length`` allowing the next ``Read()`` on the stream
2155*61c4878aSAndroid Build Coastguard Workerto be data after the protobuf, even when it was not fully parsed.
2156*61c4878aSAndroid Build Coastguard Worker
2157*61c4878aSAndroid Build Coastguard Worker-----------------
2158*61c4878aSAndroid Build Coastguard WorkerIn-memory Decoder
2159*61c4878aSAndroid Build Coastguard Worker-----------------
2160*61c4878aSAndroid Build Coastguard WorkerThe separate ``Decoder`` class operates on an protobuf message located in a
2161*61c4878aSAndroid Build Coastguard Workerbuffer in memory. It is more efficient than the ``StreamDecoder`` in cases
2162*61c4878aSAndroid Build Coastguard Workerwhere the complete protobuf data can be stored in memory. The tradeoff of this
2163*61c4878aSAndroid Build Coastguard Workerefficiency is that no code generation is provided, so all decoding must be
2164*61c4878aSAndroid Build Coastguard Workerperformed by hand.
2165*61c4878aSAndroid Build Coastguard Worker
2166*61c4878aSAndroid Build Coastguard WorkerAs ``StreamDecoder``, it provides an iterator-style API for processing a
2167*61c4878aSAndroid Build Coastguard Workermessage. Calling ``Next()`` advances the decoder to the next proto field, which
2168*61c4878aSAndroid Build Coastguard Workercan then be read by calling the appropriate ``Read*`` function for the field
2169*61c4878aSAndroid Build Coastguard Workernumber.
2170*61c4878aSAndroid Build Coastguard Worker
2171*61c4878aSAndroid Build Coastguard WorkerWhen reading ``bytes`` and ``string`` fields, the decoder returns a view of that
2172*61c4878aSAndroid Build Coastguard Workerfield within the buffer; no data is copied out.
2173*61c4878aSAndroid Build Coastguard Worker
2174*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
2175*61c4878aSAndroid Build Coastguard Worker
2176*61c4878aSAndroid Build Coastguard Worker   #include "pw_protobuf/decoder.h"
2177*61c4878aSAndroid Build Coastguard Worker   #include "pw_status/try.h"
2178*61c4878aSAndroid Build Coastguard Worker
2179*61c4878aSAndroid Build Coastguard Worker   pw::Status DecodeProtoFromBuffer(pw::span<const std::byte> buffer) {
2180*61c4878aSAndroid Build Coastguard Worker     pw::protobuf::Decoder decoder(buffer);
2181*61c4878aSAndroid Build Coastguard Worker     pw::Status status;
2182*61c4878aSAndroid Build Coastguard Worker
2183*61c4878aSAndroid Build Coastguard Worker     uint32_t uint32_field;
2184*61c4878aSAndroid Build Coastguard Worker     std::string_view string_field;
2185*61c4878aSAndroid Build Coastguard Worker
2186*61c4878aSAndroid Build Coastguard Worker     // Iterate over the fields in the message. A return value of OK indicates
2187*61c4878aSAndroid Build Coastguard Worker     // that a valid field has been found and can be read. When the decoder
2188*61c4878aSAndroid Build Coastguard Worker     // reaches the end of the message, Next() will return OUT_OF_RANGE.
2189*61c4878aSAndroid Build Coastguard Worker     // Other return values indicate an error trying to decode the message.
2190*61c4878aSAndroid Build Coastguard Worker     while ((status = decoder.Next()).ok()) {
2191*61c4878aSAndroid Build Coastguard Worker       switch (decoder.FieldNumber()) {
2192*61c4878aSAndroid Build Coastguard Worker         case 1:
2193*61c4878aSAndroid Build Coastguard Worker           PW_TRY(decoder.ReadUint32(&uint32_field));
2194*61c4878aSAndroid Build Coastguard Worker           break;
2195*61c4878aSAndroid Build Coastguard Worker         case 2:
2196*61c4878aSAndroid Build Coastguard Worker           // The passed-in string_view will point to the contents of the string
2197*61c4878aSAndroid Build Coastguard Worker           // field within the buffer.
2198*61c4878aSAndroid Build Coastguard Worker           PW_TRY(decoder.ReadString(&string_field));
2199*61c4878aSAndroid Build Coastguard Worker           break;
2200*61c4878aSAndroid Build Coastguard Worker       }
2201*61c4878aSAndroid Build Coastguard Worker     }
2202*61c4878aSAndroid Build Coastguard Worker
2203*61c4878aSAndroid Build Coastguard Worker     // Do something with the fields...
2204*61c4878aSAndroid Build Coastguard Worker
2205*61c4878aSAndroid Build Coastguard Worker     return status.IsOutOfRange() ? OkStatus() : status;
2206*61c4878aSAndroid Build Coastguard Worker   }
2207*61c4878aSAndroid Build Coastguard Worker
2208*61c4878aSAndroid Build Coastguard Worker---------------
2209*61c4878aSAndroid Build Coastguard WorkerMessage Decoder
2210*61c4878aSAndroid Build Coastguard Worker---------------
2211*61c4878aSAndroid Build Coastguard Worker
2212*61c4878aSAndroid Build Coastguard Worker.. note::
2213*61c4878aSAndroid Build Coastguard Worker
2214*61c4878aSAndroid Build Coastguard Worker   ``pw::protobuf::Message`` is unrelated to the codegen ``struct Message``
2215*61c4878aSAndroid Build Coastguard Worker   used with ``StreamDecoder``.
2216*61c4878aSAndroid Build Coastguard Worker
2217*61c4878aSAndroid Build Coastguard WorkerThe module implements a message parsing helper class ``Message``, in
2218*61c4878aSAndroid Build Coastguard Worker``pw_protobuf/message.h``, to faciliate proto message parsing and field access.
2219*61c4878aSAndroid Build Coastguard WorkerThe class provides interfaces for searching fields in a proto message and
2220*61c4878aSAndroid Build Coastguard Workercreating helper classes for it according to its interpreted field type, i.e.
2221*61c4878aSAndroid Build Coastguard Workeruint32, bytes, string, map<>, repeated etc. The class works on top of
2222*61c4878aSAndroid Build Coastguard Worker``StreamDecoder`` and thus requires a ``pw::stream::SeekableReader`` for proto
2223*61c4878aSAndroid Build Coastguard Workermessage access. The following gives examples for using the class to process
2224*61c4878aSAndroid Build Coastguard Workerdifferent fields in a proto message:
2225*61c4878aSAndroid Build Coastguard Worker
2226*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
2227*61c4878aSAndroid Build Coastguard Worker
2228*61c4878aSAndroid Build Coastguard Worker   // Consider the proto messages defined as follows:
2229*61c4878aSAndroid Build Coastguard Worker   //
2230*61c4878aSAndroid Build Coastguard Worker   // message Nested {
2231*61c4878aSAndroid Build Coastguard Worker   //   string nested_str = 1;
2232*61c4878aSAndroid Build Coastguard Worker   //   bytes nested_bytes = 2;
2233*61c4878aSAndroid Build Coastguard Worker   // }
2234*61c4878aSAndroid Build Coastguard Worker   //
2235*61c4878aSAndroid Build Coastguard Worker   // message {
2236*61c4878aSAndroid Build Coastguard Worker   //   uint32 integer = 1;
2237*61c4878aSAndroid Build Coastguard Worker   //   string str = 2;
2238*61c4878aSAndroid Build Coastguard Worker   //   bytes bytes = 3;
2239*61c4878aSAndroid Build Coastguard Worker   //   Nested nested = 4;
2240*61c4878aSAndroid Build Coastguard Worker   //   repeated string rep_str = 5;
2241*61c4878aSAndroid Build Coastguard Worker   //   repeated Nested rep_nested  = 6;
2242*61c4878aSAndroid Build Coastguard Worker   //   map<string, bytes> str_to_bytes = 7;
2243*61c4878aSAndroid Build Coastguard Worker   //   map<string, Nested> str_to_nested = 8;
2244*61c4878aSAndroid Build Coastguard Worker   // }
2245*61c4878aSAndroid Build Coastguard Worker
2246*61c4878aSAndroid Build Coastguard Worker   // Given a seekable `reader` that reads the top-level proto message, and
2247*61c4878aSAndroid Build Coastguard Worker   // a <proto_size> that gives the size of the proto message:
2248*61c4878aSAndroid Build Coastguard Worker   Message message(reader, proto_size);
2249*61c4878aSAndroid Build Coastguard Worker
2250*61c4878aSAndroid Build Coastguard Worker   // Parse a proto integer field
2251*61c4878aSAndroid Build Coastguard Worker   Uint32 integer = messasge_parser.AsUint32(1);
2252*61c4878aSAndroid Build Coastguard Worker   if (!integer.ok()) {
2253*61c4878aSAndroid Build Coastguard Worker     // handle parsing error. i.e. return integer.status().
2254*61c4878aSAndroid Build Coastguard Worker   }
2255*61c4878aSAndroid Build Coastguard Worker   uint32_t integer_value = integer.value(); // obtained the value
2256*61c4878aSAndroid Build Coastguard Worker
2257*61c4878aSAndroid Build Coastguard Worker   // Parse a string field
2258*61c4878aSAndroid Build Coastguard Worker   String str = message.AsString(2);
2259*61c4878aSAndroid Build Coastguard Worker   if (!str.ok()) {
2260*61c4878aSAndroid Build Coastguard Worker     // handle parsing error. i.e. return str.status();
2261*61c4878aSAndroid Build Coastguard Worker   }
2262*61c4878aSAndroid Build Coastguard Worker
2263*61c4878aSAndroid Build Coastguard Worker   // check string equal
2264*61c4878aSAndroid Build Coastguard Worker   Result<bool> str_check = str.Equal("foo");
2265*61c4878aSAndroid Build Coastguard Worker
2266*61c4878aSAndroid Build Coastguard Worker   // Parse a bytes field
2267*61c4878aSAndroid Build Coastguard Worker   Bytes bytes = message.AsBytes(3);
2268*61c4878aSAndroid Build Coastguard Worker   if (!bytes.ok()) {
2269*61c4878aSAndroid Build Coastguard Worker     // handle parsing error. i.e. return bytes.status();
2270*61c4878aSAndroid Build Coastguard Worker   }
2271*61c4878aSAndroid Build Coastguard Worker
2272*61c4878aSAndroid Build Coastguard Worker   // Get a reader to the bytes.
2273*61c4878aSAndroid Build Coastguard Worker   stream::IntervalReader bytes_reader = bytes.GetBytesReader();
2274*61c4878aSAndroid Build Coastguard Worker
2275*61c4878aSAndroid Build Coastguard Worker   // Parse nested message `Nested nested = 4;`
2276*61c4878aSAndroid Build Coastguard Worker   Message nested = message.AsMessage(4).
2277*61c4878aSAndroid Build Coastguard Worker   // Get the fields in the nested message.
2278*61c4878aSAndroid Build Coastguard Worker   String nested_str = nested.AsString(1);
2279*61c4878aSAndroid Build Coastguard Worker   Bytes nested_bytes = nested.AsBytes(2);
2280*61c4878aSAndroid Build Coastguard Worker
2281*61c4878aSAndroid Build Coastguard Worker   // Parse repeated field `repeated string rep_str = 5;`
2282*61c4878aSAndroid Build Coastguard Worker   RepeatedStrings rep_str = message.AsRepeatedString(5);
2283*61c4878aSAndroid Build Coastguard Worker   // Iterate through the entries. If proto is malformed when
2284*61c4878aSAndroid Build Coastguard Worker   // iterating, the next element (`str` in this case) will be invalid
2285*61c4878aSAndroid Build Coastguard Worker   // and loop will end in the iteration after.
2286*61c4878aSAndroid Build Coastguard Worker   for (String element : rep_str) {
2287*61c4878aSAndroid Build Coastguard Worker     // Check status
2288*61c4878aSAndroid Build Coastguard Worker     if (!str.ok()) {
2289*61c4878aSAndroid Build Coastguard Worker       // In the case of error, loop will end in the next iteration if
2290*61c4878aSAndroid Build Coastguard Worker       // continues. This is the chance for code to catch the error.
2291*61c4878aSAndroid Build Coastguard Worker     }
2292*61c4878aSAndroid Build Coastguard Worker     // Process str
2293*61c4878aSAndroid Build Coastguard Worker   }
2294*61c4878aSAndroid Build Coastguard Worker
2295*61c4878aSAndroid Build Coastguard Worker   // Parse repeated field `repeated Nested rep_nested = 6;`
2296*61c4878aSAndroid Build Coastguard Worker   RepeatedStrings rep_str = message.AsRepeatedString(6);
2297*61c4878aSAndroid Build Coastguard Worker   // Iterate through the entries. For iteration
2298*61c4878aSAndroid Build Coastguard Worker   for (Message element : rep_rep_nestedstr) {
2299*61c4878aSAndroid Build Coastguard Worker     // Check status
2300*61c4878aSAndroid Build Coastguard Worker     if (!element.ok()) {
2301*61c4878aSAndroid Build Coastguard Worker       // In the case of error, loop will end in the next iteration if
2302*61c4878aSAndroid Build Coastguard Worker       // continues. This is the chance for code to catch the error.
2303*61c4878aSAndroid Build Coastguard Worker     }
2304*61c4878aSAndroid Build Coastguard Worker     // Process element
2305*61c4878aSAndroid Build Coastguard Worker   }
2306*61c4878aSAndroid Build Coastguard Worker
2307*61c4878aSAndroid Build Coastguard Worker   // Parse map field `map<string, bytes> str_to_bytes = 7;`
2308*61c4878aSAndroid Build Coastguard Worker   StringToBytesMap str_to_bytes = message.AsStringToBytesMap(7);
2309*61c4878aSAndroid Build Coastguard Worker   // Access the entry by a given key value
2310*61c4878aSAndroid Build Coastguard Worker   Bytes bytes_for_key = str_to_bytes["key"];
2311*61c4878aSAndroid Build Coastguard Worker   // Or iterate through map entries
2312*61c4878aSAndroid Build Coastguard Worker   for (StringToBytesMapEntry entry : str_to_bytes) {
2313*61c4878aSAndroid Build Coastguard Worker     // Check status
2314*61c4878aSAndroid Build Coastguard Worker     if (!entry.ok()) {
2315*61c4878aSAndroid Build Coastguard Worker       // In the case of error, loop will end in the next iteration if
2316*61c4878aSAndroid Build Coastguard Worker       // continues. This is the chance for code to catch the error.
2317*61c4878aSAndroid Build Coastguard Worker     }
2318*61c4878aSAndroid Build Coastguard Worker     String key = entry.Key();
2319*61c4878aSAndroid Build Coastguard Worker     Bytes value = entry.Value();
2320*61c4878aSAndroid Build Coastguard Worker     // process entry
2321*61c4878aSAndroid Build Coastguard Worker   }
2322*61c4878aSAndroid Build Coastguard Worker
2323*61c4878aSAndroid Build Coastguard Worker   // Parse map field `map<string, Nested> str_to_nested = 8;`
2324*61c4878aSAndroid Build Coastguard Worker   StringToMessageMap str_to_nested = message.AsStringToBytesMap(8);
2325*61c4878aSAndroid Build Coastguard Worker   // Access the entry by a given key value
2326*61c4878aSAndroid Build Coastguard Worker   Message nested_for_key = str_to_nested["key"];
2327*61c4878aSAndroid Build Coastguard Worker   // Or iterate through map entries
2328*61c4878aSAndroid Build Coastguard Worker   for (StringToMessageMapEntry entry : str_to_nested) {
2329*61c4878aSAndroid Build Coastguard Worker     // Check status
2330*61c4878aSAndroid Build Coastguard Worker     if (!entry.ok()) {
2331*61c4878aSAndroid Build Coastguard Worker       // In the case of error, loop will end in the next iteration if
2332*61c4878aSAndroid Build Coastguard Worker       // continues. This is the chance for code to catch the error.
2333*61c4878aSAndroid Build Coastguard Worker       // However it is still recommended that the user breaks here.
2334*61c4878aSAndroid Build Coastguard Worker       break;
2335*61c4878aSAndroid Build Coastguard Worker     }
2336*61c4878aSAndroid Build Coastguard Worker     String key = entry.Key();
2337*61c4878aSAndroid Build Coastguard Worker     Message value = entry.Value();
2338*61c4878aSAndroid Build Coastguard Worker     // process entry
2339*61c4878aSAndroid Build Coastguard Worker   }
2340*61c4878aSAndroid Build Coastguard Worker
2341*61c4878aSAndroid Build Coastguard WorkerThe methods in ``Message`` for parsing a single field, i.e. everty `AsXXX()`
2342*61c4878aSAndroid Build Coastguard Workermethod except AsRepeatedXXX() and AsStringMapXXX(), internally performs a
2343*61c4878aSAndroid Build Coastguard Workerlinear scan of the entire proto message to find the field with the given
2344*61c4878aSAndroid Build Coastguard Workerfield number. This can be expensive if performed multiple times, especially
2345*61c4878aSAndroid Build Coastguard Workeron slow reader. The same applies to the ``operator[]`` of StringToXXXXMap
2346*61c4878aSAndroid Build Coastguard Workerhelper class. Therefore, for performance consideration, whenever possible, it
2347*61c4878aSAndroid Build Coastguard Workeris recommended to use the following for-range style to iterate and process
2348*61c4878aSAndroid Build Coastguard Workersingle fields directly.
2349*61c4878aSAndroid Build Coastguard Worker
2350*61c4878aSAndroid Build Coastguard Worker
2351*61c4878aSAndroid Build Coastguard Worker.. code-block:: c++
2352*61c4878aSAndroid Build Coastguard Worker
2353*61c4878aSAndroid Build Coastguard Worker   for (Message::Field field : message) {
2354*61c4878aSAndroid Build Coastguard Worker     // Check status
2355*61c4878aSAndroid Build Coastguard Worker     if (!field.ok()) {
2356*61c4878aSAndroid Build Coastguard Worker       // In the case of error, loop will end in the next iteration if
2357*61c4878aSAndroid Build Coastguard Worker       // continues. This is the chance for code to catch the error.
2358*61c4878aSAndroid Build Coastguard Worker     }
2359*61c4878aSAndroid Build Coastguard Worker     if (field.field_number() == 1) {
2360*61c4878aSAndroid Build Coastguard Worker       Uint32 integer = field.As<Uint32>();
2361*61c4878aSAndroid Build Coastguard Worker       ...
2362*61c4878aSAndroid Build Coastguard Worker     } else if (field.field_number() == 2) {
2363*61c4878aSAndroid Build Coastguard Worker       String str = field.As<String>();
2364*61c4878aSAndroid Build Coastguard Worker       ...
2365*61c4878aSAndroid Build Coastguard Worker     } else if (field.field_number() == 3) {
2366*61c4878aSAndroid Build Coastguard Worker       Bytes bytes = field.As<Bytes>();
2367*61c4878aSAndroid Build Coastguard Worker       ...
2368*61c4878aSAndroid Build Coastguard Worker     } else if (field.field_number() == 4) {
2369*61c4878aSAndroid Build Coastguard Worker       Message nested = field.As<Message>();
2370*61c4878aSAndroid Build Coastguard Worker       ...
2371*61c4878aSAndroid Build Coastguard Worker     }
2372*61c4878aSAndroid Build Coastguard Worker   }
2373*61c4878aSAndroid Build Coastguard Worker
2374*61c4878aSAndroid Build Coastguard Worker
2375*61c4878aSAndroid Build Coastguard Worker.. Note::
2376*61c4878aSAndroid Build Coastguard Worker  The helper API are currently in-development and may not remain stable.
2377*61c4878aSAndroid Build Coastguard Worker
2378*61c4878aSAndroid Build Coastguard Worker-----------
2379*61c4878aSAndroid Build Coastguard WorkerSize report
2380*61c4878aSAndroid Build Coastguard Worker-----------
2381*61c4878aSAndroid Build Coastguard Worker
2382*61c4878aSAndroid Build Coastguard WorkerFull size report
2383*61c4878aSAndroid Build Coastguard Worker================
2384*61c4878aSAndroid Build Coastguard Worker
2385*61c4878aSAndroid Build Coastguard WorkerThis report demonstrates the size of using the entire decoder with all of its
2386*61c4878aSAndroid Build Coastguard Workerdecode methods and a decode callback for a proto message containing each of the
2387*61c4878aSAndroid Build Coastguard Workerprotobuf field types.
2388*61c4878aSAndroid Build Coastguard Worker
2389*61c4878aSAndroid Build Coastguard Worker.. include:: size_report/decoder_partial
2390*61c4878aSAndroid Build Coastguard Worker
2391*61c4878aSAndroid Build Coastguard Worker
2392*61c4878aSAndroid Build Coastguard WorkerIncremental size report
2393*61c4878aSAndroid Build Coastguard Worker=======================
2394*61c4878aSAndroid Build Coastguard Worker
2395*61c4878aSAndroid Build Coastguard WorkerThis report is generated using the full report as a base and adding some int32
2396*61c4878aSAndroid Build Coastguard Workerfields to the decode callback to demonstrate the incremental cost of decoding
2397*61c4878aSAndroid Build Coastguard Workerfields in a message.
2398*61c4878aSAndroid Build Coastguard Worker
2399*61c4878aSAndroid Build Coastguard Worker.. include:: size_report/decoder_incremental
2400*61c4878aSAndroid Build Coastguard Worker
2401*61c4878aSAndroid Build Coastguard Worker---------------------------
2402*61c4878aSAndroid Build Coastguard WorkerSerialized size calculation
2403*61c4878aSAndroid Build Coastguard Worker---------------------------
2404*61c4878aSAndroid Build Coastguard Worker``pw_protobuf/serialized_size.h`` provides a set of functions for calculating
2405*61c4878aSAndroid Build Coastguard Workerhow much memory serialized protocol buffer fields require. The
2406*61c4878aSAndroid Build Coastguard Worker``kMaxSizeBytes*`` variables provide the maximum encoded sizes of each field
2407*61c4878aSAndroid Build Coastguard Workertype. The ``SizeOfField*()`` functions calculate the encoded size of a field of
2408*61c4878aSAndroid Build Coastguard Workerthe specified type, given a particular key and, for variable length fields
2409*61c4878aSAndroid Build Coastguard Worker(varint or delimited), a value. The ``SizeOf*Field`` functions calculate the
2410*61c4878aSAndroid Build Coastguard Workerencoded size of fields with a particular wire format (delimited, varint).
2411*61c4878aSAndroid Build Coastguard Worker
2412*61c4878aSAndroid Build Coastguard WorkerIn the rare event that you need to know the serialized size of a field's tag
2413*61c4878aSAndroid Build Coastguard Worker(field number and wire type), you can use ``TagSizeBytes()`` to calculate the
2414*61c4878aSAndroid Build Coastguard Workertag size for a given field number.
2415*61c4878aSAndroid Build Coastguard Worker
2416*61c4878aSAndroid Build Coastguard Worker--------------------------
2417*61c4878aSAndroid Build Coastguard WorkerAvailable protobuf modules
2418*61c4878aSAndroid Build Coastguard Worker--------------------------
2419*61c4878aSAndroid Build Coastguard WorkerThere are a handful of messages ready to be used in Pigweed projects. These are
2420*61c4878aSAndroid Build Coastguard Workerlocated in ``pw_protobuf/pw_protobuf_protos``.
2421*61c4878aSAndroid Build Coastguard Worker
2422*61c4878aSAndroid Build Coastguard Workercommon.proto
2423*61c4878aSAndroid Build Coastguard Worker============
2424*61c4878aSAndroid Build Coastguard WorkerContains Empty message proto used in many RPC calls.
2425*61c4878aSAndroid Build Coastguard Worker
2426*61c4878aSAndroid Build Coastguard Worker
2427*61c4878aSAndroid Build Coastguard Workerstatus.proto
2428*61c4878aSAndroid Build Coastguard Worker============
2429*61c4878aSAndroid Build Coastguard WorkerContains the enum for pw::Status.
2430*61c4878aSAndroid Build Coastguard Worker
2431*61c4878aSAndroid Build Coastguard Worker.. note::
2432*61c4878aSAndroid Build Coastguard Worker   ``pw::protobuf::StatusCode`` values should not be used outside of a .proto
2433*61c4878aSAndroid Build Coastguard Worker   file. Instead, the StatusCodes should be converted to the Status type in the
2434*61c4878aSAndroid Build Coastguard Worker   language. In C++, this would be:
2435*61c4878aSAndroid Build Coastguard Worker
2436*61c4878aSAndroid Build Coastguard Worker   .. code-block:: c++
2437*61c4878aSAndroid Build Coastguard Worker
2438*61c4878aSAndroid Build Coastguard Worker      // Reading from a proto
2439*61c4878aSAndroid Build Coastguard Worker      pw::Status status = static_cast<pw::Status::Code>(proto.status_field));
2440*61c4878aSAndroid Build Coastguard Worker      // Writing to a proto
2441*61c4878aSAndroid Build Coastguard Worker      proto.status_field = static_cast<pw::protobuf::StatusCode>(status.code()));
2442*61c4878aSAndroid Build Coastguard Worker
2443*61c4878aSAndroid Build Coastguard Worker----------------------------------------
2444*61c4878aSAndroid Build Coastguard WorkerComparison with other protobuf libraries
2445*61c4878aSAndroid Build Coastguard Worker----------------------------------------
2446*61c4878aSAndroid Build Coastguard Worker
2447*61c4878aSAndroid Build Coastguard Workerprotobuf-lite
2448*61c4878aSAndroid Build Coastguard Worker=============
2449*61c4878aSAndroid Build Coastguard Workerprotobuf-lite is the official reduced-size C++ implementation of protobuf. It
2450*61c4878aSAndroid Build Coastguard Workeruses a restricted subset of the protobuf library's features to minimize code
2451*61c4878aSAndroid Build Coastguard Workersize. However, is is still around 150K in size and requires dynamic memory
2452*61c4878aSAndroid Build Coastguard Workerallocation, making it unsuitable for many embedded systems.
2453*61c4878aSAndroid Build Coastguard Worker
2454*61c4878aSAndroid Build Coastguard Workernanopb
2455*61c4878aSAndroid Build Coastguard Worker======
2456*61c4878aSAndroid Build Coastguard Worker`Nanopb`_ is a commonly used embedded protobuf library with very small code size
2457*61c4878aSAndroid Build Coastguard Workerand full code generation. It provides both encoding/decoding functionality and
2458*61c4878aSAndroid Build Coastguard Workerin-memory C structs representing protobuf messages.
2459*61c4878aSAndroid Build Coastguard Worker
2460*61c4878aSAndroid Build Coastguard Workernanopb works well for many embedded products; however, using its generated code
2461*61c4878aSAndroid Build Coastguard Workercan run into RAM usage issues when processing nontrivial protobuf messages due
2462*61c4878aSAndroid Build Coastguard Workerto the necessity of defining a struct capable of storing all configurations of
2463*61c4878aSAndroid Build Coastguard Workerthe message, which can grow incredibly large. In one project, Pigweed developers
2464*61c4878aSAndroid Build Coastguard Workerencountered an 11K struct statically allocated for a single message---over twice
2465*61c4878aSAndroid Build Coastguard Workerthe size of the final encoded output! (This was what prompted the development of
2466*61c4878aSAndroid Build Coastguard Worker``pw_protobuf``.)
2467*61c4878aSAndroid Build Coastguard Worker
2468*61c4878aSAndroid Build Coastguard WorkerTo avoid this issue, it is possible to use nanopb's low-level encode/decode
2469*61c4878aSAndroid Build Coastguard Workerfunctions to process individual message fields directly, but this loses all of
2470*61c4878aSAndroid Build Coastguard Workerthe useful semantics of code generation. ``pw_protobuf`` is designed to optimize
2471*61c4878aSAndroid Build Coastguard Workerfor this use case; it allows for efficient operations on the wire format with an
2472*61c4878aSAndroid Build Coastguard Workerintuitive user interface.
2473*61c4878aSAndroid Build Coastguard Worker
2474*61c4878aSAndroid Build Coastguard WorkerDepending on the requirements of a project, either of these libraries could be
2475*61c4878aSAndroid Build Coastguard Workersuitable.
2476*61c4878aSAndroid Build Coastguard Worker
2477*61c4878aSAndroid Build Coastguard Worker.. _Nanopb: https://jpa.kapsi.fi/nanopb/
2478