github.com/bakjos/protoreflect@v1.9.2/dynamic/maps_1.11.go (about)

     1  //+build !go1.12
     2  
     3  package dynamic
     4  
     5  import (
     6  	"github.com/bakjos/protoreflect/desc"
     7  	"reflect"
     8  )
     9  
    10  // Pre-Go-1.12, we must use reflect.Value.MapKeys to reflectively
    11  // iterate a map. (We can be more efficient in Go 1.12 and up...)
    12  
    13  func mapsEqual(a, b reflect.Value) bool {
    14  	if a.Len() != b.Len() {
    15  		return false
    16  	}
    17  	if a.Len() == 0 && b.Len() == 0 {
    18  		// Optimize the case where maps are frequently empty because MapKeys()
    19  		// function allocates heavily.
    20  		return true
    21  	}
    22  
    23  	for _, k := range a.MapKeys() {
    24  		av := a.MapIndex(k)
    25  		bv := b.MapIndex(k)
    26  		if !bv.IsValid() {
    27  			return false
    28  		}
    29  		if !fieldsEqual(av.Interface(), bv.Interface()) {
    30  			return false
    31  		}
    32  	}
    33  	return true
    34  }
    35  
    36  func validFieldValueForMapField(fd *desc.FieldDescriptor, val reflect.Value) (interface{}, error) {
    37  	// make a defensive copy while we check the contents
    38  	// (also converts to map[interface{}]interface{} if it's some other type)
    39  	keyField := fd.GetMessageType().GetFields()[0]
    40  	valField := fd.GetMessageType().GetFields()[1]
    41  	m := map[interface{}]interface{}{}
    42  	for _, k := range val.MapKeys() {
    43  		if k.Kind() == reflect.Interface {
    44  			// unwrap it
    45  			k = reflect.ValueOf(k.Interface())
    46  		}
    47  		kk, err := validElementFieldValueForRv(keyField, k, false)
    48  		if err != nil {
    49  			return nil, err
    50  		}
    51  		v := val.MapIndex(k)
    52  		if v.Kind() == reflect.Interface {
    53  			// unwrap it
    54  			v = reflect.ValueOf(v.Interface())
    55  		}
    56  		vv, err := validElementFieldValueForRv(valField, v, true)
    57  		if err != nil {
    58  			return nil, err
    59  		}
    60  		m[kk] = vv
    61  	}
    62  	return m, nil
    63  }
    64  
    65  func canConvertMap(src reflect.Value, target reflect.Type) bool {
    66  	kt := target.Key()
    67  	vt := target.Elem()
    68  	for _, k := range src.MapKeys() {
    69  		if !canConvert(k, kt) {
    70  			return false
    71  		}
    72  		if !canConvert(src.MapIndex(k), vt) {
    73  			return false
    74  		}
    75  	}
    76  	return true
    77  }
    78  
    79  func mergeMapVal(src, target reflect.Value, targetType reflect.Type, deterministic bool) error {
    80  	tkt := targetType.Key()
    81  	tvt := targetType.Elem()
    82  	for _, k := range src.MapKeys() {
    83  		v := src.MapIndex(k)
    84  		skt := k.Type()
    85  		svt := v.Type()
    86  		var nk, nv reflect.Value
    87  		if tkt == skt {
    88  			nk = k
    89  		} else if tkt.Kind() == reflect.Ptr && tkt.Elem() == skt {
    90  			nk = k.Addr()
    91  		} else {
    92  			nk = reflect.New(tkt).Elem()
    93  			if err := mergeVal(k, nk, deterministic); err != nil {
    94  				return err
    95  			}
    96  		}
    97  		if tvt == svt {
    98  			nv = v
    99  		} else if tvt.Kind() == reflect.Ptr && tvt.Elem() == svt {
   100  			nv = v.Addr()
   101  		} else {
   102  			nv = reflect.New(tvt).Elem()
   103  			if err := mergeVal(v, nv, deterministic); err != nil {
   104  				return err
   105  			}
   106  		}
   107  		if target.IsNil() {
   108  			target.Set(reflect.MakeMap(targetType))
   109  		}
   110  		target.SetMapIndex(nk, nv)
   111  	}
   112  	return nil
   113  }
   114  
   115  func mergeMapField(m *Message, fd *desc.FieldDescriptor, rv reflect.Value) error {
   116  	for _, k := range rv.MapKeys() {
   117  		if k.Kind() == reflect.Interface && !k.IsNil() {
   118  			k = k.Elem()
   119  		}
   120  		v := rv.MapIndex(k)
   121  		if v.Kind() == reflect.Interface && !v.IsNil() {
   122  			v = v.Elem()
   123  		}
   124  		if err := m.putMapField(fd, k.Interface(), v.Interface()); err != nil {
   125  			return err
   126  		}
   127  	}
   128  	return nil
   129  }