1package funk 2 3import ( 4 "fmt" 5 "reflect" 6) 7 8func equal(expectedOrPredicate interface{}, optionalIsMap ...bool) func(keyValueIfMap, actualValue reflect.Value) bool { 9 isMap := append(optionalIsMap, false)[0] 10 11 if IsFunction(expectedOrPredicate) { 12 inTypes := []reflect.Type{nil}; if isMap { 13 inTypes = append(inTypes, nil) 14 } 15 16 if !IsPredicate(expectedOrPredicate, inTypes...) { 17 panic(fmt.Sprintf("Predicate function must have %d parameter and must return boolean", len(inTypes))) 18 } 19 20 predicateValue := reflect.ValueOf(expectedOrPredicate) 21 22 return func(keyValueIfMap, actualValue reflect.Value) bool { 23 24 if isMap && !keyValueIfMap.Type().ConvertibleTo(predicateValue.Type().In(0)) { 25 panic("Given key is not compatible with type of parameter for the predicate.") 26 } 27 28 if (isMap && !actualValue.Type().ConvertibleTo(predicateValue.Type().In(1))) || 29 (!isMap && !actualValue.Type().ConvertibleTo(predicateValue.Type().In(0))) { 30 panic("Given value is not compatible with type of parameter for the predicate.") 31 } 32 33 args := []reflect.Value{actualValue} 34 if isMap { 35 args = append([]reflect.Value{keyValueIfMap}, args...) 36 } 37 38 return predicateValue.Call(args)[0].Bool() 39 } 40 } 41 42 expected := expectedOrPredicate 43 44 return func(keyValueIfMap, actualValue reflect.Value) bool { 45 if isMap { 46 actualValue = keyValueIfMap 47 } 48 49 if expected == nil || actualValue.IsZero() { 50 return actualValue.Interface() == expected 51 } 52 53 return reflect.DeepEqual(actualValue.Interface(), expected) 54 } 55} 56 57func sliceElem(rtype reflect.Type) reflect.Type { 58 for { 59 if rtype.Kind() != reflect.Slice && rtype.Kind() != reflect.Array { 60 return rtype 61 } 62 63 rtype = rtype.Elem() 64 } 65} 66 67func redirectValue(value reflect.Value) reflect.Value { 68 for { 69 if !value.IsValid() || (value.Kind() != reflect.Ptr && value.Kind() != reflect.Interface) { 70 return value 71 } 72 73 res := value.Elem() 74 75 // Test for a circular type. 76 if res.Kind() == reflect.Ptr && value.Kind() == reflect.Ptr && value.Pointer() == res.Pointer() { 77 return value 78 } 79 80 if !res.IsValid() && value.Kind() == reflect.Ptr { 81 return reflect.Zero(value.Type().Elem()) 82 } 83 84 value = res 85 } 86} 87 88func makeSlice(value reflect.Value, values ...int) reflect.Value { 89 sliceType := sliceElem(value.Type()) 90 91 size := value.Len() 92 cap := size 93 94 if len(values) > 0 { 95 size = values[0] 96 } 97 98 if len(values) > 1 { 99 cap = values[1] 100 } 101 102 return reflect.MakeSlice(reflect.SliceOf(sliceType), size, cap) 103} 104