Documentation
¶
Overview ¶
Package protobufdecode parses raw Protocol Buffers wire-format bytes without needing the .proto schema — the equivalent of `protoc --decode_raw`. gRPC, Google APIs, mobile apps, modern microservices, and Faultier's own command framing all carry protobuf bytes; operators routinely have hex blobs of unknown messages and want the field-number / wire-type / value breakdown without hunting down the right .proto file.
Wrap-vs-native judgement ¶
Native. The Protobuf wire format is fully published (developers.google.com/protocol-buffers/docs/encoding). Every field begins with a tag = (field_number << 3) | wire_type, encoded as a varint. Six wire types dispatch to a small set of value parsers: VARINT (0), I64 (1), LEN (2, length-prefixed bytes), SGROUP/EGROUP (3/4, deprecated), I32 (5). Pasting a hex blob from `grpcurl -d` output, a Wireshark gRPC dissector, an Android app traffic capture, or an mitmproxy export is enough — no .proto, no generated code, no library.
What this package covers ¶
- **Tag decoding**: field_number + wire_type extracted from the leading varint of each field.
- **Wire type dispatch**:
- 0 VARINT — surfaced as both unsigned uint64 and zigzag-decoded int64 (for sint32 / sint64 schema fields). Bool interpretation (0/1) also surfaced when applicable.
- 1 I64 — surfaced as raw uint64 + float64 interpretation (for double / fixed64 / sfixed64).
- 2 LEN — recursively tries to decode the bytes as a nested message; if that succeeds and consumes all bytes, surfaces the nested view. Otherwise falls back to UTF-8 string (if every byte is printable) or raw hex.
- 3 SGROUP / 4 EGROUP — deprecated; surfaced by name but no body decode attempted (groups are obsolete).
- 5 I32 — surfaced as raw uint32 + float32 interpretation (for float / fixed32 / sfixed32).
- **Varint reader** with continuation-bit handling and a max-10-byte guard (uint64 max).
- **Nested message detection**: for LEN fields, the decoder probes by attempting to parse the payload as a top-level message. If parsing consumes exactly the declared length and every field has a plausible tag, the nested view is preferred over the string/hex fallback.
What this package does NOT cover (deliberately out of scope) ¶
- **Schema-aware decode**: without the .proto, field names + types are unknown. This decoder surfaces field numbers (1, 2, 3, ...) and wire types — the operator maps those back to the .proto file themselves.
- **Packed repeated fields**: a packed repeated of varint / fixed32 / fixed64 is encoded as a single LEN field whose body is a concatenation of values (no per-element tag). Without schema awareness, the LEN body falls through to nested-message / string / hex heuristics; in practice the operator can spot packed repeats by looking at the raw hex.
- **gRPC framing**: the 5-byte gRPC HTTP/2 message prefix (1-byte compression flag + 4-byte big-endian length) is the caller's responsibility to strip before passing in.
- **Proto 3 default-value semantics** and the wire encoding's "this field is set to default" markers — this is a wire-level decoder, not a semantic one.
Index ¶
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Field ¶
type Field struct {
FieldNumber int `json:"field_number"`
WireType int `json:"wire_type"`
WireTypeName string `json:"wire_type_name"`
// At most one of these is populated, depending on wire
// type + heuristic outcome.
Uint64 *uint64 `json:"uint64,omitempty"`
SInt64 *int64 `json:"sint64_zigzag,omitempty"`
Bool *bool `json:"bool,omitempty"`
Uint32 *uint32 `json:"uint32,omitempty"`
Float32 *float64 `json:"float32,omitempty"`
Float64 *float64 `json:"float64,omitempty"`
String string `json:"string,omitempty"`
BytesHex string `json:"bytes_hex,omitempty"`
NestedMessage *Message `json:"nested_message,omitempty"`
}
Field is one tag/wire-type/value triple.
type Message ¶
type Message struct {
Fields []*Field `json:"fields,omitempty"`
}
Message is the recursive decoded view of one protobuf message (a sequence of fields).
func Decode ¶
Decode parses a hex-encoded Protobuf message. Trailing bytes after the last field are rejected.
func DecodeBytes ¶
DecodeBytes parses raw Protobuf bytes.