Wyatt Hepler | f9fb90f | 2020-09-30 18:59:33 -0700 | [diff] [blame] | 1 | .. _module-pw_protobuf: |
Alexei Frolov | 9c2ed46 | 2020-01-13 15:35:42 -0800 | [diff] [blame] | 2 | |
| 3 | ----------- |
| 4 | pw_protobuf |
| 5 | ----------- |
| 6 | The protobuf module provides a lightweight interface for encoding and decoding |
| 7 | the Protocol Buffer wire format. |
| 8 | |
Alexei Frolov | 469b39f | 2020-04-30 10:48:43 -0700 | [diff] [blame] | 9 | .. 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 Frolov | 4a257c1 | 2020-03-02 14:09:42 -0800 | [diff] [blame] | 15 | Design |
| 16 | ====== |
| 17 | Unlike other protobuf libraries, which typically provide in-memory data |
Armando Montanez | 0054a9b | 2020-03-13 13:06:24 -0700 | [diff] [blame] | 18 | structures to represent protobuf messages, ``pw_protobuf`` operates directly on |
| 19 | the wire format and leaves data storage to the user. This has a few benefits. |
| 20 | The primary one is that it allows the library to be incredibly small, with the |
Alexei Frolov | 4a257c1 | 2020-03-02 14:09:42 -0800 | [diff] [blame] | 21 | encoder and decoder each having a code size of around 1.5K and negligible RAM |
| 22 | usage. Users can choose the tradeoffs most suitable for their product on top of |
| 23 | this core implementation. |
| 24 | |
Armando Montanez | 0054a9b | 2020-03-13 13:06:24 -0700 | [diff] [blame] | 25 | ``pw_protobuf`` also provides zero-overhead C++ code generation which wraps its |
Alexei Frolov | 4a257c1 | 2020-03-02 14:09:42 -0800 | [diff] [blame] | 26 | low-level wire format operations with a user-friendly API for processing |
| 27 | specific protobuf messages. The code generation integrates with Pigweed's GN |
| 28 | build system. |
| 29 | |
Alexei Frolov | f9ae189 | 2021-04-01 18:24:27 -0700 | [diff] [blame] | 30 | Configuration |
| 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 Frolov | 4a257c1 | 2020-03-02 14:09:42 -0800 | [diff] [blame] | 56 | Usage |
| 57 | ===== |
Armando Montanez | 0054a9b | 2020-03-13 13:06:24 -0700 | [diff] [blame] | 58 | ``pw_protobuf`` splits wire format encoding and decoding operations. Links to |
| 59 | the design and APIs of each are listed in below. |
Alexei Frolov | 4a257c1 | 2020-03-02 14:09:42 -0800 | [diff] [blame] | 60 | |
Wyatt Hepler | f9fb90f | 2020-09-30 18:59:33 -0700 | [diff] [blame] | 61 | See also :ref:`module-pw_protobuf_compiler` for details on ``pw_protobuf``'s |
Armando Montanez | 0054a9b | 2020-03-13 13:06:24 -0700 | [diff] [blame] | 62 | build system integration. |
Alexei Frolov | 4a257c1 | 2020-03-02 14:09:42 -0800 | [diff] [blame] | 63 | |
| 64 | **pw_protobuf functionality** |
| 65 | |
Alexei Frolov | 9c2ed46 | 2020-01-13 15:35:42 -0800 | [diff] [blame] | 66 | .. toctree:: |
| 67 | :maxdepth: 1 |
| 68 | |
Armando Montanez | 0ed221c | 2021-04-02 18:33:01 -0700 | [diff] [blame] | 69 | encoding |
Alexei Frolov | 4a257c1 | 2020-03-02 14:09:42 -0800 | [diff] [blame] | 70 | decoding |
| 71 | |
| 72 | Comparison with other protobuf libraries |
| 73 | ======================================== |
| 74 | |
| 75 | protobuf-lite |
| 76 | ^^^^^^^^^^^^^ |
| 77 | protobuf-lite is the official reduced-size C++ implementation of protobuf. It |
| 78 | uses a restricted subset of the protobuf library's features to minimize code |
| 79 | size. However, is is still around 150K in size and requires dynamic memory |
| 80 | allocation, making it unsuitable for many embedded systems. |
| 81 | |
| 82 | nanopb |
| 83 | ^^^^^^ |
| 84 | `nanopb <https://github.com/nanopb/nanopb>`_ is a commonly used embedded |
| 85 | protobuf library with very small code size and full code generation. It provides |
| 86 | both encoding/decoding functionality and in-memory C structs representing |
| 87 | protobuf messages. |
| 88 | |
| 89 | nanopb works well for many embedded products; however, using its generated code |
| 90 | can run into RAM usage issues when processing nontrivial protobuf messages due |
| 91 | to the necessity of defining a struct capable of storing all configurations of |
| 92 | the message, which can grow incredibly large. In one project, Pigweed developers |
| 93 | encountered an 11K struct statically allocated for a single message---over twice |
| 94 | the size of the final encoded output! (This was what prompted the development of |
Armando Montanez | 0054a9b | 2020-03-13 13:06:24 -0700 | [diff] [blame] | 95 | ``pw_protobuf``.) |
Alexei Frolov | 4a257c1 | 2020-03-02 14:09:42 -0800 | [diff] [blame] | 96 | |
| 97 | To avoid this issue, it is possible to use nanopb's low-level encode/decode |
| 98 | functions to process individual message fields directly, but this loses all of |
Armando Montanez | 0054a9b | 2020-03-13 13:06:24 -0700 | [diff] [blame] | 99 | the useful semantics of code generation. ``pw_protobuf`` is designed to optimize |
| 100 | for this use case; it allows for efficient operations on the wire format with an |
Alexei Frolov | 4a257c1 | 2020-03-02 14:09:42 -0800 | [diff] [blame] | 101 | intuitive user interface. |
| 102 | |
| 103 | Depending on the requirements of a project, either of these libraries could be |
| 104 | suitable. |