blob: 8505798fe5b1c73f0201e569a3762d13a306d08f [file] [log] [blame]
Joe Tsai88bc5a72018-11-05 11:42:22 -08001// Copyright 2018 The Go Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style
3// license that can be found in the LICENSE file.
4
5package value
6
7import (
8 "reflect"
9
10 pref "github.com/golang/protobuf/v2/reflect/protoreflect"
11)
12
Joe Tsaiba0ef9a2018-11-29 14:54:05 -080013func MapOf(p interface{}, kc, kv Converter) interface {
14 pref.Map
15 Unwrapper
16} {
Joe Tsai88bc5a72018-11-05 11:42:22 -080017 // TODO: Validate that p is a *map[K]V?
18 rv := reflect.ValueOf(p).Elem()
19 return mapReflect{rv, kc, kv}
20}
21
22type mapReflect struct {
23 v reflect.Value // addressable map[K]V
24 keyConv Converter
25 valConv Converter
26}
27
28func (ms mapReflect) Len() int {
29 return ms.v.Len()
30}
31func (ms mapReflect) Has(k pref.MapKey) bool {
32 rk := ms.keyConv.GoValueOf(k.Value())
33 rv := ms.v.MapIndex(rk)
34 return rv.IsValid()
35}
36func (ms mapReflect) Get(k pref.MapKey) pref.Value {
37 rk := ms.keyConv.GoValueOf(k.Value())
38 rv := ms.v.MapIndex(rk)
39 if !rv.IsValid() {
40 return pref.Value{}
41 }
42 return ms.valConv.PBValueOf(rv)
43}
44func (ms mapReflect) Set(k pref.MapKey, v pref.Value) {
45 if ms.v.IsNil() {
46 ms.v.Set(reflect.MakeMap(ms.v.Type()))
47 }
48 rk := ms.keyConv.GoValueOf(k.Value())
49 rv := ms.valConv.GoValueOf(v)
50 ms.v.SetMapIndex(rk, rv)
51}
52func (ms mapReflect) Clear(k pref.MapKey) {
53 rk := ms.keyConv.GoValueOf(k.Value())
54 ms.v.SetMapIndex(rk, reflect.Value{})
55}
56func (ms mapReflect) Mutable(k pref.MapKey) pref.Mutable {
57 // Mutable is only valid for messages and panics for other kinds.
58 if ms.v.IsNil() {
59 ms.v.Set(reflect.MakeMap(ms.v.Type()))
60 }
61 rk := ms.keyConv.GoValueOf(k.Value())
62 rv := ms.v.MapIndex(rk)
Joe Tsaif6d4a422018-11-19 14:26:06 -080063 if !rv.IsValid() {
Joe Tsai6f9095c2018-11-10 14:12:21 -080064 pv := pref.ValueOf(ms.valConv.MessageType.New().ProtoReflect())
Joe Tsai88bc5a72018-11-05 11:42:22 -080065 rv = ms.valConv.GoValueOf(pv)
66 ms.v.SetMapIndex(rk, rv)
67 }
Joe Tsaif6d4a422018-11-19 14:26:06 -080068 return ms.valConv.PBValueOf(rv).Message()
Joe Tsai88bc5a72018-11-05 11:42:22 -080069}
70func (ms mapReflect) Range(f func(pref.MapKey, pref.Value) bool) {
71 for _, k := range ms.v.MapKeys() {
72 if v := ms.v.MapIndex(k); v.IsValid() {
73 pk := ms.keyConv.PBValueOf(k).MapKey()
74 pv := ms.valConv.PBValueOf(v)
75 if !f(pk, pv) {
76 return
77 }
78 }
79 }
80}
Joe Tsaiba0ef9a2018-11-29 14:54:05 -080081func (ms mapReflect) ProtoUnwrap() interface{} {
Joe Tsaif0c01e42018-11-06 13:05:20 -080082 return ms.v.Addr().Interface()
Joe Tsai88bc5a72018-11-05 11:42:22 -080083}
84func (ms mapReflect) ProtoMutable() {}