NOTE: the design described here is being implemented currently, but is not yet complete. The repo is in heavy transition right now.
μpb has the following design goals:
μpb accomplishes these goals by keeping a very small core that does not contain descriptors. We need some way of knowing what fields are in each message and where they live, but instead of descriptors, we keep a small/lightweight summary of the .proto file. We call this a upb_msglayout
. It contains the bare minimum of what we need to know to parse and serialize protobuf binary format into our internal representation for messages, upb_msg
.
The core then contains functions to parse/serialize a message, given a upb_msg*
and a const upb_msglayout*
.
This approach is similar to nanopb which also compiles message definitions to a compact, internal representation without names. However nanopb does not aim to be a fully-featured library, and has no support for text format, JSON, or descriptors. μpb is unique in that it has a small core similar to nanopb (though not quite as small), but also offers a full-featured protobuf library for applications that want reflection, text format, JSON format, etc.
Without descriptors, the core doesn't have access to field names, so it cannot parse/serialize to protobuf text format or JSON. Instead this functionality lives in separate modules that depend on the module implementing descriptors. With the descriptor module we can parse/serialize binary descriptors and validate that they follow all the rules of protobuf schemas.
To provide binary compatibility, we version the structs that generated messages use to create a upb_msglayout*
. The current initializers are upb_msglayout_msginit_v1
, upb_msglayout_fieldinit_v1
, etc. Then upb_msglayout*
uses these as its internal representation. If upb changes its internal representation for a upb_msglayout*
, it will also include code to convert the old representation to the new representation. This will use some more memory/CPU at runtime to convert between the two, but apps that statically link μpb will never need to worry about this.
The current state of the repo is quite different than what is described above. Here are the major items that need to be implemented.
upb_msglayout*
.upb_msg
, but we need to simplify all of that a LOT. Likely we will want to make handlers only per-message instead of per-field, except for variable-length fields.