protobufdecode

package
v0.663.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 9, 2026 License: AGPL-3.0 Imports: 6 Imported by: 0

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

func Decode(hexBlob string) (*Message, error)

Decode parses a hex-encoded Protobuf message. Trailing bytes after the last field are rejected.

func DecodeBytes

func DecodeBytes(b []byte) (*Message, error)

DecodeBytes parses raw Protobuf bytes.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL