blob: 28b901b7b5fbb4693b84b9411318bbc2f7ee1539 [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?
Joe Tsai6cf80c42018-12-01 04:57:09 -080018 rv := reflect.ValueOf(p)
Joe Tsai88bc5a72018-11-05 11:42:22 -080019 return mapReflect{rv, kc, kv}
20}
21
22type mapReflect struct {
Joe Tsai6cf80c42018-12-01 04:57:09 -080023 v reflect.Value // *map[K]V
Joe Tsai88bc5a72018-11-05 11:42:22 -080024 keyConv Converter
25 valConv Converter
26}
27
28func (ms mapReflect) Len() int {
Joe Tsai6cf80c42018-12-01 04:57:09 -080029 if ms.v.IsNil() {
30 return 0
31 }
32 return ms.v.Elem().Len()
Joe Tsai88bc5a72018-11-05 11:42:22 -080033}
34func (ms mapReflect) Has(k pref.MapKey) bool {
Joe Tsai6cf80c42018-12-01 04:57:09 -080035 if ms.v.IsNil() {
36 return false
37 }
Joe Tsai88bc5a72018-11-05 11:42:22 -080038 rk := ms.keyConv.GoValueOf(k.Value())
Joe Tsai6cf80c42018-12-01 04:57:09 -080039 rv := ms.v.Elem().MapIndex(rk)
Joe Tsai88bc5a72018-11-05 11:42:22 -080040 return rv.IsValid()
41}
42func (ms mapReflect) Get(k pref.MapKey) pref.Value {
Joe Tsai6cf80c42018-12-01 04:57:09 -080043 if ms.v.IsNil() {
44 return pref.Value{}
45 }
Joe Tsai88bc5a72018-11-05 11:42:22 -080046 rk := ms.keyConv.GoValueOf(k.Value())
Joe Tsai6cf80c42018-12-01 04:57:09 -080047 rv := ms.v.Elem().MapIndex(rk)
Joe Tsai88bc5a72018-11-05 11:42:22 -080048 if !rv.IsValid() {
49 return pref.Value{}
50 }
51 return ms.valConv.PBValueOf(rv)
52}
53func (ms mapReflect) Set(k pref.MapKey, v pref.Value) {
Joe Tsai6cf80c42018-12-01 04:57:09 -080054 if ms.v.Elem().IsNil() {
55 ms.v.Elem().Set(reflect.MakeMap(ms.v.Elem().Type()))
Joe Tsai88bc5a72018-11-05 11:42:22 -080056 }
57 rk := ms.keyConv.GoValueOf(k.Value())
58 rv := ms.valConv.GoValueOf(v)
Joe Tsai6cf80c42018-12-01 04:57:09 -080059 ms.v.Elem().SetMapIndex(rk, rv)
Joe Tsai88bc5a72018-11-05 11:42:22 -080060}
61func (ms mapReflect) Clear(k pref.MapKey) {
62 rk := ms.keyConv.GoValueOf(k.Value())
Joe Tsai6cf80c42018-12-01 04:57:09 -080063 ms.v.Elem().SetMapIndex(rk, reflect.Value{})
Joe Tsai88bc5a72018-11-05 11:42:22 -080064}
65func (ms mapReflect) Mutable(k pref.MapKey) pref.Mutable {
66 // Mutable is only valid for messages and panics for other kinds.
Joe Tsai6cf80c42018-12-01 04:57:09 -080067 if ms.v.Elem().IsNil() {
68 ms.v.Elem().Set(reflect.MakeMap(ms.v.Elem().Type()))
Joe Tsai88bc5a72018-11-05 11:42:22 -080069 }
70 rk := ms.keyConv.GoValueOf(k.Value())
Joe Tsai6cf80c42018-12-01 04:57:09 -080071 rv := ms.v.Elem().MapIndex(rk)
Joe Tsaif6d4a422018-11-19 14:26:06 -080072 if !rv.IsValid() {
Joe Tsai6f9095c2018-11-10 14:12:21 -080073 pv := pref.ValueOf(ms.valConv.MessageType.New().ProtoReflect())
Joe Tsai88bc5a72018-11-05 11:42:22 -080074 rv = ms.valConv.GoValueOf(pv)
Joe Tsai6cf80c42018-12-01 04:57:09 -080075 ms.v.Elem().SetMapIndex(rk, rv)
Joe Tsai88bc5a72018-11-05 11:42:22 -080076 }
Joe Tsaif6d4a422018-11-19 14:26:06 -080077 return ms.valConv.PBValueOf(rv).Message()
Joe Tsai88bc5a72018-11-05 11:42:22 -080078}
79func (ms mapReflect) Range(f func(pref.MapKey, pref.Value) bool) {
Joe Tsai6cf80c42018-12-01 04:57:09 -080080 if ms.v.IsNil() {
81 return
82 }
83 for _, k := range ms.v.Elem().MapKeys() {
84 if v := ms.v.Elem().MapIndex(k); v.IsValid() {
Joe Tsai88bc5a72018-11-05 11:42:22 -080085 pk := ms.keyConv.PBValueOf(k).MapKey()
86 pv := ms.valConv.PBValueOf(v)
87 if !f(pk, pv) {
88 return
89 }
90 }
91 }
92}
Joe Tsaiba0ef9a2018-11-29 14:54:05 -080093func (ms mapReflect) ProtoUnwrap() interface{} {
Joe Tsai6cf80c42018-12-01 04:57:09 -080094 return ms.v.Interface()
Joe Tsai88bc5a72018-11-05 11:42:22 -080095}
96func (ms mapReflect) ProtoMutable() {}