func setValueAt(root, value interface{}, parts []string) (interface{}, error) {
	h, t := ht(parts)
	return setNodeValueAt(root, value, h, t)
}
setValueAt sets the value at the path parts.
package gjp
import (
	"strconv"
	"strings"
	"github.com/tideland/golib/errors"
	"github.com/tideland/golib/stringex"
)
func splitPath(path, separator string) []string {
	return stringex.SplitFilter(path, separator, func(part string) bool {
		return part != ""
	})
}
func isValue(raw interface{}) (interface{}, bool) {
	if raw == nil {
		return raw, true
	}
	_, ook := isObject(raw)
	_, aok := isArray(raw)
	if ook || aok {
		return nil, false
	}
	return raw, true
}
func isObject(raw interface{}) (map[string]interface{}, bool) {
	o, ok := raw.(map[string]interface{})
	return o, ok
}
func isArray(raw interface{}) ([]interface{}, bool) {
	a, ok := raw.([]interface{})
	return a, ok
}
func valueAt(node interface{}, parts []string) (interface{}, error) {
	length := len(parts)
	if length == 0 {
		return node, nil
	}
	head, tail := ht(parts)
	if head == "" {
		return node, nil
	}
	if o, ok := isObject(node); ok {
		field, ok := o[head]
		if !ok {
			return nil, errors.New(ErrInvalidPart, errorMessages, head)
		}
		return valueAt(field, tail)
	}
	if a, ok := isArray(node); ok {
		index, err := strconv.Atoi(head)
		if err != nil || index >= len(a) {
			return nil, errors.Annotate(err, ErrInvalidPart, errorMessages, head)
		}
		return valueAt(a[index], tail)
	}
	return nil, errors.New(ErrPathTooLong, errorMessages)
}