xref: /aosp_15_r20/external/golang-protobuf/internal/impl/convert_map.go (revision 1c12ee1efe575feb122dbf939ff15148a3b3e8f2)
1*1c12ee1eSDan Willemsen// Copyright 2018 The Go Authors. All rights reserved.
2*1c12ee1eSDan Willemsen// Use of this source code is governed by a BSD-style
3*1c12ee1eSDan Willemsen// license that can be found in the LICENSE file.
4*1c12ee1eSDan Willemsen
5*1c12ee1eSDan Willemsenpackage impl
6*1c12ee1eSDan Willemsen
7*1c12ee1eSDan Willemsenimport (
8*1c12ee1eSDan Willemsen	"fmt"
9*1c12ee1eSDan Willemsen	"reflect"
10*1c12ee1eSDan Willemsen
11*1c12ee1eSDan Willemsen	"google.golang.org/protobuf/reflect/protoreflect"
12*1c12ee1eSDan Willemsen)
13*1c12ee1eSDan Willemsen
14*1c12ee1eSDan Willemsentype mapConverter struct {
15*1c12ee1eSDan Willemsen	goType           reflect.Type // map[K]V
16*1c12ee1eSDan Willemsen	keyConv, valConv Converter
17*1c12ee1eSDan Willemsen}
18*1c12ee1eSDan Willemsen
19*1c12ee1eSDan Willemsenfunc newMapConverter(t reflect.Type, fd protoreflect.FieldDescriptor) *mapConverter {
20*1c12ee1eSDan Willemsen	if t.Kind() != reflect.Map {
21*1c12ee1eSDan Willemsen		panic(fmt.Sprintf("invalid Go type %v for field %v", t, fd.FullName()))
22*1c12ee1eSDan Willemsen	}
23*1c12ee1eSDan Willemsen	return &mapConverter{
24*1c12ee1eSDan Willemsen		goType:  t,
25*1c12ee1eSDan Willemsen		keyConv: newSingularConverter(t.Key(), fd.MapKey()),
26*1c12ee1eSDan Willemsen		valConv: newSingularConverter(t.Elem(), fd.MapValue()),
27*1c12ee1eSDan Willemsen	}
28*1c12ee1eSDan Willemsen}
29*1c12ee1eSDan Willemsen
30*1c12ee1eSDan Willemsenfunc (c *mapConverter) PBValueOf(v reflect.Value) protoreflect.Value {
31*1c12ee1eSDan Willemsen	if v.Type() != c.goType {
32*1c12ee1eSDan Willemsen		panic(fmt.Sprintf("invalid type: got %v, want %v", v.Type(), c.goType))
33*1c12ee1eSDan Willemsen	}
34*1c12ee1eSDan Willemsen	return protoreflect.ValueOfMap(&mapReflect{v, c.keyConv, c.valConv})
35*1c12ee1eSDan Willemsen}
36*1c12ee1eSDan Willemsen
37*1c12ee1eSDan Willemsenfunc (c *mapConverter) GoValueOf(v protoreflect.Value) reflect.Value {
38*1c12ee1eSDan Willemsen	return v.Map().(*mapReflect).v
39*1c12ee1eSDan Willemsen}
40*1c12ee1eSDan Willemsen
41*1c12ee1eSDan Willemsenfunc (c *mapConverter) IsValidPB(v protoreflect.Value) bool {
42*1c12ee1eSDan Willemsen	mapv, ok := v.Interface().(*mapReflect)
43*1c12ee1eSDan Willemsen	if !ok {
44*1c12ee1eSDan Willemsen		return false
45*1c12ee1eSDan Willemsen	}
46*1c12ee1eSDan Willemsen	return mapv.v.Type() == c.goType
47*1c12ee1eSDan Willemsen}
48*1c12ee1eSDan Willemsen
49*1c12ee1eSDan Willemsenfunc (c *mapConverter) IsValidGo(v reflect.Value) bool {
50*1c12ee1eSDan Willemsen	return v.IsValid() && v.Type() == c.goType
51*1c12ee1eSDan Willemsen}
52*1c12ee1eSDan Willemsen
53*1c12ee1eSDan Willemsenfunc (c *mapConverter) New() protoreflect.Value {
54*1c12ee1eSDan Willemsen	return c.PBValueOf(reflect.MakeMap(c.goType))
55*1c12ee1eSDan Willemsen}
56*1c12ee1eSDan Willemsen
57*1c12ee1eSDan Willemsenfunc (c *mapConverter) Zero() protoreflect.Value {
58*1c12ee1eSDan Willemsen	return c.PBValueOf(reflect.Zero(c.goType))
59*1c12ee1eSDan Willemsen}
60*1c12ee1eSDan Willemsen
61*1c12ee1eSDan Willemsentype mapReflect struct {
62*1c12ee1eSDan Willemsen	v       reflect.Value // map[K]V
63*1c12ee1eSDan Willemsen	keyConv Converter
64*1c12ee1eSDan Willemsen	valConv Converter
65*1c12ee1eSDan Willemsen}
66*1c12ee1eSDan Willemsen
67*1c12ee1eSDan Willemsenfunc (ms *mapReflect) Len() int {
68*1c12ee1eSDan Willemsen	return ms.v.Len()
69*1c12ee1eSDan Willemsen}
70*1c12ee1eSDan Willemsenfunc (ms *mapReflect) Has(k protoreflect.MapKey) bool {
71*1c12ee1eSDan Willemsen	rk := ms.keyConv.GoValueOf(k.Value())
72*1c12ee1eSDan Willemsen	rv := ms.v.MapIndex(rk)
73*1c12ee1eSDan Willemsen	return rv.IsValid()
74*1c12ee1eSDan Willemsen}
75*1c12ee1eSDan Willemsenfunc (ms *mapReflect) Get(k protoreflect.MapKey) protoreflect.Value {
76*1c12ee1eSDan Willemsen	rk := ms.keyConv.GoValueOf(k.Value())
77*1c12ee1eSDan Willemsen	rv := ms.v.MapIndex(rk)
78*1c12ee1eSDan Willemsen	if !rv.IsValid() {
79*1c12ee1eSDan Willemsen		return protoreflect.Value{}
80*1c12ee1eSDan Willemsen	}
81*1c12ee1eSDan Willemsen	return ms.valConv.PBValueOf(rv)
82*1c12ee1eSDan Willemsen}
83*1c12ee1eSDan Willemsenfunc (ms *mapReflect) Set(k protoreflect.MapKey, v protoreflect.Value) {
84*1c12ee1eSDan Willemsen	rk := ms.keyConv.GoValueOf(k.Value())
85*1c12ee1eSDan Willemsen	rv := ms.valConv.GoValueOf(v)
86*1c12ee1eSDan Willemsen	ms.v.SetMapIndex(rk, rv)
87*1c12ee1eSDan Willemsen}
88*1c12ee1eSDan Willemsenfunc (ms *mapReflect) Clear(k protoreflect.MapKey) {
89*1c12ee1eSDan Willemsen	rk := ms.keyConv.GoValueOf(k.Value())
90*1c12ee1eSDan Willemsen	ms.v.SetMapIndex(rk, reflect.Value{})
91*1c12ee1eSDan Willemsen}
92*1c12ee1eSDan Willemsenfunc (ms *mapReflect) Mutable(k protoreflect.MapKey) protoreflect.Value {
93*1c12ee1eSDan Willemsen	if _, ok := ms.valConv.(*messageConverter); !ok {
94*1c12ee1eSDan Willemsen		panic("invalid Mutable on map with non-message value type")
95*1c12ee1eSDan Willemsen	}
96*1c12ee1eSDan Willemsen	v := ms.Get(k)
97*1c12ee1eSDan Willemsen	if !v.IsValid() {
98*1c12ee1eSDan Willemsen		v = ms.NewValue()
99*1c12ee1eSDan Willemsen		ms.Set(k, v)
100*1c12ee1eSDan Willemsen	}
101*1c12ee1eSDan Willemsen	return v
102*1c12ee1eSDan Willemsen}
103*1c12ee1eSDan Willemsenfunc (ms *mapReflect) Range(f func(protoreflect.MapKey, protoreflect.Value) bool) {
104*1c12ee1eSDan Willemsen	iter := mapRange(ms.v)
105*1c12ee1eSDan Willemsen	for iter.Next() {
106*1c12ee1eSDan Willemsen		k := ms.keyConv.PBValueOf(iter.Key()).MapKey()
107*1c12ee1eSDan Willemsen		v := ms.valConv.PBValueOf(iter.Value())
108*1c12ee1eSDan Willemsen		if !f(k, v) {
109*1c12ee1eSDan Willemsen			return
110*1c12ee1eSDan Willemsen		}
111*1c12ee1eSDan Willemsen	}
112*1c12ee1eSDan Willemsen}
113*1c12ee1eSDan Willemsenfunc (ms *mapReflect) NewValue() protoreflect.Value {
114*1c12ee1eSDan Willemsen	return ms.valConv.New()
115*1c12ee1eSDan Willemsen}
116*1c12ee1eSDan Willemsenfunc (ms *mapReflect) IsValid() bool {
117*1c12ee1eSDan Willemsen	return !ms.v.IsNil()
118*1c12ee1eSDan Willemsen}
119*1c12ee1eSDan Willemsenfunc (ms *mapReflect) protoUnwrap() interface{} {
120*1c12ee1eSDan Willemsen	return ms.v.Interface()
121*1c12ee1eSDan Willemsen}
122