encoding: add Format helper function and method

The Format function and MarshalOptions.Format method are helper
functions for directly obtaining the formatted string for a message
without having to deal with errors or convert a []byte to string.
It is only intended for human consumption (e.g., debugging or logging).

We also add a MarshalOptions.Multiline option to specify that the output
should use some default indentation in a multiline output.

This assists in the v1 to v2 migration where:
	protoV1.CompactTextString(m) => prototext.MarshalOptions{}.Format(m)
	protoV1.MarshalTextString(m) => prototext.Format(m)

At Google, there are approximately 10x more usages of MarshalTextString than
CompactTextString, so it makes sense that the top-level Format function
does multiline expansion by default.

Fixes #850

Change-Id: I149c9e190a6d99b985d3884df675499a3313e9b3
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/213460
Reviewed-by: Damien Neil <dneil@google.com>
Reviewed-by: Herbie Ong <herbie@google.com>
diff --git a/proto/decode_test.go b/proto/decode_test.go
index 5ccb816..3b8a092 100644
--- a/proto/decode_test.go
+++ b/proto/decode_test.go
@@ -30,7 +30,7 @@
 				wire := append(([]byte)(nil), test.wire...)
 				got := reflect.New(reflect.TypeOf(want).Elem()).Interface().(proto.Message)
 				if err := opts.Unmarshal(wire, got); err != nil {
-					t.Errorf("Unmarshal error: %v\nMessage:\n%v", err, marshalText(want))
+					t.Errorf("Unmarshal error: %v\nMessage:\n%v", err, prototext.Format(want))
 					return
 				}
 
@@ -40,7 +40,7 @@
 					wire[i] = 0
 				}
 				if !proto.Equal(got, want) && got.ProtoReflect().IsValid() && want.ProtoReflect().IsValid() {
-					t.Errorf("Unmarshal returned unexpected result; got:\n%v\nwant:\n%v", marshalText(got), marshalText(want))
+					t.Errorf("Unmarshal returned unexpected result; got:\n%v\nwant:\n%v", prototext.Format(got), prototext.Format(want))
 				}
 			})
 		}
@@ -58,7 +58,7 @@
 				opts.AllowPartial = false
 				got := reflect.New(reflect.TypeOf(m).Elem()).Interface().(proto.Message)
 				if err := proto.Unmarshal(test.wire, got); err == nil {
-					t.Fatalf("Unmarshal succeeded (want error)\nMessage:\n%v", marshalText(got))
+					t.Fatalf("Unmarshal succeeded (want error)\nMessage:\n%v", prototext.Format(got))
 				}
 			})
 		}
@@ -76,7 +76,7 @@
 				opts.AllowPartial = test.partial
 				got := want.ProtoReflect().New().Interface()
 				if err := opts.Unmarshal(test.wire, got); err == nil {
-					t.Errorf("Unmarshal unexpectedly succeeded\ninput bytes: [%x]\nMessage:\n%v", test.wire, marshalText(got))
+					t.Errorf("Unmarshal unexpectedly succeeded\ninput bytes: [%x]\nMessage:\n%v", test.wire, prototext.Format(got))
 				}
 			})
 		}
@@ -147,15 +147,3 @@
 		proto.SetExtension(m, desc, value)
 	}
 }
-
-func marshalText(m proto.Message) string {
-	if m == nil {
-		return "<nil>\n"
-	}
-	b, _ := prototext.MarshalOptions{
-		AllowPartial: true,
-		EmitUnknown:  true,
-		Indent:       "\t",
-	}.Marshal(m)
-	return string(b)
-}