123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171 |
- package core
- import (
- "fmt"
- "reflect"
- "strconv"
- "strings"
- "time"
- "github.com/mattn/anko/env"
- )
- // ImportToX adds all the toX to the env given
- func ImportToX(e *env.Env) {
- e.Define("toBool", func(v interface{}) bool {
- rv := reflect.ValueOf(v)
- if !rv.IsValid() {
- return false
- }
- nt := reflect.TypeOf(true)
- if rv.Type().ConvertibleTo(nt) {
- return rv.Convert(nt).Bool()
- }
- if rv.Type().ConvertibleTo(reflect.TypeOf(1.0)) && rv.Convert(reflect.TypeOf(1.0)).Float() > 0.0 {
- return true
- }
- if rv.Kind() == reflect.String {
- s := strings.ToLower(v.(string))
- if s == "y" || s == "yes" {
- return true
- }
- b, err := strconv.ParseBool(s)
- if err == nil {
- return b
- }
- }
- return false
- })
- e.Define("toString", func(v interface{}) string {
- if b, ok := v.([]byte); ok {
- return string(b)
- }
- return fmt.Sprint(v)
- })
- e.Define("toInt", func(v interface{}) int64 {
- rv := reflect.ValueOf(v)
- if !rv.IsValid() {
- return 0
- }
- nt := reflect.TypeOf(1)
- if rv.Type().ConvertibleTo(nt) {
- return rv.Convert(nt).Int()
- }
- if rv.Kind() == reflect.String {
- i, err := strconv.ParseInt(v.(string), 10, 64)
- if err == nil {
- return i
- }
- f, err := strconv.ParseFloat(v.(string), 64)
- if err == nil {
- return int64(f)
- }
- }
- if rv.Kind() == reflect.Bool {
- if v.(bool) {
- return 1
- }
- }
- return 0
- })
- e.Define("toFloat", func(v interface{}) float64 {
- rv := reflect.ValueOf(v)
- if !rv.IsValid() {
- return 0
- }
- nt := reflect.TypeOf(1.0)
- if rv.Type().ConvertibleTo(nt) {
- return rv.Convert(nt).Float()
- }
- if rv.Kind() == reflect.String {
- f, err := strconv.ParseFloat(v.(string), 64)
- if err == nil {
- return f
- }
- }
- if rv.Kind() == reflect.Bool {
- if v.(bool) {
- return 1.0
- }
- }
- return 0.0
- })
- e.Define("toChar", func(s rune) string {
- return string(s)
- })
- e.Define("toRune", func(s string) rune {
- if len(s) == 0 {
- return 0
- }
- return []rune(s)[0]
- })
- e.Define("toBoolSlice", func(v []interface{}) []bool {
- var result []bool
- toSlice(v, &result)
- return result
- })
- e.Define("toStringSlice", func(v []interface{}) []string {
- var result []string
- toSlice(v, &result)
- return result
- })
- e.Define("toIntSlice", func(v []interface{}) []int64 {
- var result []int64
- toSlice(v, &result)
- return result
- })
- e.Define("toFloatSlice", func(v []interface{}) []float64 {
- var result []float64
- toSlice(v, &result)
- return result
- })
- e.Define("toByteSlice", func(s string) []byte {
- return []byte(s)
- })
- e.Define("toRuneSlice", func(s string) []rune {
- return []rune(s)
- })
- e.Define("toDuration", func(v int64) time.Duration {
- return time.Duration(v)
- })
- }
- // toSlice takes in a "generic" slice and converts and copies
- // it's elements into the typed slice pointed at by ptr.
- // Note that this is a costly operation.
- func toSlice(from []interface{}, ptr interface{}) {
- // Value of the pointer to the target
- obj := reflect.Indirect(reflect.ValueOf(ptr))
- // We can't just convert from interface{} to whatever the target is (diff memory layout),
- // so we need to create a New slice of the proper type and copy the values individually
- t := reflect.TypeOf(ptr).Elem()
- tt := t.Elem()
- slice := reflect.MakeSlice(t, len(from), len(from))
- // Copying the data, val is an addressable Pointer of the actual target type
- val := reflect.Indirect(reflect.New(tt))
- for i := 0; i < len(from); i++ {
- v := reflect.ValueOf(from[i])
- if v.IsValid() && v.Type().ConvertibleTo(tt) {
- val.Set(v.Convert(tt))
- } else {
- val.Set(reflect.Zero(tt))
- }
- slice.Index(i).Set(val)
- }
- // Ok now assign our slice to the target pointer
- obj.Set(slice)
- }
|