kaniko/vendor/github.com/otiai10/mint/mquery/mquery.go

73 lines
1.4 KiB
Go

package mquery
import (
"fmt"
"reflect"
"strconv"
"strings"
)
func Query(m interface{}, q string) interface{} {
return query(m, strings.Split(q, "."))
}
func query(m interface{}, qs []string) interface{} {
t := reflect.TypeOf(m)
switch t.Kind() {
case reflect.Map:
return queryMap(m, t, qs)
case reflect.Slice:
return querySlice(m, t, qs)
default:
return m
}
}
func queryMap(m interface{}, t reflect.Type, qs []string) interface{} {
if len(qs) == 0 {
return m
}
val := reflect.ValueOf(m)
if val.IsZero() {
return nil
}
switch t.Key().Kind() {
case reflect.String:
val := reflect.ValueOf(m).MapIndex(reflect.ValueOf(qs[0]))
if !val.IsValid() {
return nil
}
return query(val.Interface(), qs[1:])
case reflect.Int:
i, err := strconv.Atoi(qs[0])
if err != nil {
return fmt.Errorf("cannot access map with keyword: %s: %v", qs[0], err)
}
val := reflect.ValueOf(m).MapIndex(reflect.ValueOf(i))
if !val.IsValid() {
return nil
}
return query(val.Interface(), qs[1:])
}
return nil
}
func querySlice(m interface{}, t reflect.Type, qs []string) interface{} {
if len(qs) == 0 {
return m
}
v := reflect.ValueOf(m)
if v.Len() == 0 {
return nil
}
i, err := strconv.Atoi(qs[0])
if err != nil {
return fmt.Errorf("cannot access slice with keyword: %s: %v", qs[0], err)
}
if v.Len() <= i {
return nil
}
next := v.Index(i).Interface()
return query(next, qs[1:])
}