1// Copyright © 2014 Steve Francia <spf@spf13.com>. 2// 3// Use of this source code is governed by an MIT-style 4// license that can be found in the LICENSE file. 5 6package cast 7 8import ( 9 "fmt" 10 "html/template" 11 "reflect" 12 "strconv" 13 "strings" 14 "time" 15) 16 17// ToTimeE casts an empty interface to time.Time. 18func ToTimeE(i interface{}) (tim time.Time, err error) { 19 i = indirect(i) 20 21 switch v := i.(type) { 22 case time.Time: 23 return v, nil 24 case string: 25 d, e := StringToDate(v) 26 if e == nil { 27 return d, nil 28 } 29 return time.Time{}, fmt.Errorf("Could not parse Date/Time format: %v\n", e) 30 case int: 31 return time.Unix(int64(v), 0), nil 32 case int32: 33 return time.Unix(int64(v), 0), nil 34 case int64: 35 return time.Unix(v, 0), nil 36 default: 37 return time.Time{}, fmt.Errorf("Unable to Cast %#v to Time\n", i) 38 } 39} 40 41// ToDurationE casts an empty interface to time.Duration. 42func ToDurationE(i interface{}) (d time.Duration, err error) { 43 i = indirect(i) 44 45 switch s := i.(type) { 46 case time.Duration: 47 return s, nil 48 case int64, int32, int16, int8, int: 49 d = time.Duration(ToInt64(s)) 50 return 51 case float32, float64: 52 d = time.Duration(ToFloat64(s)) 53 return 54 case string: 55 if strings.ContainsAny(s, "nsuµmh") { 56 d, err = time.ParseDuration(s) 57 } else { 58 d, err = time.ParseDuration(s + "ns") 59 } 60 return 61 default: 62 err = fmt.Errorf("Unable to Cast %#v to Duration\n", i) 63 return 64 } 65} 66 67// ToBoolE casts an empty interface to a bool. 68func ToBoolE(i interface{}) (bool, error) { 69 70 i = indirect(i) 71 72 switch b := i.(type) { 73 case bool: 74 return b, nil 75 case nil: 76 return false, nil 77 case int: 78 if i.(int) != 0 { 79 return true, nil 80 } 81 return false, nil 82 case string: 83 return strconv.ParseBool(i.(string)) 84 default: 85 return false, fmt.Errorf("Unable to Cast %#v to bool", i) 86 } 87} 88 89// ToFloat64E casts an empty interface to a float64. 90func ToFloat64E(i interface{}) (float64, error) { 91 i = indirect(i) 92 93 switch s := i.(type) { 94 case float64: 95 return s, nil 96 case float32: 97 return float64(s), nil 98 case int64: 99 return float64(s), nil 100 case int32: 101 return float64(s), nil 102 case int16: 103 return float64(s), nil 104 case int8: 105 return float64(s), nil 106 case int: 107 return float64(s), nil 108 case string: 109 v, err := strconv.ParseFloat(s, 64) 110 if err == nil { 111 return float64(v), nil 112 } 113 return 0.0, fmt.Errorf("Unable to Cast %#v to float", i) 114 default: 115 return 0.0, fmt.Errorf("Unable to Cast %#v to float", i) 116 } 117} 118 119// ToInt64E casts an empty interface to an int64. 120func ToInt64E(i interface{}) (int64, error) { 121 i = indirect(i) 122 123 switch s := i.(type) { 124 case int64: 125 return s, nil 126 case int: 127 return int64(s), nil 128 case int32: 129 return int64(s), nil 130 case int16: 131 return int64(s), nil 132 case int8: 133 return int64(s), nil 134 case string: 135 v, err := strconv.ParseInt(s, 0, 0) 136 if err == nil { 137 return v, nil 138 } 139 return 0, fmt.Errorf("Unable to Cast %#v to int64", i) 140 case float64: 141 return int64(s), nil 142 case bool: 143 if bool(s) { 144 return int64(1), nil 145 } 146 return int64(0), nil 147 case nil: 148 return int64(0), nil 149 default: 150 return int64(0), fmt.Errorf("Unable to Cast %#v to int64", i) 151 } 152} 153 154// ToIntE casts an empty interface to an int. 155func ToIntE(i interface{}) (int, error) { 156 i = indirect(i) 157 158 switch s := i.(type) { 159 case int: 160 return s, nil 161 case int64: 162 return int(s), nil 163 case int32: 164 return int(s), nil 165 case int16: 166 return int(s), nil 167 case int8: 168 return int(s), nil 169 case string: 170 v, err := strconv.ParseInt(s, 0, 0) 171 if err == nil { 172 return int(v), nil 173 } 174 return 0, fmt.Errorf("Unable to Cast %#v to int", i) 175 case float64: 176 return int(s), nil 177 case bool: 178 if bool(s) { 179 return 1, nil 180 } 181 return 0, nil 182 case nil: 183 return 0, nil 184 default: 185 return 0, fmt.Errorf("Unable to Cast %#v to int", i) 186 } 187} 188 189// From html/template/content.go 190// Copyright 2011 The Go Authors. All rights reserved. 191// indirect returns the value, after dereferencing as many times 192// as necessary to reach the base type (or nil). 193func indirect(a interface{}) interface{} { 194 if a == nil { 195 return nil 196 } 197 if t := reflect.TypeOf(a); t.Kind() != reflect.Ptr { 198 // Avoid creating a reflect.Value if it's not a pointer. 199 return a 200 } 201 v := reflect.ValueOf(a) 202 for v.Kind() == reflect.Ptr && !v.IsNil() { 203 v = v.Elem() 204 } 205 return v.Interface() 206} 207 208// From html/template/content.go 209// Copyright 2011 The Go Authors. All rights reserved. 210// indirectToStringerOrError returns the value, after dereferencing as many times 211// as necessary to reach the base type (or nil) or an implementation of fmt.Stringer 212// or error, 213func indirectToStringerOrError(a interface{}) interface{} { 214 if a == nil { 215 return nil 216 } 217 218 var errorType = reflect.TypeOf((*error)(nil)).Elem() 219 var fmtStringerType = reflect.TypeOf((*fmt.Stringer)(nil)).Elem() 220 221 v := reflect.ValueOf(a) 222 for !v.Type().Implements(fmtStringerType) && !v.Type().Implements(errorType) && v.Kind() == reflect.Ptr && !v.IsNil() { 223 v = v.Elem() 224 } 225 return v.Interface() 226} 227 228// ToStringE casts an empty interface to a string. 229func ToStringE(i interface{}) (string, error) { 230 i = indirectToStringerOrError(i) 231 232 switch s := i.(type) { 233 case string: 234 return s, nil 235 case bool: 236 return strconv.FormatBool(s), nil 237 case float64: 238 return strconv.FormatFloat(i.(float64), 'f', -1, 64), nil 239 case int64: 240 return strconv.FormatInt(i.(int64), 10), nil 241 case int: 242 return strconv.FormatInt(int64(i.(int)), 10), nil 243 case []byte: 244 return string(s), nil 245 case template.HTML: 246 return string(s), nil 247 case template.URL: 248 return string(s), nil 249 case template.JS: 250 return string(s), nil 251 case template.CSS: 252 return string(s), nil 253 case template.HTMLAttr: 254 return string(s), nil 255 case nil: 256 return "", nil 257 case fmt.Stringer: 258 return s.String(), nil 259 case error: 260 return s.Error(), nil 261 default: 262 return "", fmt.Errorf("Unable to Cast %#v to string", i) 263 } 264} 265 266// ToStringMapStringE casts an empty interface to a map[string]string. 267func ToStringMapStringE(i interface{}) (map[string]string, error) { 268 269 var m = map[string]string{} 270 271 switch v := i.(type) { 272 case map[string]string: 273 return v, nil 274 case map[string]interface{}: 275 for k, val := range v { 276 m[ToString(k)] = ToString(val) 277 } 278 return m, nil 279 case map[interface{}]string: 280 for k, val := range v { 281 m[ToString(k)] = ToString(val) 282 } 283 return m, nil 284 case map[interface{}]interface{}: 285 for k, val := range v { 286 m[ToString(k)] = ToString(val) 287 } 288 return m, nil 289 default: 290 return m, fmt.Errorf("Unable to Cast %#v to map[string]string", i) 291 } 292} 293 294// ToStringMapStringSliceE casts an empty interface to a map[string][]string. 295func ToStringMapStringSliceE(i interface{}) (map[string][]string, error) { 296 297 var m = map[string][]string{} 298 299 switch v := i.(type) { 300 case map[string][]string: 301 return v, nil 302 case map[string][]interface{}: 303 for k, val := range v { 304 m[ToString(k)] = ToStringSlice(val) 305 } 306 return m, nil 307 case map[string]string: 308 for k, val := range v { 309 m[ToString(k)] = []string{val} 310 } 311 case map[string]interface{}: 312 for k, val := range v { 313 switch vt := val.(type) { 314 case []interface{}: 315 m[ToString(k)] = ToStringSlice(vt) 316 case []string: 317 m[ToString(k)] = vt 318 default: 319 m[ToString(k)] = []string{ToString(val)} 320 } 321 } 322 return m, nil 323 case map[interface{}][]string: 324 for k, val := range v { 325 m[ToString(k)] = ToStringSlice(val) 326 } 327 return m, nil 328 case map[interface{}]string: 329 for k, val := range v { 330 m[ToString(k)] = ToStringSlice(val) 331 } 332 return m, nil 333 case map[interface{}][]interface{}: 334 for k, val := range v { 335 m[ToString(k)] = ToStringSlice(val) 336 } 337 return m, nil 338 case map[interface{}]interface{}: 339 for k, val := range v { 340 key, err := ToStringE(k) 341 if err != nil { 342 return m, fmt.Errorf("Unable to Cast %#v to map[string][]string", i) 343 } 344 value, err := ToStringSliceE(val) 345 if err != nil { 346 return m, fmt.Errorf("Unable to Cast %#v to map[string][]string", i) 347 } 348 m[key] = value 349 } 350 default: 351 return m, fmt.Errorf("Unable to Cast %#v to map[string][]string", i) 352 } 353 return m, nil 354} 355 356// ToStringMapBoolE casts an empty interface to a map[string]bool. 357func ToStringMapBoolE(i interface{}) (map[string]bool, error) { 358 359 var m = map[string]bool{} 360 361 switch v := i.(type) { 362 case map[interface{}]interface{}: 363 for k, val := range v { 364 m[ToString(k)] = ToBool(val) 365 } 366 return m, nil 367 case map[string]interface{}: 368 for k, val := range v { 369 m[ToString(k)] = ToBool(val) 370 } 371 return m, nil 372 case map[string]bool: 373 return v, nil 374 default: 375 return m, fmt.Errorf("Unable to Cast %#v to map[string]bool", i) 376 } 377} 378 379// ToStringMapE casts an empty interface to a map[string]interface{}. 380func ToStringMapE(i interface{}) (map[string]interface{}, error) { 381 382 var m = map[string]interface{}{} 383 384 switch v := i.(type) { 385 case map[interface{}]interface{}: 386 for k, val := range v { 387 m[ToString(k)] = val 388 } 389 return m, nil 390 case map[string]interface{}: 391 return v, nil 392 default: 393 return m, fmt.Errorf("Unable to Cast %#v to map[string]interface{}", i) 394 } 395} 396 397// ToSliceE casts an empty interface to a []interface{}. 398func ToSliceE(i interface{}) ([]interface{}, error) { 399 400 var s []interface{} 401 402 switch v := i.(type) { 403 case []interface{}: 404 for _, u := range v { 405 s = append(s, u) 406 } 407 return s, nil 408 case []map[string]interface{}: 409 for _, u := range v { 410 s = append(s, u) 411 } 412 return s, nil 413 default: 414 return s, fmt.Errorf("Unable to Cast %#v of type %v to []interface{}", i, reflect.TypeOf(i)) 415 } 416} 417 418// ToBoolSliceE casts an empty interface to a []bool. 419func ToBoolSliceE(i interface{}) ([]bool, error) { 420 421 if i == nil { 422 return []bool{}, fmt.Errorf("Unable to Cast %#v to []bool", i) 423 } 424 425 switch v := i.(type) { 426 case []bool: 427 return v, nil 428 } 429 430 kind := reflect.TypeOf(i).Kind() 431 switch kind { 432 case reflect.Slice, reflect.Array: 433 s := reflect.ValueOf(i) 434 a := make([]bool, s.Len()) 435 for j := 0; j < s.Len(); j++ { 436 val, err := ToBoolE(s.Index(j).Interface()) 437 if err != nil { 438 return []bool{}, fmt.Errorf("Unable to Cast %#v to []bool", i) 439 } 440 a[j] = val 441 } 442 return a, nil 443 default: 444 return []bool{}, fmt.Errorf("Unable to Cast %#v to []bool", i) 445 } 446} 447 448// ToStringSliceE casts an empty interface to a []string. 449func ToStringSliceE(i interface{}) ([]string, error) { 450 451 var a []string 452 453 switch v := i.(type) { 454 case []interface{}: 455 for _, u := range v { 456 a = append(a, ToString(u)) 457 } 458 return a, nil 459 case []string: 460 return v, nil 461 case string: 462 return strings.Fields(v), nil 463 case interface{}: 464 str, err := ToStringE(v) 465 if err != nil { 466 return a, fmt.Errorf("Unable to Cast %#v to []string", i) 467 } 468 return []string{str}, nil 469 default: 470 return a, fmt.Errorf("Unable to Cast %#v to []string", i) 471 } 472} 473 474// ToIntSliceE casts an empty interface to a []int. 475func ToIntSliceE(i interface{}) ([]int, error) { 476 477 if i == nil { 478 return []int{}, fmt.Errorf("Unable to Cast %#v to []int", i) 479 } 480 481 switch v := i.(type) { 482 case []int: 483 return v, nil 484 } 485 486 kind := reflect.TypeOf(i).Kind() 487 switch kind { 488 case reflect.Slice, reflect.Array: 489 s := reflect.ValueOf(i) 490 a := make([]int, s.Len()) 491 for j := 0; j < s.Len(); j++ { 492 val, err := ToIntE(s.Index(j).Interface()) 493 if err != nil { 494 return []int{}, fmt.Errorf("Unable to Cast %#v to []int", i) 495 } 496 a[j] = val 497 } 498 return a, nil 499 default: 500 return []int{}, fmt.Errorf("Unable to Cast %#v to []int", i) 501 } 502} 503 504// StringToDate casts an empty interface to a time.Time. 505func StringToDate(s string) (time.Time, error) { 506 return parseDateWith(s, []string{ 507 time.RFC3339, 508 "2006-01-02T15:04:05", // iso8601 without timezone 509 time.RFC1123Z, 510 time.RFC1123, 511 time.RFC822Z, 512 time.RFC822, 513 time.ANSIC, 514 time.UnixDate, 515 time.RubyDate, 516 "2006-01-02 15:04:05Z07:00", 517 "02 Jan 06 15:04 MST", 518 "2006-01-02", 519 "02 Jan 2006", 520 "2006-01-02 15:04:05 -07:00", 521 "2006-01-02 15:04:05 -0700", 522 "2006-01-02 15:04:05", 523 }) 524} 525 526func parseDateWith(s string, dates []string) (d time.Time, e error) { 527 for _, dateType := range dates { 528 if d, e = time.Parse(dateType, s); e == nil { 529 return 530 } 531 } 532 return d, fmt.Errorf("Unable to parse date: %s", s) 533} 534