1package parseutil 2 3import ( 4 "encoding/json" 5 "errors" 6 "fmt" 7 "strconv" 8 "strings" 9 "time" 10 11 "github.com/hashicorp/errwrap" 12 sockaddr "github.com/hashicorp/go-sockaddr" 13 "github.com/hashicorp/vault/sdk/helper/strutil" 14 "github.com/mitchellh/mapstructure" 15) 16 17func ParseDurationSecond(in interface{}) (time.Duration, error) { 18 var dur time.Duration 19 jsonIn, ok := in.(json.Number) 20 if ok { 21 in = jsonIn.String() 22 } 23 switch inp := in.(type) { 24 case nil: 25 // return default of zero 26 case string: 27 if inp == "" { 28 return dur, nil 29 } 30 var err error 31 // Look for a suffix otherwise its a plain second value 32 if strings.HasSuffix(inp, "s") || strings.HasSuffix(inp, "m") || strings.HasSuffix(inp, "h") || strings.HasSuffix(inp, "ms") { 33 dur, err = time.ParseDuration(inp) 34 if err != nil { 35 return dur, err 36 } 37 } else { 38 // Plain integer 39 secs, err := strconv.ParseInt(inp, 10, 64) 40 if err != nil { 41 return dur, err 42 } 43 dur = time.Duration(secs) * time.Second 44 } 45 case int: 46 dur = time.Duration(inp) * time.Second 47 case int32: 48 dur = time.Duration(inp) * time.Second 49 case int64: 50 dur = time.Duration(inp) * time.Second 51 case uint: 52 dur = time.Duration(inp) * time.Second 53 case uint32: 54 dur = time.Duration(inp) * time.Second 55 case uint64: 56 dur = time.Duration(inp) * time.Second 57 case float32: 58 dur = time.Duration(inp) * time.Second 59 case float64: 60 dur = time.Duration(inp) * time.Second 61 case time.Duration: 62 dur = inp 63 default: 64 return 0, errors.New("could not parse duration from input") 65 } 66 67 return dur, nil 68} 69 70func ParseInt(in interface{}) (int64, error) { 71 var ret int64 72 jsonIn, ok := in.(json.Number) 73 if ok { 74 in = jsonIn.String() 75 } 76 switch in.(type) { 77 case string: 78 inp := in.(string) 79 if inp == "" { 80 return 0, nil 81 } 82 var err error 83 left, err := strconv.ParseInt(inp, 10, 64) 84 if err != nil { 85 return ret, err 86 } 87 ret = left 88 case int: 89 ret = int64(in.(int)) 90 case int32: 91 ret = int64(in.(int32)) 92 case int64: 93 ret = in.(int64) 94 case uint: 95 ret = int64(in.(uint)) 96 case uint32: 97 ret = int64(in.(uint32)) 98 case uint64: 99 ret = int64(in.(uint64)) 100 default: 101 return 0, errors.New("could not parse value from input") 102 } 103 104 return ret, nil 105} 106 107func ParseBool(in interface{}) (bool, error) { 108 var result bool 109 if err := mapstructure.WeakDecode(in, &result); err != nil { 110 return false, err 111 } 112 return result, nil 113} 114 115func ParseCommaStringSlice(in interface{}) ([]string, error) { 116 rawString, ok := in.(string) 117 if ok && rawString == "" { 118 return []string{}, nil 119 } 120 var result []string 121 config := &mapstructure.DecoderConfig{ 122 Result: &result, 123 WeaklyTypedInput: true, 124 DecodeHook: mapstructure.StringToSliceHookFunc(","), 125 } 126 decoder, err := mapstructure.NewDecoder(config) 127 if err != nil { 128 return nil, err 129 } 130 if err := decoder.Decode(in); err != nil { 131 return nil, err 132 } 133 return strutil.TrimStrings(result), nil 134} 135 136func ParseAddrs(addrs interface{}) ([]*sockaddr.SockAddrMarshaler, error) { 137 out := make([]*sockaddr.SockAddrMarshaler, 0) 138 stringAddrs := make([]string, 0) 139 140 switch addrs.(type) { 141 case string: 142 stringAddrs = strutil.ParseArbitraryStringSlice(addrs.(string), ",") 143 if len(stringAddrs) == 0 { 144 return nil, fmt.Errorf("unable to parse addresses from %v", addrs) 145 } 146 147 case []string: 148 stringAddrs = addrs.([]string) 149 150 case []interface{}: 151 for _, v := range addrs.([]interface{}) { 152 stringAddr, ok := v.(string) 153 if !ok { 154 return nil, fmt.Errorf("error parsing %v as string", v) 155 } 156 stringAddrs = append(stringAddrs, stringAddr) 157 } 158 159 default: 160 return nil, fmt.Errorf("unknown address input type %T", addrs) 161 } 162 163 for _, addr := range stringAddrs { 164 sa, err := sockaddr.NewSockAddr(addr) 165 if err != nil { 166 return nil, errwrap.Wrapf(fmt.Sprintf("error parsing address %q: {{err}}", addr), err) 167 } 168 out = append(out, &sockaddr.SockAddrMarshaler{ 169 SockAddr: sa, 170 }) 171 } 172 173 return out, nil 174} 175