map.go 2.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384
  1. // 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. package value
  5. import (
  6. "reflect"
  7. pref "github.com/golang/protobuf/v2/reflect/protoreflect"
  8. )
  9. func MapOf(p interface{}, kc, kv Converter) interface {
  10. pref.Map
  11. Unwrapper
  12. } {
  13. // TODO: Validate that p is a *map[K]V?
  14. rv := reflect.ValueOf(p).Elem()
  15. return mapReflect{rv, kc, kv}
  16. }
  17. type mapReflect struct {
  18. v reflect.Value // addressable map[K]V
  19. keyConv Converter
  20. valConv Converter
  21. }
  22. func (ms mapReflect) Len() int {
  23. return ms.v.Len()
  24. }
  25. func (ms mapReflect) Has(k pref.MapKey) bool {
  26. rk := ms.keyConv.GoValueOf(k.Value())
  27. rv := ms.v.MapIndex(rk)
  28. return rv.IsValid()
  29. }
  30. func (ms mapReflect) Get(k pref.MapKey) pref.Value {
  31. rk := ms.keyConv.GoValueOf(k.Value())
  32. rv := ms.v.MapIndex(rk)
  33. if !rv.IsValid() {
  34. return pref.Value{}
  35. }
  36. return ms.valConv.PBValueOf(rv)
  37. }
  38. func (ms mapReflect) Set(k pref.MapKey, v pref.Value) {
  39. if ms.v.IsNil() {
  40. ms.v.Set(reflect.MakeMap(ms.v.Type()))
  41. }
  42. rk := ms.keyConv.GoValueOf(k.Value())
  43. rv := ms.valConv.GoValueOf(v)
  44. ms.v.SetMapIndex(rk, rv)
  45. }
  46. func (ms mapReflect) Clear(k pref.MapKey) {
  47. rk := ms.keyConv.GoValueOf(k.Value())
  48. ms.v.SetMapIndex(rk, reflect.Value{})
  49. }
  50. func (ms mapReflect) Mutable(k pref.MapKey) pref.Mutable {
  51. // Mutable is only valid for messages and panics for other kinds.
  52. if ms.v.IsNil() {
  53. ms.v.Set(reflect.MakeMap(ms.v.Type()))
  54. }
  55. rk := ms.keyConv.GoValueOf(k.Value())
  56. rv := ms.v.MapIndex(rk)
  57. if !rv.IsValid() {
  58. pv := pref.ValueOf(ms.valConv.MessageType.New().ProtoReflect())
  59. rv = ms.valConv.GoValueOf(pv)
  60. ms.v.SetMapIndex(rk, rv)
  61. }
  62. return ms.valConv.PBValueOf(rv).Message()
  63. }
  64. func (ms mapReflect) Range(f func(pref.MapKey, pref.Value) bool) {
  65. for _, k := range ms.v.MapKeys() {
  66. if v := ms.v.MapIndex(k); v.IsValid() {
  67. pk := ms.keyConv.PBValueOf(k).MapKey()
  68. pv := ms.valConv.PBValueOf(v)
  69. if !f(pk, pv) {
  70. return
  71. }
  72. }
  73. }
  74. }
  75. func (ms mapReflect) ProtoUnwrap() interface{} {
  76. return ms.v.Addr().Interface()
  77. }
  78. func (ms mapReflect) ProtoMutable() {}