github.com/Big-big-orange/protoreflect@v0.0.0-20240408141420-285cedfdf6a4/dynamic/maps_1.11.go (about)

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