github.com/artisanhe/tools@v1.0.1-0.20210607022958-19a8fef2eb04/courier/swagger/gen/openapi_common.go (about) 1 package gen 2 3 import ( 4 "fmt" 5 "reflect" 6 "regexp" 7 "strconv" 8 "strings" 9 10 "github.com/go-courier/oas" 11 "github.com/go-courier/ptr" 12 ) 13 14 var ( 15 rxValidate = regexp.MustCompile(`^@([^\[\(\{]+)([\[\(\{])([^\}^\]^\)]+)([\}\]\)])$`) 16 ) 17 18 func BindValidateFromValidateTagString(schema *oas.Schema, validate string) { 19 commonValidations := getCommonValidations(validate) 20 bindSchemaWithValidations(schema, commonValidations) 21 schema.AddExtension(XTagValidate, validate) 22 } 23 24 func getCommonValidations(validateTag string) (commonValidations oas.SchemaValidation) { 25 var matched = rxValidate.FindAllStringSubmatch(validateTag, -1) 26 27 // "@int[1,2]", "int", "[", "1,2", "]" 28 if len(matched) > 0 && len(matched[0]) == 5 { 29 tpe := matched[0][1] 30 startBracket := matched[0][2] 31 endBracket := matched[0][4] 32 values := strings.Split(matched[0][3], ",") 33 34 if startBracket != "{" && endBracket != "}" { 35 switch tpe { 36 case "byte", "int", "int8", "int16", "int32", "int64", "rune", "uint", "uint8", "uint16", "uint32", "uint64", "uintptr", "float32", "float64": 37 if len(values) > 0 { 38 if val, err := strconv.ParseFloat(values[0], 64); err == nil { 39 commonValidations.Minimum = &val 40 commonValidations.ExclusiveMinimum = (startBracket == "(") 41 } 42 } 43 if len(values) > 1 { 44 if val, err := strconv.ParseFloat(values[1], 64); err == nil { 45 commonValidations.Maximum = &val 46 commonValidations.ExclusiveMaximum = (endBracket == ")") 47 } 48 } 49 case "string": 50 if len(values) > 0 { 51 if val, err := strconv.ParseInt(values[0], 10, 64); err == nil { 52 commonValidations.MinLength = ptr.Uint64(uint64(val)) 53 } 54 } 55 if len(values) > 1 { 56 if val, err := strconv.ParseInt(values[1], 10, 64); err == nil { 57 commonValidations.MaxLength = ptr.Uint64(uint64(val)) 58 } 59 } 60 } 61 } else { 62 enums := make([]interface{}, 0) 63 64 for _, value := range values { 65 if tpe != "string" { 66 if val, err := strconv.ParseInt(value, 10, 64); err == nil { 67 enums = append(enums, val) 68 } 69 } else { 70 enums = append(enums, value) 71 } 72 } 73 74 commonValidations.Enum = enums 75 } 76 } 77 78 return 79 } 80 81 func bindSchemaWithValidations(schema *oas.Schema, schemaValidation oas.SchemaValidation) { 82 schema.SchemaValidation = schemaValidation 83 84 // for partial enum 85 if len(schema.Enum) != 0 && len(schemaValidation.Enum) != 0 { 86 var enums []interface{} 87 88 for _, enumValueOrIndex := range schemaValidation.Enum { 89 switch reflect.TypeOf(enumValueOrIndex).Name() { 90 case "string": 91 if enumContainsValue(schema.Enum, enumValueOrIndex) { 92 enums = append(enums, enumValueOrIndex) 93 } else if enumValueOrIndex != "" { 94 panic(fmt.Errorf("%s is not value of %s", enumValueOrIndex, schema.Enum)) 95 } 96 default: 97 if idx, ok := enumValueOrIndex.(int); ok { 98 if schema.Enum[idx] != nil { 99 enums = append(enums, schema.Enum[idx]) 100 } else if idx != 0 { 101 panic(fmt.Errorf("%s is out-range of %s", enumValueOrIndex, schema.Enum)) 102 } 103 } 104 105 } 106 } 107 108 schema.Enum = enums 109 } 110 } 111 112 func enumContainsValue(enum []interface{}, value interface{}) bool { 113 var isContains = false 114 115 for _, enumValue := range enum { 116 if enumValue == value { 117 isContains = true 118 } 119 } 120 121 return isContains 122 }