internal/value: extract Vector and Map logic as separate package

The implementation of reflect/protoreflect.NewGoExtension needs to be able to
provide a constructor for wrapping *[]T as a protoreflect.Vector.
However, it cannot depend on internal/impl since impl also depends on prototype.
Extract the common logic of Vector creation into a separate package that
has no dependencies on either impl or prototype.

Change-Id: I9295fde9b8861de11af085c91d9dfa56047d1b1e
Reviewed-on: https://go-review.googlesource.com/c/147446
Reviewed-by: Herbie Ong <herbie@google.com>
diff --git a/internal/value/vector.go b/internal/value/vector.go
new file mode 100644
index 0000000..4c1a78d
--- /dev/null
+++ b/internal/value/vector.go
@@ -0,0 +1,63 @@
+// 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 value
+
+import (
+	"reflect"
+
+	pref "github.com/golang/protobuf/v2/reflect/protoreflect"
+)
+
+func VectorOf(p interface{}, c Converter) pref.Vector {
+	// TODO: Validate that p is a *[]T?
+	rv := reflect.ValueOf(p).Elem()
+	return vectorReflect{rv, c}
+}
+
+type vectorReflect struct {
+	v    reflect.Value // addressable []T
+	conv Converter
+}
+
+func (vs vectorReflect) Len() int {
+	return vs.v.Len()
+}
+func (vs vectorReflect) Get(i int) pref.Value {
+	return vs.conv.PBValueOf(vs.v.Index(i))
+}
+func (vs vectorReflect) Set(i int, v pref.Value) {
+	vs.v.Index(i).Set(vs.conv.GoValueOf(v))
+}
+func (vs vectorReflect) Append(v pref.Value) {
+	vs.v.Set(reflect.Append(vs.v, vs.conv.GoValueOf(v)))
+}
+func (vs vectorReflect) Mutable(i int) pref.Mutable {
+	// Mutable is only valid for messages and panics for other kinds.
+	rv := vs.v.Index(i)
+	if rv.IsNil() {
+		// TODO: Is checking for nil proper behavior for custom messages?
+		pv := pref.ValueOf(vs.conv.NewMessage())
+		rv.Set(vs.conv.GoValueOf(pv))
+	}
+	return rv.Interface().(pref.Message)
+}
+func (vs vectorReflect) MutableAppend() pref.Mutable {
+	// MutableAppend is only valid for messages and panics for other kinds.
+	pv := pref.ValueOf(vs.conv.NewMessage())
+	vs.v.Set(reflect.Append(vs.v, vs.conv.GoValueOf(pv)))
+	return vs.v.Index(vs.Len() - 1).Interface().(pref.Message)
+}
+func (vs vectorReflect) Truncate(i int) {
+	vs.v.Set(vs.v.Slice(0, i))
+}
+func (vs vectorReflect) Unwrap() interface{} {
+	return vs.v.Interface()
+}
+func (vs vectorReflect) ProtoMutable() {}
+
+var (
+	_ pref.Vector = vectorReflect{}
+	_ Unwrapper   = vectorReflect{}
+)