mirror of
https://github.com/protocolbuffers/protobuf-go.git
synced 2025-01-06 10:01:25 +00:00
6f9095c675
Rather than having the Converter carry a NewMessage method, have the struct simply expose the MessageType or EnumType since they carry more information and are retrieved anyways as part of the functionality of NewConverter. While changing Converter, export the fields and remove all the methods. Also, add an IsLegacy boolean, which is useful for the later implementation of the extension fields. Add a wrapLegacyEnum function which is used to wrap v1 enums as v2 enums. We use this functionality in NewLegacyConverter to detrive the EnumType. Additionally, modify wrapLegacyMessage to return a protoreflect.ProtoMessage to be consistent with wrapLegacyEnum which must return a protoreflect.ProtoEnum. Change-Id: Idc8989d07e4895d30de4ebc22c9ffa7357815cad Reviewed-on: https://go-review.googlesource.com/c/148827 Reviewed-by: Herbie Ong <herbie@google.com>
88 lines
2.2 KiB
Go
88 lines
2.2 KiB
Go
// 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 MapOf(p interface{}, kc, kv Converter) pref.Map {
|
|
// TODO: Validate that p is a *map[K]V?
|
|
rv := reflect.ValueOf(p).Elem()
|
|
return mapReflect{rv, kc, kv}
|
|
}
|
|
|
|
type mapReflect struct {
|
|
v reflect.Value // addressable map[K]V
|
|
keyConv Converter
|
|
valConv Converter
|
|
}
|
|
|
|
func (ms mapReflect) Len() int {
|
|
return ms.v.Len()
|
|
}
|
|
func (ms mapReflect) Has(k pref.MapKey) bool {
|
|
rk := ms.keyConv.GoValueOf(k.Value())
|
|
rv := ms.v.MapIndex(rk)
|
|
return rv.IsValid()
|
|
}
|
|
func (ms mapReflect) Get(k pref.MapKey) pref.Value {
|
|
rk := ms.keyConv.GoValueOf(k.Value())
|
|
rv := ms.v.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()))
|
|
}
|
|
rk := ms.keyConv.GoValueOf(k.Value())
|
|
rv := ms.valConv.GoValueOf(v)
|
|
ms.v.SetMapIndex(rk, rv)
|
|
}
|
|
func (ms mapReflect) Clear(k pref.MapKey) {
|
|
rk := ms.keyConv.GoValueOf(k.Value())
|
|
ms.v.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()))
|
|
}
|
|
rk := ms.keyConv.GoValueOf(k.Value())
|
|
rv := ms.v.MapIndex(rk)
|
|
if !rv.IsValid() || rv.IsNil() {
|
|
// TODO: Is checking for nil proper behavior for custom messages?
|
|
pv := pref.ValueOf(ms.valConv.MessageType.New().ProtoReflect())
|
|
rv = ms.valConv.GoValueOf(pv)
|
|
ms.v.SetMapIndex(rk, rv)
|
|
}
|
|
return rv.Interface().(pref.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() {
|
|
pk := ms.keyConv.PBValueOf(k).MapKey()
|
|
pv := ms.valConv.PBValueOf(v)
|
|
if !f(pk, pv) {
|
|
return
|
|
}
|
|
}
|
|
}
|
|
}
|
|
func (ms mapReflect) Unwrap() interface{} {
|
|
return ms.v.Interface()
|
|
}
|
|
func (ms mapReflect) ProtoMutable() {}
|
|
|
|
var (
|
|
_ pref.Map = mapReflect{}
|
|
_ Unwrapper = mapReflect{}
|
|
)
|