proto, runtime/protoiface: add support for fast-path marshaling

Allow message implementations to provide optimized versions of standard
operations. Generated messages now include a ProtoReflectMethods method,
returning a protoiface.Methods struct containing pointers to assorted
optional functions.

The Methods struct also includes a Flags field indicating support for
optional features such as deterministic marshaling.

Implementation of the fast paths (and tests) will come in later CLs.

Change-Id: Idd1beed0ecf43ec5e5e7b8da2ee1e08d3ce32213
Reviewed-on: https://go-review.googlesource.com/c/protobuf/+/170340
Reviewed-by: Joe Tsai <thebrokentoaster@gmail.com>
diff --git a/proto/size.go b/proto/size.go
index 8c9263f..a817cf7 100644
--- a/proto/size.go
+++ b/proto/size.go
@@ -13,9 +13,21 @@
 
 // Size returns the size in bytes of the wire-format encoding of m.
 func Size(m Message) int {
+	if size, err := sizeMessageFast(m); err == nil {
+		return size
+	}
 	return sizeMessage(m.ProtoReflect())
 }
 
+func sizeMessageFast(m Message) (int, error) {
+	// TODO: Pass MarshalOptions to size to permit disabling fast path?
+	methods := protoMethods(m)
+	if methods == nil || methods.Size == nil {
+		return 0, errInternalNoFast
+	}
+	return methods.Size(m), nil
+}
+
 func sizeMessage(m protoreflect.Message) (size int) {
 	fields := m.Type().Fields()
 	knownFields := m.KnownFields()