github.com/System-Glitch/goyave/v2@v2.10.3-0.20200819142921-51011e75d504/validation/arrays.go (about) 1 package validation 2 3 import ( 4 "fmt" 5 "net" 6 "net/url" 7 "reflect" 8 "time" 9 10 "github.com/System-Glitch/goyave/v2/helper" 11 "github.com/google/uuid" 12 ) 13 14 // createArray create a slice of the same type as the given type. 15 func createArray(dataType string, length int) reflect.Value { 16 var arr reflect.Value 17 switch dataType { 18 case "string": 19 newArray := make([]string, 0, length) 20 arr = reflect.ValueOf(&newArray).Elem() 21 case "numeric": 22 newArray := make([]float64, 0, length) 23 arr = reflect.ValueOf(&newArray).Elem() 24 case "integer": 25 newArray := make([]int, 0, length) 26 arr = reflect.ValueOf(&newArray).Elem() 27 case "timezone": 28 newArray := make([]*time.Location, 0, length) 29 arr = reflect.ValueOf(&newArray).Elem() 30 case "ip", "ipv4", "ipv6": 31 newArray := make([]net.IP, 0, length) 32 arr = reflect.ValueOf(&newArray).Elem() 33 case "json": 34 newArray := make([]interface{}, 0, length) 35 arr = reflect.ValueOf(&newArray).Elem() 36 case "url": 37 newArray := make([]*url.URL, 0, length) 38 arr = reflect.ValueOf(&newArray).Elem() 39 case "uuid": 40 newArray := make([]uuid.UUID, 0, length) 41 arr = reflect.ValueOf(&newArray).Elem() 42 case "bool": 43 newArray := make([]bool, 0, length) 44 arr = reflect.ValueOf(&newArray).Elem() 45 case "date": 46 newArray := make([]time.Time, 0, length) 47 arr = reflect.ValueOf(&newArray).Elem() 48 } 49 return arr 50 } 51 52 func validateArray(field string, value interface{}, parameters []string, form map[string]interface{}) bool { 53 if GetFieldType(value) == "array" { 54 55 if len(parameters) == 0 { 56 return true 57 } 58 59 if parameters[0] == "array" { 60 panic("Cannot use array type for array validation. Use \">array\" instead") 61 } 62 63 if !validationRules[parameters[0]].IsType { 64 panic(fmt.Sprintf("Rule %s is not converting, cannot use it for array validation", parameters[0])) 65 } 66 67 list := reflect.ValueOf(value) 68 length := list.Len() 69 arr := createArray(parameters[0], length) 70 71 params := parameters[1:] 72 73 for i := 0; i < length; i++ { 74 val := list.Index(i).Interface() 75 tmpData := map[string]interface{}{field: val} 76 if !validationRules[parameters[0]].Function(field, val, params, tmpData) { 77 return false 78 } 79 arr.Set(reflect.Append(arr, reflect.ValueOf(tmpData[field]))) 80 } 81 82 form[field] = arr.Interface() 83 return true 84 } 85 86 return false 87 } 88 89 func validateDistinct(field string, value interface{}, parameters []string, form map[string]interface{}) bool { 90 if GetFieldType(value) != "array" { 91 return false // Can't validate if not an array 92 } 93 94 found := []interface{}{} 95 list := reflect.ValueOf(value) 96 for i := 0; i < list.Len(); i++ { 97 v := list.Index(i).Interface() 98 if helper.Contains(found, v) { 99 return false 100 } 101 found = append(found, v) 102 } 103 104 return true 105 } 106 107 func checkInNumeric(parameters []string, value interface{}) bool { 108 for _, v := range parameters { 109 floatVal, _ := helper.ToFloat64(value) 110 other, err := helper.ToFloat64(v) 111 if err == nil && floatVal == other { // Compare only values of the same type 112 return true 113 } 114 } 115 return false 116 } 117 118 func validateIn(field string, value interface{}, parameters []string, form map[string]interface{}) bool { 119 switch GetFieldType(value) { 120 case "numeric": 121 return checkInNumeric(parameters, value) 122 case "string": 123 return helper.Contains(parameters, value) 124 } 125 // Don't check arrays and files 126 return false 127 } 128 129 func validateNotIn(field string, value interface{}, parameters []string, form map[string]interface{}) bool { 130 switch GetFieldType(value) { 131 case "numeric": 132 return !checkInNumeric(parameters, value) 133 case "string": 134 return !helper.ContainsStr(parameters, value.(string)) 135 } 136 // Don't check arrays and files 137 return false 138 } 139 140 func validateInArray(field string, value interface{}, parameters []string, form map[string]interface{}) bool { 141 other, exists := form[parameters[0]] 142 if exists && GetFieldType(other) == "array" { 143 return helper.Contains(other, value) 144 } 145 return false 146 } 147 148 func validateNotInArray(field string, value interface{}, parameters []string, form map[string]interface{}) bool { 149 other, exists := form[parameters[0]] 150 if exists && GetFieldType(other) == "array" { 151 return !helper.Contains(other, value) 152 } 153 return false 154 }