@@ -23,10 +23,11 @@ package proto
2323import (
2424 "fmt"
2525
26- "google.golang.org/grpc/encoding"
27- "google.golang.org/grpc/mem"
2826 "google.golang.org/protobuf/proto"
2927 "google.golang.org/protobuf/protoadapt"
28+
29+ "google.golang.org/grpc/encoding"
30+ "google.golang.org/grpc/mem"
3031)
3132
3233// Name is the name registered for the proto compressor.
@@ -46,9 +47,21 @@ func (c *codecV2) Marshal(v any) (data mem.BufferSlice, err error) {
4647 return nil , fmt .Errorf ("proto: failed to marshal, message is %T, want proto.Message" , v )
4748 }
4849
50+ // Important: if we remove this Size call then we cannot use
51+ // UseCachedSize in MarshalOptions below.
4952 size := proto .Size (vv )
50- // proto.Size caches the size, enabling UseCachedSize
51- // lets us reuse that value instead of recomputing it during marshal.
53+
54+ // MarshalOptions with UseCachedSize allows reusing the result from the
55+ // previous Size call. This is safe here because:
56+ //
57+ // 1. We just computed the size.
58+ // 2. We assume the message is not being mutated concurrently.
59+ //
60+ // Important: If the proto.Size call above is removed, using UseCachedSize
61+ // becomes unsafe and may lead to incorrect marshaling.
62+ //
63+ // For more details, see the doc of UseCachedSize:
64+ // https://pkg.go.dev/google.golang.org/protobuf/proto#MarshalOptions
5265 marshalOptions := proto.MarshalOptions {UseCachedSize : true }
5366
5467 if mem .IsBelowBufferPoolingThreshold (size ) {
0 commit comments