github.com/openfga/openfga@v1.5.4-rc1/internal/condition/types/converters.go (about) 1 package types 2 3 import ( 4 "fmt" 5 "math/big" 6 "reflect" 7 "time" 8 ) 9 10 func primitiveTypeConverterFunc[T any](value any) (any, error) { 11 v, ok := value.(T) 12 if !ok { 13 return nil, fmt.Errorf("expected type value '%T', but found '%s'", *new(T), reflect.TypeOf(value)) 14 } 15 16 return v, nil 17 } 18 19 func numericTypeConverterFunc[T int64 | uint64 | float64](value any) (any, error) { 20 v, ok := value.(T) 21 if ok { 22 return v, nil 23 } 24 25 floatValue, ok := value.(float64) 26 bigFloat := big.NewFloat(floatValue) 27 if !ok { 28 stringValue, ok := value.(string) 29 if !ok { 30 return nil, fmt.Errorf("expected type value '%T', but found '%s'", *new(T), reflect.TypeOf(value)) 31 } 32 33 f, _, err := big.ParseFloat(stringValue, 10, 64, 0) 34 if err != nil { 35 return nil, fmt.Errorf("expected a %T value, but found invalid string value '%v'", *new(T), value) 36 } 37 38 bigFloat = f 39 } 40 41 n := *new(T) 42 switch any(n).(type) { 43 case int64: 44 if !bigFloat.IsInt() { 45 return nil, fmt.Errorf("expected an int value, but found numeric value '%s'", bigFloat.String()) 46 } 47 48 numericValue, _ := bigFloat.Int64() 49 return numericValue, nil 50 51 case uint64: 52 if !bigFloat.IsInt() { 53 return nil, fmt.Errorf("expected a uint value, but found numeric value '%s'", bigFloat.String()) 54 } 55 56 numericValue, _ := bigFloat.Int64() 57 if numericValue < 0 { 58 return nil, fmt.Errorf("expected a uint value, but found int64 value '%s'", bigFloat.String()) 59 } 60 return uint64(numericValue), nil 61 62 case float64: 63 numericValue, a := bigFloat.Float64() 64 if a == big.Above || a == big.Below { 65 return nil, fmt.Errorf("number cannot be represented as a float64: %s", bigFloat.String()) 66 } 67 return numericValue, nil 68 69 default: 70 return nil, fmt.Errorf("unsupported numeric type in numerical parameter type conversion: %T", n) 71 } 72 } 73 74 func anyTypeConverterFunc(value any) (any, error) { 75 return value, nil 76 } 77 78 func durationTypeConverterFunc(value any) (any, error) { 79 v, ok := value.(string) 80 if !ok { 81 return nil, fmt.Errorf("expected a duration string, but found: %T '%v'", value, value) 82 } 83 84 d, err := time.ParseDuration(v) 85 if err != nil { 86 return nil, fmt.Errorf("expected a valid duration string, but found: '%v'", value) 87 } 88 89 return d, nil 90 } 91 92 func timestampTypeConverterFunc(value any) (any, error) { 93 v, ok := value.(string) 94 if !ok { 95 return nil, fmt.Errorf("expected RFC 3339 formatted timestamp string, but found: %T '%v'", value, value) 96 } 97 98 d, err := time.Parse(time.RFC3339, v) 99 if err != nil { 100 return nil, fmt.Errorf("expected RFC 3339 formatted timestamp string, but found '%s'", v) 101 } 102 103 return d, nil 104 } 105 106 func ipaddressTypeConverterFunc(value any) (any, error) { 107 ipaddr, ok := value.(IPAddress) 108 if ok { 109 return ipaddr, nil 110 } 111 112 v, ok := value.(string) 113 if !ok { 114 return nil, fmt.Errorf("expected an ipaddress string, but found: %T '%v'", value, value) 115 } 116 117 d, err := ParseIPAddress(v) 118 if err != nil { 119 return nil, fmt.Errorf("expected a well-formed IP address, but found: '%s'", v) 120 } 121 122 return d, nil 123 }