The debug dumper

Generated with --dump (implies --arena). Header: <stem>.rp.dump.hpp. Back to the README.

--dump emits a third header that prints a decoded arena tree as human-readable, JSON-like text. It is not a JSON codec and not a wire serializer. It reads the arena decoder’s public accessors (no reflection, no descriptor.proto) and dumps whatever the arena header exposes. For each message in the schema it teaches rapidproto::dump how to print it:

std::string rapidproto::dump(const T& m, const rapidproto::DumpOptions& opts = {});
void        rapidproto::dump(std::ostream& os, const T& m, const rapidproto::DumpOptions& opts = {});
./build/release/rapidprotoc --dump -I. --out-dir=out person.proto
# out/person.rp.dump.hpp + the arena header + out/rapidproto/dump_runtime.hpp
#include "person.rp.hpp"
#include "person.rp.dump.hpp"

namespace ex = rp::arena::example;
const ex::Person* p = ex::Person::decode(rapidproto::ByteView(buf), arena);
std::cout << rapidproto::dump(*p) << '\n';           // or: rapidproto::dump(std::cout, *p, 120);

DumpOptions tunes a dump. Every field has a default, and an integer converts to a width:

rapidproto::DumpOptions opts;
opts.width  = 100;                              // line-width budget (compact vs one-entry-per-line)
opts.indent = 2;                                // start two nesting levels in, to nest under other output
opts.skip   = {"email", "address.zip"};         // omit these fields by qualified path (subtree and all)
std::cout << rapidproto::dump(*p, opts);

What it renders: scalars, string, bytes (as lowercase hex), enums by their prefix-stripped name (UNKNOWN(<n>) for an open-enum value outside the schema’s range), nested sub-messages, repeated fields (arrays), maps (objects), and the active member of a oneof; groups print through the identical nested-message accessor. A bool prints as true/false, including as a map<bool, …> key. float/double print with enough digits to read back to the same value, without padding out to the type’s maximum, and the non-finite ones as the quoted strings "NaN" / "Infinity" / "-Infinity" - JSON has no number syntax for those. Every value is formatted by the dumper itself, so the text does not vary with the locale or format flags of the stream you write to (and the dump leaves both alone). Default-valued implicit (proto3 singular) fields and empty repeated/maps are omitted; explicit-presence fields print when set; a required field always prints. A message that reserves the unknown-fields bit shows "has_unknown_fields": true when set - a bit only, since the arena retains no unknown-field data. The output is width-adaptive: each object or array renders on one line if it fits the budget (width, default 120 columns), otherwise one entry per line - with a wide array filling as many aligned columns as fit. Well-known types (Timestamp, etc.) print as their nested fields, with no special JSON form.