Skip to content

Commit

Permalink
proto: extend Marshal documentation, include an example
Browse files Browse the repository at this point in the history
The example has been written so that it can be run, meaning it only uses
packages that are included in the protobuf module (durationpb specifically).

I included an Output: comment in the example so that pkgsite displays the
program output even without having to run it (but running it is of course
possible).

I added a brief tip to protoscope, which is often mentioned in the protobuf.dev
docs for illustrative purposes, and I think it really makes much clearer to the
reader how the protobuf wire format looks like and what information survives the
encoding process (field numbers and their values, but not field names like in
JSON).

The struct literal contains only one field so that we don’t need to marshal this
message deterministically for stable wire format, which is not the point of the
example and would be distracting.

The value was chosen such that the wire format hex representation contains at
least one byte that is clearly identifiable as hexadecimal, to avoid confusion.

Change-Id: I86103abfd7d5b3f654aca3bfbb452f8ef7e49828
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/574455
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-by: Lasse Folger <lassefolger@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
  • Loading branch information
stapelberg committed Mar 27, 2024
1 parent 3ebf7dd commit c69658e
Show file tree
Hide file tree
Showing 2 changed files with 32 additions and 0 deletions.
4 changes: 4 additions & 0 deletions proto/encode.go
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,10 @@ type MarshalOptions struct {
}

// Marshal returns the wire-format encoding of m.
//
// This is the most convenient entry point for encoding a Protobuf message.
//
// See the [MarshalOptions] type if you need more control.
func Marshal(m Message) ([]byte, error) {
// Treat nil message interface as an empty message; nothing to output.
if m == nil {
Expand Down
28 changes: 28 additions & 0 deletions proto/encode_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ import (
"google.golang.org/protobuf/encoding/protowire"
"google.golang.org/protobuf/proto"
"google.golang.org/protobuf/reflect/protoreflect"
"google.golang.org/protobuf/types/known/durationpb"

"google.golang.org/protobuf/internal/errors"
orderpb "google.golang.org/protobuf/internal/testprotos/order"
Expand Down Expand Up @@ -281,3 +282,30 @@ func TestEncodeEmpty(t *testing.T) {
})
}
}

// This example illustrates how to marshal (encode) a Protobuf message struct
// literal into wire-format encoding.
//
// This example hard-codes a duration of 125ns for the illustration of struct
// fields, but note that you do not need to fill the fields of well-known types
// like duration.proto yourself. To convert a time.Duration, use
// [google.golang.org/protobuf/types/known/durationpb.New].
func ExampleMarshal() {
b, err := proto.Marshal(&durationpb.Duration{
Nanos: 125,
})
if err != nil {
panic(err)
}

fmt.Printf("125ns encoded into %d bytes of Protobuf wire format:\n% x\n", len(b), b)

// You can use protoscope to explore the wire format:
// https://github.com/protocolbuffers/protoscope
//
// echo -n '10 7d' | xxd -r -ps | protoscope
// 2: 125

// Output: 125ns encoded into 2 bytes of Protobuf wire format:
// 10 7d
}

0 comments on commit c69658e

Please sign in to comment.