func ValidSecret(subject string) bool {
	return fullglobOrGlob.MatchString(subject)
}
ValidSecret returns whether the subject is a valid secret name value
package pathexp
import (
	"errors"
	"regexp"
	"sort"
	"strings"
)
const slugstr = `[a-z\d][-_a-z\d]{0,63}`
var (
	slug           = regexp.MustCompile(`^` + slugstr + `$`)
	globRe         = regexp.MustCompile(`^(` + slugstr + `)(\*?)$`)
	fullglobOrGlob = regexp.MustCompile(`(^\*$)|(?:^(` + slugstr + `)(\*?)$)`)
	doubleGlob     = regexp.MustCompile(`^\*\*$`)
)
const (
	orgIdx = iota
	projectIdx
	envIdx
	serviceIdx
	identityIdx
	instanceIdx
)
type PathExp struct {
	Org        literal
	Project    literal
	Envs       segment
	Services   segment
	Identities segment
	Instances  segment
}
type segment interface {
	String() string
	Contains(subject string) bool
	Components() []string
}
type literal string
type glob string
type fullglob struct{}
type alternation []segment
func (l literal) String() string { return string(l) }
func (l literal) Contains(subject string) bool {
	return string(l) == subject
}
func (l literal) Components() []string {
	return []string{string(l)}
}
func (g glob) String() string { return string(g) + "*" }
func (g glob) Contains(subject string) bool {
	return strings.Index(subject, string(g)) == 0
}
func (g glob) Components() []string {
	return []string{string(g)}
}
func GlobContains(value, subject string) bool {
	gl := glob(value)
	return gl.Contains(subject)
}
func (f fullglob) String() string { return "*" }
func (f fullglob) Contains(subject string) bool {
	return true
}
func (f fullglob) Components() []string {
	return []string{"*"}
}
func (a alternation) String() string {
	strs := []string{}
	for _, s := range a {
		strs = append(strs, s.String())
	}
	sort.Strings(strs)
	return "[" + strings.Join(strs, "|") + "]"
}
func (a alternation) Contains(subject string) bool {
	for _, s := range a {
		if s.Contains(subject) {
			return true
		}
	}
	return false
}
func (a alternation) Components() []string {
	out := make([]string, len(a))
	for i, v := range a {
		out[i] = v.String()
	}
	return out
}
func compareSegmentType(a, b segment) int {
	segs := []segment{a, b}
	ranks := make([]int, 2)
	for i, seg := range segs {
		switch seg.(type) {
		case literal:
			ranks[i] = 3
		case glob:
			ranks[i] = 2
		case alternation:
			ranks[i] = 1
		case fullglob:
			ranks[i] = 0
		default:
			panic("Bad type for segment!")
		}
	}
	switch {
	case ranks[0] < ranks[1]:
		return -1
	case ranks[0] > ranks[1]:
		return 1
	default:
		return 0
	}
}
func segmentsEqual(a, b segment) bool {
	switch at := a.(type) {
	case literal:
		if bl, ok := b.(literal); ok {
			return at == bl
		}
		return false
	case glob:
		if bg, ok := b.(glob); ok {
			return at == bg
		}
		return false
	case alternation:
		if ba, ok := b.(alternation); ok {
			if len(at) != len(ba) {
				return false
			}
		LoopA:
			for _, av := range at {
				for _, bv := range ba {
					if segmentsEqual(av, bv) {
						continue LoopA
					}
				}
				return false
			}
			return true
		}
		return false
	case fullglob:
		_, ok := b.(fullglob)
		return ok
	default:
		panic("Bad type for segment!")
	}
}
func New(org, project string, envs, services, identities, instances []string) (*PathExp, error) {
	return newPathexp(org, project, envs, services, identities, instances, true)
}
func NewPartial(org, project string, envs, services, identities, instances []string) (*PathExp, error) {
	return newPathexp(org, project, envs, services, identities, instances, false)
}