proto: Add CloneOf[M Message](m M) M
This allows writing:
`copy := proto.CloneOf(orig)`
instead of the previous:
`copy := proto.Clone(orig).(*pb.MyMessage)`
Fixes golang/protobuf#1594
Change-Id: I7b8b712b6e59607ccc339720ee3c146e8a7ea28b
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/653536
Reviewed-by: Cassondra Foesch <cfoesch@gmail.com>
Reviewed-by: Michael Stapelberg <stapelberg@google.com>
LUCI-TryBot-Result: Go LUCI <golang-scoped@luci-project-accounts.iam.gserviceaccount.com>
Reviewed-by: Damien Neil <dneil@google.com>
diff --git a/proto/merge.go b/proto/merge.go
index 3c6fe57..ef55b97 100644
--- a/proto/merge.go
+++ b/proto/merge.go
@@ -59,6 +59,12 @@
return dst.Interface()
}
+// CloneOf returns a deep copy of m. If the top-level message is invalid,
+// it returns an invalid message as well.
+func CloneOf[M Message](m M) M {
+ return Clone(m).(M)
+}
+
// mergeOptions provides a namespace for merge functions, and can be
// exported in the future if we add user-visible merge options.
type mergeOptions struct{}
diff --git a/proto/merge_test.go b/proto/merge_test.go
index 05978cb..2cdc1b7 100644
--- a/proto/merge_test.go
+++ b/proto/merge_test.go
@@ -853,6 +853,16 @@
}
}
+func TestCloneOf(t *testing.T) {
+ want := &testpb.TestAllTypes{
+ OptionalInt32: proto.Int32(1),
+ }
+ got := proto.CloneOf(want)
+ if !proto.Equal(got, want) {
+ t.Errorf("Clone(src) != src:\n got %v\nwant %v", got, want)
+ }
+}
+
// mutateValue changes a Value, returning a new value.
//
// For scalar values, it returns a value different from the input.