summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/stretchr/objx/accessors.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/stretchr/objx/accessors.go')
-rw-r--r--vendor/github.com/stretchr/objx/accessors.go178
1 files changed, 118 insertions, 60 deletions
diff --git a/vendor/github.com/stretchr/objx/accessors.go b/vendor/github.com/stretchr/objx/accessors.go
index 78939426d..d95be0ca9 100644
--- a/vendor/github.com/stretchr/objx/accessors.go
+++ b/vendor/github.com/stretchr/objx/accessors.go
@@ -1,22 +1,15 @@
package objx
import (
+ "fmt"
"regexp"
"strconv"
"strings"
)
-const (
- // PathSeparator is the character used to separate the elements
- // of the keypath.
- //
- // For example, `location.address.city`
- PathSeparator string = "."
-
- // arrayAccesRegexString is the regex used to extract the array number
- // from the access path
- arrayAccesRegexString = `^(.+)\[([0-9]+)\]$`
-)
+// arrayAccesRegexString is the regex used to extract the array number
+// from the access path
+const arrayAccesRegexString = `^(.+)\[([0-9]+)\]$`
// arrayAccesRegex is the compiled arrayAccesRegexString
var arrayAccesRegex = regexp.MustCompile(arrayAccesRegexString)
@@ -35,7 +28,7 @@ var arrayAccesRegex = regexp.MustCompile(arrayAccesRegexString)
//
// o.Get("books[1].chapters[2].title")
func (m Map) Get(selector string) *Value {
- rawObj := access(m, selector, nil, false)
+ rawObj := access(m, selector, nil, false, false)
return &Value{data: rawObj}
}
@@ -50,64 +43,129 @@ func (m Map) Get(selector string) *Value {
//
// o.Set("books[1].chapters[2].title","Time to Go")
func (m Map) Set(selector string, value interface{}) Map {
- access(m, selector, value, true)
+ access(m, selector, value, true, false)
return m
}
-// getIndex returns the index, which is hold in s by two braches.
-// It also returns s withour the index part, e.g. name[1] will return (1, name).
-// If no index is found, -1 is returned
-func getIndex(s string) (int, string) {
- arrayMatches := arrayAccesRegex.FindStringSubmatch(s)
- if len(arrayMatches) > 0 {
- // Get the key into the map
- selector := arrayMatches[1]
- // Get the index into the array at the key
- // We know this cannt fail because arrayMatches[2] is an int for sure
- index, _ := strconv.Atoi(arrayMatches[2])
- return index, selector
- }
- return -1, s
-}
-
// access accesses the object using the selector and performs the
// appropriate action.
-func access(current interface{}, selector string, value interface{}, isSet bool) interface{} {
- selSegs := strings.SplitN(selector, PathSeparator, 2)
- thisSel := selSegs[0]
- index := -1
+func access(current, selector, value interface{}, isSet, panics bool) interface{} {
- if strings.Contains(thisSel, "[") {
- index, thisSel = getIndex(thisSel)
- }
+ switch selector.(type) {
+ case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
- if curMap, ok := current.(Map); ok {
- current = map[string]interface{}(curMap)
- }
- // get the object in question
- switch current.(type) {
- case map[string]interface{}:
- curMSI := current.(map[string]interface{})
- if len(selSegs) <= 1 && isSet {
- curMSI[thisSel] = value
- return nil
- }
- current = curMSI[thisSel]
- default:
- current = nil
- }
- // do we need to access the item of an array?
- if index > -1 {
if array, ok := current.([]interface{}); ok {
- if index < len(array) {
- current = array[index]
- } else {
- current = nil
+ index := intFromInterface(selector)
+
+ if index >= len(array) {
+ if panics {
+ panic(fmt.Sprintf("objx: Index %d is out of range. Slice only contains %d items.", index, len(array)))
+ }
+ return nil
}
+
+ return array[index]
}
- }
- if len(selSegs) > 1 {
- current = access(current, selSegs[1], value, isSet)
+
+ return nil
+
+ case string:
+
+ selStr := selector.(string)
+ selSegs := strings.SplitN(selStr, PathSeparator, 2)
+ thisSel := selSegs[0]
+ index := -1
+ var err error
+
+ if strings.Contains(thisSel, "[") {
+ arrayMatches := arrayAccesRegex.FindStringSubmatch(thisSel)
+
+ if len(arrayMatches) > 0 {
+ // Get the key into the map
+ thisSel = arrayMatches[1]
+
+ // Get the index into the array at the key
+ index, err = strconv.Atoi(arrayMatches[2])
+
+ if err != nil {
+ // This should never happen. If it does, something has gone
+ // seriously wrong. Panic.
+ panic("objx: Array index is not an integer. Must use array[int].")
+ }
+ }
+ }
+
+ if curMap, ok := current.(Map); ok {
+ current = map[string]interface{}(curMap)
+ }
+
+ // get the object in question
+ switch current.(type) {
+ case map[string]interface{}:
+ curMSI := current.(map[string]interface{})
+ if len(selSegs) <= 1 && isSet {
+ curMSI[thisSel] = value
+ return nil
+ }
+ current = curMSI[thisSel]
+ default:
+ current = nil
+ }
+
+ if current == nil && panics {
+ panic(fmt.Sprintf("objx: '%v' invalid on object.", selector))
+ }
+
+ // do we need to access the item of an array?
+ if index > -1 {
+ if array, ok := current.([]interface{}); ok {
+ if index < len(array) {
+ current = array[index]
+ } else {
+ if panics {
+ panic(fmt.Sprintf("objx: Index %d is out of range. Slice only contains %d items.", index, len(array)))
+ }
+ current = nil
+ }
+ }
+ }
+
+ if len(selSegs) > 1 {
+ current = access(current, selSegs[1], value, isSet, panics)
+ }
+
}
return current
}
+
+// intFromInterface converts an interface object to the largest
+// representation of an unsigned integer using a type switch and
+// assertions
+func intFromInterface(selector interface{}) int {
+ var value int
+ switch selector.(type) {
+ case int:
+ value = selector.(int)
+ case int8:
+ value = int(selector.(int8))
+ case int16:
+ value = int(selector.(int16))
+ case int32:
+ value = int(selector.(int32))
+ case int64:
+ value = int(selector.(int64))
+ case uint:
+ value = int(selector.(uint))
+ case uint8:
+ value = int(selector.(uint8))
+ case uint16:
+ value = int(selector.(uint16))
+ case uint32:
+ value = int(selector.(uint32))
+ case uint64:
+ value = int(selector.(uint64))
+ default:
+ panic("objx: array access argument is not an integer type (this should never happen)")
+ }
+ return value
+}