niki/vendor/github.com/swaggo/swag/const.go

568 lines
13 KiB
Go

package swag
import (
"go/ast"
"go/token"
"reflect"
"strconv"
"strings"
"unicode/utf8"
)
// ConstVariable a model to record a const variable
type ConstVariable struct {
Name *ast.Ident
Type ast.Expr
Value interface{}
Comment *ast.CommentGroup
File *ast.File
Pkg *PackageDefinitions
}
var escapedChars = map[uint8]uint8{
'n': '\n',
'r': '\r',
't': '\t',
'v': '\v',
'\\': '\\',
'"': '"',
}
// EvaluateEscapedChar parse escaped character
func EvaluateEscapedChar(text string) rune {
if len(text) == 1 {
return rune(text[0])
}
if len(text) == 2 && text[0] == '\\' {
return rune(escapedChars[text[1]])
}
if len(text) == 6 && text[0:2] == "\\u" {
n, err := strconv.ParseInt(text[2:], 16, 32)
if err == nil {
return rune(n)
}
}
return 0
}
// EvaluateEscapedString parse escaped characters in string
func EvaluateEscapedString(text string) string {
if !strings.ContainsRune(text, '\\') {
return text
}
result := make([]byte, 0, len(text))
for i := 0; i < len(text); i++ {
if text[i] == '\\' {
i++
if text[i] == 'u' {
i++
char, err := strconv.ParseInt(text[i:i+4], 16, 32)
if err == nil {
result = utf8.AppendRune(result, rune(char))
}
i += 3
} else if c, ok := escapedChars[text[i]]; ok {
result = append(result, c)
}
} else {
result = append(result, text[i])
}
}
return string(result)
}
// EvaluateDataConversion evaluate the type a explicit type conversion
func EvaluateDataConversion(x interface{}, typeName string) interface{} {
switch value := x.(type) {
case int:
switch typeName {
case "int":
return int(value)
case "byte":
return byte(value)
case "int8":
return int8(value)
case "int16":
return int16(value)
case "int32":
return int32(value)
case "int64":
return int64(value)
case "uint":
return uint(value)
case "uint8":
return uint8(value)
case "uint16":
return uint16(value)
case "uint32":
return uint32(value)
case "uint64":
return uint64(value)
case "rune":
return rune(value)
}
case uint:
switch typeName {
case "int":
return int(value)
case "byte":
return byte(value)
case "int8":
return int8(value)
case "int16":
return int16(value)
case "int32":
return int32(value)
case "int64":
return int64(value)
case "uint":
return uint(value)
case "uint8":
return uint8(value)
case "uint16":
return uint16(value)
case "uint32":
return uint32(value)
case "uint64":
return uint64(value)
case "rune":
return rune(value)
}
case int8:
switch typeName {
case "int":
return int(value)
case "byte":
return byte(value)
case "int8":
return int8(value)
case "int16":
return int16(value)
case "int32":
return int32(value)
case "int64":
return int64(value)
case "uint":
return uint(value)
case "uint8":
return uint8(value)
case "uint16":
return uint16(value)
case "uint32":
return uint32(value)
case "uint64":
return uint64(value)
case "rune":
return rune(value)
}
case uint8:
switch typeName {
case "int":
return int(value)
case "byte":
return byte(value)
case "int8":
return int8(value)
case "int16":
return int16(value)
case "int32":
return int32(value)
case "int64":
return int64(value)
case "uint":
return uint(value)
case "uint8":
return uint8(value)
case "uint16":
return uint16(value)
case "uint32":
return uint32(value)
case "uint64":
return uint64(value)
case "rune":
return rune(value)
}
case int16:
switch typeName {
case "int":
return int(value)
case "byte":
return byte(value)
case "int8":
return int8(value)
case "int16":
return int16(value)
case "int32":
return int32(value)
case "int64":
return int64(value)
case "uint":
return uint(value)
case "uint8":
return uint8(value)
case "uint16":
return uint16(value)
case "uint32":
return uint32(value)
case "uint64":
return uint64(value)
case "rune":
return rune(value)
}
case uint16:
switch typeName {
case "int":
return int(value)
case "byte":
return byte(value)
case "int8":
return int8(value)
case "int16":
return int16(value)
case "int32":
return int32(value)
case "int64":
return int64(value)
case "uint":
return uint(value)
case "uint8":
return uint8(value)
case "uint16":
return uint16(value)
case "uint32":
return uint32(value)
case "uint64":
return uint64(value)
case "rune":
return rune(value)
}
case int32:
switch typeName {
case "int":
return int(value)
case "byte":
return byte(value)
case "int8":
return int8(value)
case "int16":
return int16(value)
case "int32":
return int32(value)
case "int64":
return int64(value)
case "uint":
return uint(value)
case "uint8":
return uint8(value)
case "uint16":
return uint16(value)
case "uint32":
return uint32(value)
case "uint64":
return uint64(value)
case "rune":
return rune(value)
case "string":
return string(value)
}
case uint32:
switch typeName {
case "int":
return int(value)
case "byte":
return byte(value)
case "int8":
return int8(value)
case "int16":
return int16(value)
case "int32":
return int32(value)
case "int64":
return int64(value)
case "uint":
return uint(value)
case "uint8":
return uint8(value)
case "uint16":
return uint16(value)
case "uint32":
return uint32(value)
case "uint64":
return uint64(value)
case "rune":
return rune(value)
}
case int64:
switch typeName {
case "int":
return int(value)
case "byte":
return byte(value)
case "int8":
return int8(value)
case "int16":
return int16(value)
case "int32":
return int32(value)
case "int64":
return int64(value)
case "uint":
return uint(value)
case "uint8":
return uint8(value)
case "uint16":
return uint16(value)
case "uint32":
return uint32(value)
case "uint64":
return uint64(value)
case "rune":
return rune(value)
}
case uint64:
switch typeName {
case "int":
return int(value)
case "byte":
return byte(value)
case "int8":
return int8(value)
case "int16":
return int16(value)
case "int32":
return int32(value)
case "int64":
return int64(value)
case "uint":
return uint(value)
case "uint8":
return uint8(value)
case "uint16":
return uint16(value)
case "uint32":
return uint32(value)
case "uint64":
return uint64(value)
case "rune":
return rune(value)
}
case string:
switch typeName {
case "string":
return value
}
}
return nil
}
// EvaluateUnary evaluate the type and value of a unary expression
func EvaluateUnary(x interface{}, operator token.Token, xtype ast.Expr) (interface{}, ast.Expr) {
switch operator {
case token.SUB:
switch value := x.(type) {
case int:
return -value, xtype
case int8:
return -value, xtype
case int16:
return -value, xtype
case int32:
return -value, xtype
case int64:
return -value, xtype
}
case token.XOR:
switch value := x.(type) {
case int:
return ^value, xtype
case int8:
return ^value, xtype
case int16:
return ^value, xtype
case int32:
return ^value, xtype
case int64:
return ^value, xtype
case uint:
return ^value, xtype
case uint8:
return ^value, xtype
case uint16:
return ^value, xtype
case uint32:
return ^value, xtype
case uint64:
return ^value, xtype
}
}
return nil, nil
}
// EvaluateBinary evaluate the type and value of a binary expression
func EvaluateBinary(x, y interface{}, operator token.Token, xtype, ytype ast.Expr) (interface{}, ast.Expr) {
if operator == token.SHR || operator == token.SHL {
var rightOperand uint64
yValue := reflect.ValueOf(y)
if yValue.CanUint() {
rightOperand = yValue.Uint()
} else if yValue.CanInt() {
rightOperand = uint64(yValue.Int())
}
switch operator {
case token.SHL:
switch xValue := x.(type) {
case int:
return xValue << rightOperand, xtype
case int8:
return xValue << rightOperand, xtype
case int16:
return xValue << rightOperand, xtype
case int32:
return xValue << rightOperand, xtype
case int64:
return xValue << rightOperand, xtype
case uint:
return xValue << rightOperand, xtype
case uint8:
return xValue << rightOperand, xtype
case uint16:
return xValue << rightOperand, xtype
case uint32:
return xValue << rightOperand, xtype
case uint64:
return xValue << rightOperand, xtype
}
case token.SHR:
switch xValue := x.(type) {
case int:
return xValue >> rightOperand, xtype
case int8:
return xValue >> rightOperand, xtype
case int16:
return xValue >> rightOperand, xtype
case int32:
return xValue >> rightOperand, xtype
case int64:
return xValue >> rightOperand, xtype
case uint:
return xValue >> rightOperand, xtype
case uint8:
return xValue >> rightOperand, xtype
case uint16:
return xValue >> rightOperand, xtype
case uint32:
return xValue >> rightOperand, xtype
case uint64:
return xValue >> rightOperand, xtype
}
}
return nil, nil
}
evalType := xtype
if evalType == nil {
evalType = ytype
}
xValue := reflect.ValueOf(x)
yValue := reflect.ValueOf(y)
if xValue.Kind() == reflect.String && yValue.Kind() == reflect.String {
return xValue.String() + yValue.String(), evalType
}
var targetValue reflect.Value
if xValue.Kind() != reflect.Int {
targetValue = reflect.New(xValue.Type()).Elem()
} else {
targetValue = reflect.New(yValue.Type()).Elem()
}
switch operator {
case token.ADD:
if xValue.CanInt() && yValue.CanInt() {
targetValue.SetInt(xValue.Int() + yValue.Int())
} else if xValue.CanUint() && yValue.CanUint() {
targetValue.SetUint(xValue.Uint() + yValue.Uint())
} else if xValue.CanInt() && yValue.CanUint() {
targetValue.SetUint(uint64(xValue.Int()) + yValue.Uint())
} else if xValue.CanUint() && yValue.CanInt() {
targetValue.SetUint(xValue.Uint() + uint64(yValue.Int()))
}
case token.SUB:
if xValue.CanInt() && yValue.CanInt() {
targetValue.SetInt(xValue.Int() - yValue.Int())
} else if xValue.CanUint() && yValue.CanUint() {
targetValue.SetUint(xValue.Uint() - yValue.Uint())
} else if xValue.CanInt() && yValue.CanUint() {
targetValue.SetUint(uint64(xValue.Int()) - yValue.Uint())
} else if xValue.CanUint() && yValue.CanInt() {
targetValue.SetUint(xValue.Uint() - uint64(yValue.Int()))
}
case token.MUL:
if xValue.CanInt() && yValue.CanInt() {
targetValue.SetInt(xValue.Int() * yValue.Int())
} else if xValue.CanUint() && yValue.CanUint() {
targetValue.SetUint(xValue.Uint() * yValue.Uint())
} else if xValue.CanInt() && yValue.CanUint() {
targetValue.SetUint(uint64(xValue.Int()) * yValue.Uint())
} else if xValue.CanUint() && yValue.CanInt() {
targetValue.SetUint(xValue.Uint() * uint64(yValue.Int()))
}
case token.QUO:
if xValue.CanInt() && yValue.CanInt() {
targetValue.SetInt(xValue.Int() / yValue.Int())
} else if xValue.CanUint() && yValue.CanUint() {
targetValue.SetUint(xValue.Uint() / yValue.Uint())
} else if xValue.CanInt() && yValue.CanUint() {
targetValue.SetUint(uint64(xValue.Int()) / yValue.Uint())
} else if xValue.CanUint() && yValue.CanInt() {
targetValue.SetUint(xValue.Uint() / uint64(yValue.Int()))
}
case token.REM:
if xValue.CanInt() && yValue.CanInt() {
targetValue.SetInt(xValue.Int() % yValue.Int())
} else if xValue.CanUint() && yValue.CanUint() {
targetValue.SetUint(xValue.Uint() % yValue.Uint())
} else if xValue.CanInt() && yValue.CanUint() {
targetValue.SetUint(uint64(xValue.Int()) % yValue.Uint())
} else if xValue.CanUint() && yValue.CanInt() {
targetValue.SetUint(xValue.Uint() % uint64(yValue.Int()))
}
case token.AND:
if xValue.CanInt() && yValue.CanInt() {
targetValue.SetInt(xValue.Int() & yValue.Int())
} else if xValue.CanUint() && yValue.CanUint() {
targetValue.SetUint(xValue.Uint() & yValue.Uint())
} else if xValue.CanInt() && yValue.CanUint() {
targetValue.SetUint(uint64(xValue.Int()) & yValue.Uint())
} else if xValue.CanUint() && yValue.CanInt() {
targetValue.SetUint(xValue.Uint() & uint64(yValue.Int()))
}
case token.OR:
if xValue.CanInt() && yValue.CanInt() {
targetValue.SetInt(xValue.Int() | yValue.Int())
} else if xValue.CanUint() && yValue.CanUint() {
targetValue.SetUint(xValue.Uint() | yValue.Uint())
} else if xValue.CanInt() && yValue.CanUint() {
targetValue.SetUint(uint64(xValue.Int()) | yValue.Uint())
} else if xValue.CanUint() && yValue.CanInt() {
targetValue.SetUint(xValue.Uint() | uint64(yValue.Int()))
}
case token.XOR:
if xValue.CanInt() && yValue.CanInt() {
targetValue.SetInt(xValue.Int() ^ yValue.Int())
} else if xValue.CanUint() && yValue.CanUint() {
targetValue.SetUint(xValue.Uint() ^ yValue.Uint())
} else if xValue.CanInt() && yValue.CanUint() {
targetValue.SetUint(uint64(xValue.Int()) ^ yValue.Uint())
} else if xValue.CanUint() && yValue.CanInt() {
targetValue.SetUint(xValue.Uint() ^ uint64(yValue.Int()))
}
}
return targetValue.Interface(), evalType
}