blob: 7459afe7e65f662d8e8724e48c06e9124afc43c5 [file] [log] [blame]
Wyatt Heplerf9fb90f2020-09-30 18:59:33 -07001.. _module-pw_protobuf:
Alexei Frolov9c2ed462020-01-13 15:35:42 -08002
3-----------
4pw_protobuf
5-----------
6The protobuf module provides a lightweight interface for encoding and decoding
7the Protocol Buffer wire format.
8
Alexei Frolov469b39f2020-04-30 10:48:43 -07009.. note::
10
11 The protobuf module is a work in progress. Wire format encoding and decoding
12 is supported, though the APIs are not final. C++ code generation exists for
13 encoding, but not decoding.
14
Alexei Frolov4a257c12020-03-02 14:09:42 -080015Design
16======
17Unlike other protobuf libraries, which typically provide in-memory data
Armando Montanez0054a9b2020-03-13 13:06:24 -070018structures to represent protobuf messages, ``pw_protobuf`` operates directly on
19the wire format and leaves data storage to the user. This has a few benefits.
20The primary one is that it allows the library to be incredibly small, with the
Alexei Frolov4a257c12020-03-02 14:09:42 -080021encoder and decoder each having a code size of around 1.5K and negligible RAM
22usage. Users can choose the tradeoffs most suitable for their product on top of
23this core implementation.
24
Armando Montanez0054a9b2020-03-13 13:06:24 -070025``pw_protobuf`` also provides zero-overhead C++ code generation which wraps its
Alexei Frolov4a257c12020-03-02 14:09:42 -080026low-level wire format operations with a user-friendly API for processing
27specific protobuf messages. The code generation integrates with Pigweed's GN
28build system.
29
Alexei Frolovf9ae1892021-04-01 18:24:27 -070030Configuration
31=============
32``pw_protobuf`` supports the following configuration options.
33
34* ``PW_PROTOBUF_CFG_MAX_VARINT_SIZE``:
35 When encoding nested messages, the number of bytes to reserve for the varint
36 submessage length. Nested messages are limited in size to the maximum value
37 that can be varint-encoded into this reserved space.
38
39 The values that can be set, and their corresponding maximum submessage
40 lengths, are outlined below.
41
42 +-------------------+----------------------------------------+
43 | MAX_VARINT_SIZE | Maximum submessage length |
44 +===================+========================================+
45 | 1 byte | 127 |
46 +-------------------+----------------------------------------+
47 | 2 bytes | 16,383 or < 16KiB |
48 +-------------------+----------------------------------------+
49 | 3 bytes | 2,097,151 or < 2048KiB |
50 +-------------------+----------------------------------------+
51 | 4 bytes (default) | 268,435,455 or < 256MiB |
52 +-------------------+----------------------------------------+
53 | 5 bytes | 4,294,967,295 or < 4GiB (max uint32_t) |
54 +-------------------+----------------------------------------+
55
Alexei Frolov4a257c12020-03-02 14:09:42 -080056Usage
57=====
Armando Montanez0054a9b2020-03-13 13:06:24 -070058``pw_protobuf`` splits wire format encoding and decoding operations. Links to
59the design and APIs of each are listed in below.
Alexei Frolov4a257c12020-03-02 14:09:42 -080060
Wyatt Heplerf9fb90f2020-09-30 18:59:33 -070061See also :ref:`module-pw_protobuf_compiler` for details on ``pw_protobuf``'s
Armando Montanez0054a9b2020-03-13 13:06:24 -070062build system integration.
Alexei Frolov4a257c12020-03-02 14:09:42 -080063
64**pw_protobuf functionality**
65
Alexei Frolov9c2ed462020-01-13 15:35:42 -080066.. toctree::
67 :maxdepth: 1
68
Armando Montanez0ed221c2021-04-02 18:33:01 -070069 encoding
Alexei Frolov4a257c12020-03-02 14:09:42 -080070 decoding
71
72Comparison with other protobuf libraries
73========================================
74
75protobuf-lite
76^^^^^^^^^^^^^
77protobuf-lite is the official reduced-size C++ implementation of protobuf. It
78uses a restricted subset of the protobuf library's features to minimize code
79size. However, is is still around 150K in size and requires dynamic memory
80allocation, making it unsuitable for many embedded systems.
81
82nanopb
83^^^^^^
84`nanopb <https://github.com/nanopb/nanopb>`_ is a commonly used embedded
85protobuf library with very small code size and full code generation. It provides
86both encoding/decoding functionality and in-memory C structs representing
87protobuf messages.
88
89nanopb works well for many embedded products; however, using its generated code
90can run into RAM usage issues when processing nontrivial protobuf messages due
91to the necessity of defining a struct capable of storing all configurations of
92the message, which can grow incredibly large. In one project, Pigweed developers
93encountered an 11K struct statically allocated for a single message---over twice
94the size of the final encoded output! (This was what prompted the development of
Armando Montanez0054a9b2020-03-13 13:06:24 -070095``pw_protobuf``.)
Alexei Frolov4a257c12020-03-02 14:09:42 -080096
97To avoid this issue, it is possible to use nanopb's low-level encode/decode
98functions to process individual message fields directly, but this loses all of
Armando Montanez0054a9b2020-03-13 13:06:24 -070099the useful semantics of code generation. ``pw_protobuf`` is designed to optimize
100for this use case; it allows for efficient operations on the wire format with an
Alexei Frolov4a257c12020-03-02 14:09:42 -0800101intuitive user interface.
102
103Depending on the requirements of a project, either of these libraries could be
104suitable.