class TypedProtoDecoderBase

Defined at line 332 of file ../../third_party/perfetto/include/perfetto/protozero/proto_decoder.h

This decoder loads all fields upfront, without recursing in nested messages.

It is used as a base class for typed decoders generated by the pbzero plugin.

The split between TypedProtoDecoderBase and TypedProtoDecoder

<

> is to have

unique definition of functions like ParseAllFields() and ExpandHeapStorage().

The storage (either on-stack or on-heap) for this class is organized as

follows:

|-------------------------- fields_ ----------------------|

[ field 0 (invalid) ] [ fields 1 .. N ] [ repeated fields ]

^ ^

num_fields_ size_

Note that if a message has high field numbers, upon creation |size_| can be

<

|num_fields_| (until a heap expansion is hit while inserting).

Protected Members

unique_ptr heap_storage_
Field * fields_
uint32_t num_fields_
uint32_t size_
uint32_t capacity_

Public Methods

const Field & Get (uint32_t id)

If the field |id| is known at compile time, prefer the templated

specialization at

<kFieldNumber

>().

Defined at line 336 of file ../../third_party/perfetto/include/perfetto/protozero/proto_decoder.h

Field GetExtensionSlowly (uint32_t id)

Like Get(), but also resolves "extension" fields whose id exceeds the

highest field id known in-tree at compile time (i.e. id >= num_fields_,

which is MAX_FIELD_ID + 1). Such fields are NOT stored by ParseAllFields()

-- e.g. fields carved out of TracePacket's `extensions 1000 to 1999`

range. For in-tree ids this delegates to Get(); for extension ids it falls

back to a linear re-scan of the buffer.

NOTE: for *repeated* fields the slow path returns the FIRST occurrence

(FindField semantics), whereas Get() returns the last. All current

extension fields are singular submessages, so this is not observable today.

TODO: make extension lookups fast without re-scanning the buffer. The

blocker is that fields_ is indexed directly by field id (on_stack_storage_,

or heap_storage_ after ExpandHeapStorage()), so it must be sized to the

largest field id. That is fine for the densely-numbered in-tree fields, but

extension ids are sparse and can be arbitrarily high (the OOT range starts

at 1000), so indexing by id would waste / unbound memory. Proposed design:

- Replace the flat array with a two-level sparse map. Level 1 is a set of

id ranges built dynamically while decoding (these need not match the

static extensions.json allocations), e.g. tracked with a bitset. Level

2 maps an id within a matched range to a compact slot index.

- Back the slots with an object pool so repeated decodes reuse storage

and allocate ~zero: only a few decoders are live at any time, so the

pool stays small.

This costs memory proportional to the extension fields actually present

rather than to the max field id, and keeps the decode hot path

allocation-free.

Defined at line 374 of file ../../third_party/perfetto/include/perfetto/protozero/proto_decoder.h

template <typename T>
RepeatedFieldIterator<T> GetRepeated (uint32_t field_id)

Returns an object that allows to iterate over all instances of a repeated

field given its id. Example usage:

for (auto it = decoder.GetRepeated

<int32

_t>(N); it; ++it) { ... }

Defined at line 388 of file ../../third_party/perfetto/include/perfetto/protozero/proto_decoder.h

template <proto_utils::ProtoWireType wire_type, typename cpp_type>
PackedRepeatedFieldIterator<wire_type, cpp_type> GetPackedRepeated (uint32_t field_id, bool * parse_error_location)

Returns an objects that allows to iterate over all entries of a packed

repeated field given its id and type. The |wire_type| is necessary for

decoding the packed field, the |cpp_type| is for convenience

&

stronger

typing.

The caller must also supply a pointer to a bool that is set to true if the

packed buffer is found to be malformed while iterating (so you need to

exhaust the iterator if you want to check the full extent of the buffer).

Note that unlike standard protobuf parsers, protozero does not allow

treating of packed repeated fields as non-packed and vice-versa (therefore

not making the packed option forwards and backwards compatible). So

the caller needs to use the right accessor for correct results.

Defined at line 426 of file ../../third_party/perfetto/include/perfetto/protozero/proto_decoder.h

template <proto_utils::ProtoWireType wire_type, typename cpp_type>
UnifiedRepeatedFieldIterator<wire_type, cpp_type> GetUnifiedRepeated (uint32_t field_id, bool * parse_error_location)

Returns a unified iterator that automatically dispatches between packed and

non-packed repeated field iteration based on the wire format. This allows

parsers to handle both formats without knowing ahead of time which one is

used.

Example usage:

bool parse_error = false;

for (auto it = decoder.GetUnifiedRepeated

<wire

_type, int32_t>(N,

&parse

_error);

it; ++it) { ... }

Defined at line 450 of file ../../third_party/perfetto/include/perfetto/protozero/proto_decoder.h

Protected Methods

void ParseAllFields ()
void ExpandHeapStorage ()

Called when the default on-stack storage is exhausted and new repeated

fields need to be pushed.

void TypedProtoDecoderBase (Field * storage, uint32_t num_fields, uint32_t capacity, const uint8_t * buffer, size_t length)

Defined at line 466 of file ../../third_party/perfetto/include/perfetto/protozero/proto_decoder.h