Alexei Frolov | 9c2ed46 | 2020-01-13 15:35:42 -0800 | [diff] [blame] | 1 | .. default-domain:: cpp |
| 2 | |
| 3 | .. highlight:: sh |
| 4 | |
| 5 | .. _chapter-protobuf: |
| 6 | |
| 7 | ----------- |
| 8 | pw_protobuf |
| 9 | ----------- |
| 10 | The protobuf module provides a lightweight interface for encoding and decoding |
| 11 | the Protocol Buffer wire format. |
| 12 | |
Alexei Frolov | 4a257c1 | 2020-03-02 14:09:42 -0800 | [diff] [blame^] | 13 | Design |
| 14 | ====== |
| 15 | Unlike other protobuf libraries, which typically provide in-memory data |
| 16 | structures to represent protobuf messages, pw_protobuf operates directly on the |
| 17 | wire format and leaves data storage to the user. This has a few benefits. The |
| 18 | primary one is that it allows the library to be incredibly small, with the |
| 19 | encoder and decoder each having a code size of around 1.5K and negligible RAM |
| 20 | usage. Users can choose the tradeoffs most suitable for their product on top of |
| 21 | this core implementation. |
| 22 | |
| 23 | pw_protobuf also provides zero-overhead C++ code generation which wraps its |
| 24 | low-level wire format operations with a user-friendly API for processing |
| 25 | specific protobuf messages. The code generation integrates with Pigweed's GN |
| 26 | build system. |
| 27 | |
| 28 | Usage |
| 29 | ===== |
| 30 | pw_protobuf splits wire format encoding and decoding operations. Links to the |
| 31 | design and APIs of each are listed in below. |
| 32 | |
| 33 | See also :ref:`chapter-pw-protobuf-compiler` for details on pw_protobuf's build |
| 34 | system integration. |
| 35 | |
| 36 | **pw_protobuf functionality** |
| 37 | |
Alexei Frolov | 9c2ed46 | 2020-01-13 15:35:42 -0800 | [diff] [blame] | 38 | .. toctree:: |
| 39 | :maxdepth: 1 |
| 40 | |
Alexei Frolov | 4a257c1 | 2020-03-02 14:09:42 -0800 | [diff] [blame^] | 41 | decoding |
| 42 | |
| 43 | Comparison with other protobuf libraries |
| 44 | ======================================== |
| 45 | |
| 46 | protobuf-lite |
| 47 | ^^^^^^^^^^^^^ |
| 48 | protobuf-lite is the official reduced-size C++ implementation of protobuf. It |
| 49 | uses a restricted subset of the protobuf library's features to minimize code |
| 50 | size. However, is is still around 150K in size and requires dynamic memory |
| 51 | allocation, making it unsuitable for many embedded systems. |
| 52 | |
| 53 | nanopb |
| 54 | ^^^^^^ |
| 55 | `nanopb <https://github.com/nanopb/nanopb>`_ is a commonly used embedded |
| 56 | protobuf library with very small code size and full code generation. It provides |
| 57 | both encoding/decoding functionality and in-memory C structs representing |
| 58 | protobuf messages. |
| 59 | |
| 60 | nanopb works well for many embedded products; however, using its generated code |
| 61 | can run into RAM usage issues when processing nontrivial protobuf messages due |
| 62 | to the necessity of defining a struct capable of storing all configurations of |
| 63 | the message, which can grow incredibly large. In one project, Pigweed developers |
| 64 | encountered an 11K struct statically allocated for a single message---over twice |
| 65 | the size of the final encoded output! (This was what prompted the development of |
| 66 | pw_protobuf.) |
| 67 | |
| 68 | To avoid this issue, it is possible to use nanopb's low-level encode/decode |
| 69 | functions to process individual message fields directly, but this loses all of |
| 70 | the useful semantics of code generation. pw_protobuf is designed to optimize for |
| 71 | this use case; it allows for efficient operations on the wire format with an |
| 72 | intuitive user interface. |
| 73 | |
| 74 | Depending on the requirements of a project, either of these libraries could be |
| 75 | suitable. |