internal/impl: initial commit

This provides an implementation of the has, get, set, clear methods for each
field in a message. The approach taken here is similar to the table-driven
implementation in the current v1 proto package.

The pointer_reflect.go and pointer_unsafe.go files are a simplified version of
the same files in the v1 implementation. They provide a pointer abstraction
that enables a high-efficiency approach in a non-purego environment.
The unsafe fast-path is not implemented in this commit.

This commit only implements the accessor methods for scalars using pure
Go reflection.

Change-Id: Icdf707e9d4e3385e55434f93b30a341a7680ae11
Reviewed-on: https://go-review.googlesource.com/135136
Reviewed-by: Damien Neil <dneil@google.com>
diff --git a/internal/impl/message.go b/internal/impl/message.go
new file mode 100644
index 0000000..2f10f1d
--- /dev/null
+++ b/internal/impl/message.go
@@ -0,0 +1,91 @@
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package impl
+
+import (
+	"reflect"
+	"strconv"
+	"strings"
+
+	pref "google.golang.org/proto/reflect/protoreflect"
+)
+
+type MessageInfo struct {
+	// TODO: Split fields into dense and sparse maps similar to the current
+	// table-driven implementation in v1?
+	fields map[pref.FieldNumber]*fieldInfo
+}
+
+// generateFieldFuncs generates per-field functions for all common operations
+// to be performed on each field. It takes in a reflect.Type representing the
+// Go struct, and a protoreflect.MessageDescriptor to match with the fields
+// in the struct.
+//
+// This code assumes that the struct is well-formed and panics if there are
+// any discrepancies.
+func (mi *MessageInfo) generateFieldFuncs(t reflect.Type, md pref.MessageDescriptor) {
+	// Generate a mapping of field numbers and names to Go struct field or type.
+	fields := map[pref.FieldNumber]reflect.StructField{}
+	oneofs := map[pref.Name]reflect.StructField{}
+	oneofFields := map[pref.FieldNumber]reflect.Type{}
+	special := map[string]reflect.StructField{}
+fieldLoop:
+	for i := 0; i < t.NumField(); i++ {
+		f := t.Field(i)
+		for _, s := range strings.Split(f.Tag.Get("protobuf"), ",") {
+			if len(s) > 0 && strings.Trim(s, "0123456789") == "" {
+				n, _ := strconv.ParseUint(s, 10, 64)
+				fields[pref.FieldNumber(n)] = f
+				continue fieldLoop
+			}
+		}
+		if s := f.Tag.Get("protobuf_oneof"); len(s) > 0 {
+			oneofs[pref.Name(s)] = f
+			continue fieldLoop
+		}
+		switch f.Name {
+		case "XXX_weak", "XXX_unrecognized", "XXX_sizecache", "XXX_extensions", "XXX_InternalExtensions":
+			special[f.Name] = f
+			continue fieldLoop
+		}
+	}
+	if fn, ok := t.MethodByName("XXX_OneofFuncs"); ok {
+		vs := fn.Func.Call([]reflect.Value{reflect.New(fn.Type.In(0)).Elem()})[3]
+	oneofLoop:
+		for _, v := range vs.Interface().([]interface{}) {
+			tf := reflect.TypeOf(v).Elem()
+			f := tf.Field(0)
+			for _, s := range strings.Split(f.Tag.Get("protobuf"), ",") {
+				if len(s) > 0 && strings.Trim(s, "0123456789") == "" {
+					n, _ := strconv.ParseUint(s, 10, 64)
+					oneofFields[pref.FieldNumber(n)] = tf
+					continue oneofLoop
+				}
+			}
+		}
+	}
+
+	mi.fields = map[pref.FieldNumber]*fieldInfo{}
+	for i := 0; i < md.Fields().Len(); i++ {
+		fd := md.Fields().Get(i)
+		fs := fields[fd.Number()]
+		var fi fieldInfo
+		switch {
+		case fd.IsWeak():
+			fi = fieldInfoForWeak(fd, special["XXX_weak"])
+		case fd.OneofType() != nil:
+			fi = fieldInfoForOneof(fd, oneofs[fd.OneofType().Name()], oneofFields[fd.Number()])
+		case fd.IsMap():
+			fi = fieldInfoForMap(fd, fs)
+		case fd.Cardinality() == pref.Repeated:
+			fi = fieldInfoForVector(fd, fs)
+		case fd.Kind() != pref.MessageKind && fd.Kind() != pref.GroupKind:
+			fi = fieldInfoForScalar(fd, fs)
+		default:
+			fi = fieldInfoForMessage(fd, fs)
+		}
+		mi.fields[fd.Number()] = &fi
+	}
+}