github.com/Big-big-orange/protoreflect@v0.0.0-20240408141420-285cedfdf6a4/dynamic/maps_1.12.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  // With Go 1.12 and above, we can use reflect.Value.MapRange to iterate
    13  // over maps more efficiently than using reflect.Value.MapKeys.
    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
    21  		return true
    22  	}
    23  
    24  	iter := a.MapRange()
    25  	for iter.Next() {
    26  		k := iter.Key()
    27  		av := iter.Value()
    28  		bv := b.MapIndex(k)
    29  		if !bv.IsValid() {
    30  			return false
    31  		}
    32  		if !fieldsEqual(av.Interface(), bv.Interface()) {
    33  			return false
    34  		}
    35  	}
    36  	return true
    37  }
    38  
    39  func validFieldValueForMapField(fd *desc.FieldDescriptor, val reflect.Value) (interface{}, error) {
    40  	// make a defensive copy while we check the contents
    41  	// (also converts to map[interface{}]interface{} if it's some other type)
    42  	keyField := fd.GetMessageType().GetFields()[0]
    43  	valField := fd.GetMessageType().GetFields()[1]
    44  	m := map[interface{}]interface{}{}
    45  	iter := val.MapRange()
    46  	for iter.Next() {
    47  		k := iter.Key()
    48  		if k.Kind() == reflect.Interface {
    49  			// unwrap it
    50  			k = reflect.ValueOf(k.Interface())
    51  		}
    52  		kk, err := validElementFieldValueForRv(keyField, k, false)
    53  		if err != nil {
    54  			return nil, err
    55  		}
    56  		v := iter.Value()
    57  		if v.Kind() == reflect.Interface {
    58  			// unwrap it
    59  			v = reflect.ValueOf(v.Interface())
    60  		}
    61  		vv, err := validElementFieldValueForRv(valField, v, true)
    62  		if err != nil {
    63  			return nil, err
    64  		}
    65  		m[kk] = vv
    66  	}
    67  	return m, nil
    68  }
    69  
    70  func canConvertMap(src reflect.Value, target reflect.Type) bool {
    71  	kt := target.Key()
    72  	vt := target.Elem()
    73  	iter := src.MapRange()
    74  	for iter.Next() {
    75  		if !canConvert(iter.Key(), kt) {
    76  			return false
    77  		}
    78  		if !canConvert(iter.Value(), vt) {
    79  			return false
    80  		}
    81  	}
    82  	return true
    83  }
    84  
    85  func mergeMapVal(src, target reflect.Value, targetType reflect.Type, deterministic bool) error {
    86  	tkt := targetType.Key()
    87  	tvt := targetType.Elem()
    88  	iter := src.MapRange()
    89  	for iter.Next() {
    90  		k := iter.Key()
    91  		v := iter.Value()
    92  		skt := k.Type()
    93  		svt := v.Type()
    94  		var nk, nv reflect.Value
    95  		if tkt == skt {
    96  			nk = k
    97  		} else if tkt.Kind() == reflect.Ptr && tkt.Elem() == skt {
    98  			nk = k.Addr()
    99  		} else {
   100  			nk = reflect.New(tkt).Elem()
   101  			if err := mergeVal(k, nk, deterministic); err != nil {
   102  				return err
   103  			}
   104  		}
   105  		if tvt == svt {
   106  			nv = v
   107  		} else if tvt.Kind() == reflect.Ptr && tvt.Elem() == svt {
   108  			nv = v.Addr()
   109  		} else {
   110  			nv = reflect.New(tvt).Elem()
   111  			if err := mergeVal(v, nv, deterministic); err != nil {
   112  				return err
   113  			}
   114  		}
   115  		if target.IsNil() {
   116  			target.Set(reflect.MakeMap(targetType))
   117  		}
   118  		target.SetMapIndex(nk, nv)
   119  	}
   120  	return nil
   121  }
   122  
   123  func mergeMapField(m *Message, fd *desc.FieldDescriptor, rv reflect.Value) error {
   124  	iter := rv.MapRange()
   125  	for iter.Next() {
   126  		k := iter.Key()
   127  		v := iter.Value()
   128  		if k.Kind() == reflect.Interface && !k.IsNil() {
   129  			k = k.Elem()
   130  		}
   131  		if v.Kind() == reflect.Interface && !v.IsNil() {
   132  			v = v.Elem()
   133  		}
   134  		if err := m.putMapField(fd, k.Interface(), v.Interface()); err != nil {
   135  			return err
   136  		}
   137  	}
   138  	return nil
   139  }