databricks-cli/libs/dyn/path_string.go

90 lines
1.6 KiB
Go
Raw Normal View History

package dyn
import (
"fmt"
"strconv"
"strings"
)
// MustPathFromString is like NewPathFromString but panics on error.
func MustPathFromString(input string) Path {
p, err := NewPathFromString(input)
if err != nil {
panic(err)
}
return p
}
// NewPathFromString parses a path from a string.
//
// The string must be a sequence of keys and indices separated by dots.
// Indices must be enclosed in square brackets.
// The string may include a leading dot.
//
// Examples:
// - foo.bar
// - foo[1].bar
// - foo.bar[1]
// - foo.bar[1][2]
// - .
func NewPathFromString(input string) (Path, error) {
var path Path
p := input
// Trim leading dot.
if p != "" && p[0] == '.' {
p = p[1:]
}
for p != "" {
// Every component may have a leading dot.
if p != "" && p[0] == '.' {
p = p[1:]
}
if p == "" {
return nil, fmt.Errorf("invalid path: %s", input)
}
if p[0] == '[' {
// Find next ]
i := strings.Index(p, "]")
if i < 0 {
return nil, fmt.Errorf("invalid path: %s", input)
}
// Parse index
j, err := strconv.Atoi(p[1:i])
if err != nil {
return nil, fmt.Errorf("invalid path: %s", input)
}
// Append index
path = append(path, Index(j))
p = p[i+1:]
// The next character must be a . or [
if p != "" && strings.IndexAny(p, ".[") != 0 {
return nil, fmt.Errorf("invalid path: %s", input)
}
} else {
// Find next . or [
i := strings.IndexAny(p, ".[")
if i < 0 {
i = len(p)
}
if i == 0 {
return nil, fmt.Errorf("invalid path: %s", input)
}
// Append key
path = append(path, Key(p[:i]))
p = p[i:]
}
}
return path, nil
}