internal/impl: allow reflection on typed nil pointers

Similar to how generated messages allow you to call Get methods on a
nil pointer, we permit similar functionality when protobuf reflection
is used on a nil pointer.

Change-Id: Ie2f596d39105c191073b42d7d689525c3b715240
Reviewed-on: https://go-review.googlesource.com/c/152021
Reviewed-by: Damien Neil <dneil@google.com>
diff --git a/internal/value/list.go b/internal/value/list.go
index dadb05f..bcac98b 100644
--- a/internal/value/list.go
+++ b/internal/value/list.go
@@ -15,41 +15,44 @@
 	Unwrapper
 } {
 	// TODO: Validate that p is a *[]T?
-	rv := reflect.ValueOf(p).Elem()
+	rv := reflect.ValueOf(p)
 	return listReflect{rv, c}
 }
 
 type listReflect struct {
-	v    reflect.Value // addressable []T
+	v    reflect.Value // *[]T
 	conv Converter
 }
 
 func (ls listReflect) Len() int {
-	return ls.v.Len()
+	if ls.v.IsNil() {
+		return 0
+	}
+	return ls.v.Elem().Len()
 }
 func (ls listReflect) Get(i int) pref.Value {
-	return ls.conv.PBValueOf(ls.v.Index(i))
+	return ls.conv.PBValueOf(ls.v.Elem().Index(i))
 }
 func (ls listReflect) Set(i int, v pref.Value) {
-	ls.v.Index(i).Set(ls.conv.GoValueOf(v))
+	ls.v.Elem().Index(i).Set(ls.conv.GoValueOf(v))
 }
 func (ls listReflect) Append(v pref.Value) {
-	ls.v.Set(reflect.Append(ls.v, ls.conv.GoValueOf(v)))
+	ls.v.Elem().Set(reflect.Append(ls.v.Elem(), ls.conv.GoValueOf(v)))
 }
 func (ls listReflect) Mutable(i int) pref.Mutable {
 	// Mutable is only valid for messages and panics for other kinds.
-	return ls.conv.PBValueOf(ls.v.Index(i)).Message()
+	return ls.conv.PBValueOf(ls.v.Elem().Index(i)).Message()
 }
 func (ls listReflect) MutableAppend() pref.Mutable {
 	// MutableAppend is only valid for messages and panics for other kinds.
 	pv := pref.ValueOf(ls.conv.MessageType.New().ProtoReflect())
-	ls.v.Set(reflect.Append(ls.v, ls.conv.GoValueOf(pv)))
+	ls.v.Elem().Set(reflect.Append(ls.v.Elem(), ls.conv.GoValueOf(pv)))
 	return pv.Message()
 }
 func (ls listReflect) Truncate(i int) {
-	ls.v.Set(ls.v.Slice(0, i))
+	ls.v.Elem().Set(ls.v.Elem().Slice(0, i))
 }
 func (ls listReflect) ProtoUnwrap() interface{} {
-	return ls.v.Addr().Interface()
+	return ls.v.Interface()
 }
 func (ls listReflect) ProtoMutable() {}
diff --git a/internal/value/map.go b/internal/value/map.go
index 8505798..28b901b 100644
--- a/internal/value/map.go
+++ b/internal/value/map.go
@@ -15,61 +15,73 @@
 	Unwrapper
 } {
 	// TODO: Validate that p is a *map[K]V?
-	rv := reflect.ValueOf(p).Elem()
+	rv := reflect.ValueOf(p)
 	return mapReflect{rv, kc, kv}
 }
 
 type mapReflect struct {
-	v       reflect.Value // addressable map[K]V
+	v       reflect.Value // *map[K]V
 	keyConv Converter
 	valConv Converter
 }
 
 func (ms mapReflect) Len() int {
-	return ms.v.Len()
+	if ms.v.IsNil() {
+		return 0
+	}
+	return ms.v.Elem().Len()
 }
 func (ms mapReflect) Has(k pref.MapKey) bool {
+	if ms.v.IsNil() {
+		return false
+	}
 	rk := ms.keyConv.GoValueOf(k.Value())
-	rv := ms.v.MapIndex(rk)
+	rv := ms.v.Elem().MapIndex(rk)
 	return rv.IsValid()
 }
 func (ms mapReflect) Get(k pref.MapKey) pref.Value {
+	if ms.v.IsNil() {
+		return pref.Value{}
+	}
 	rk := ms.keyConv.GoValueOf(k.Value())
-	rv := ms.v.MapIndex(rk)
+	rv := ms.v.Elem().MapIndex(rk)
 	if !rv.IsValid() {
 		return pref.Value{}
 	}
 	return ms.valConv.PBValueOf(rv)
 }
 func (ms mapReflect) Set(k pref.MapKey, v pref.Value) {
-	if ms.v.IsNil() {
-		ms.v.Set(reflect.MakeMap(ms.v.Type()))
+	if ms.v.Elem().IsNil() {
+		ms.v.Elem().Set(reflect.MakeMap(ms.v.Elem().Type()))
 	}
 	rk := ms.keyConv.GoValueOf(k.Value())
 	rv := ms.valConv.GoValueOf(v)
-	ms.v.SetMapIndex(rk, rv)
+	ms.v.Elem().SetMapIndex(rk, rv)
 }
 func (ms mapReflect) Clear(k pref.MapKey) {
 	rk := ms.keyConv.GoValueOf(k.Value())
-	ms.v.SetMapIndex(rk, reflect.Value{})
+	ms.v.Elem().SetMapIndex(rk, reflect.Value{})
 }
 func (ms mapReflect) Mutable(k pref.MapKey) pref.Mutable {
 	// Mutable is only valid for messages and panics for other kinds.
-	if ms.v.IsNil() {
-		ms.v.Set(reflect.MakeMap(ms.v.Type()))
+	if ms.v.Elem().IsNil() {
+		ms.v.Elem().Set(reflect.MakeMap(ms.v.Elem().Type()))
 	}
 	rk := ms.keyConv.GoValueOf(k.Value())
-	rv := ms.v.MapIndex(rk)
+	rv := ms.v.Elem().MapIndex(rk)
 	if !rv.IsValid() {
 		pv := pref.ValueOf(ms.valConv.MessageType.New().ProtoReflect())
 		rv = ms.valConv.GoValueOf(pv)
-		ms.v.SetMapIndex(rk, rv)
+		ms.v.Elem().SetMapIndex(rk, rv)
 	}
 	return ms.valConv.PBValueOf(rv).Message()
 }
 func (ms mapReflect) Range(f func(pref.MapKey, pref.Value) bool) {
-	for _, k := range ms.v.MapKeys() {
-		if v := ms.v.MapIndex(k); v.IsValid() {
+	if ms.v.IsNil() {
+		return
+	}
+	for _, k := range ms.v.Elem().MapKeys() {
+		if v := ms.v.Elem().MapIndex(k); v.IsValid() {
 			pk := ms.keyConv.PBValueOf(k).MapKey()
 			pv := ms.valConv.PBValueOf(v)
 			if !f(pk, pv) {
@@ -79,6 +91,6 @@
 	}
 }
 func (ms mapReflect) ProtoUnwrap() interface{} {
-	return ms.v.Addr().Interface()
+	return ms.v.Interface()
 }
 func (ms mapReflect) ProtoMutable() {}