map.go 2.1 KB

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