blob: 9fc7358bb874dba266d710602dea8f16adb6fe62 [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
Damien Neile89e6242019-05-13 23:55:40 -070010 pref "google.golang.org/protobuf/reflect/protoreflect"
Joe Tsai88bc5a72018-11-05 11:42:22 -080011)
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}
Joe Tsai88bc5a72018-11-05 11:42:22 -080065func (ms mapReflect) Range(f func(pref.MapKey, pref.Value) bool) {
Joe Tsai6cf80c42018-12-01 04:57:09 -080066 if ms.v.IsNil() {
67 return
68 }
69 for _, k := range ms.v.Elem().MapKeys() {
70 if v := ms.v.Elem().MapIndex(k); v.IsValid() {
Joe Tsai88bc5a72018-11-05 11:42:22 -080071 pk := ms.keyConv.PBValueOf(k).MapKey()
72 pv := ms.valConv.PBValueOf(v)
73 if !f(pk, pv) {
74 return
75 }
76 }
77 }
78}
Joe Tsai3bc7d6f2019-01-09 02:57:13 -080079func (ms mapReflect) NewMessage() pref.Message {
Joe Tsaib2f66be2019-05-22 00:42:45 -040080 return ms.valConv.NewMessage()
Damien Neil97e7f572018-12-07 14:28:33 -080081}
Joe Tsaiba0ef9a2018-11-29 14:54:05 -080082func (ms mapReflect) ProtoUnwrap() interface{} {
Joe Tsai6cf80c42018-12-01 04:57:09 -080083 return ms.v.Interface()
Joe Tsai88bc5a72018-11-05 11:42:22 -080084}