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