proto: extend Marshal documentation, include an example

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>
This commit is contained in:
Michael Stapelberg 2024-03-26 16:31:25 +01:00
parent 3ebf7dd8a5
commit c69658e234
2 changed files with 32 additions and 0 deletions

View File

@ -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 {

View File

@ -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"
@ -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
}