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  }