This repository has been archived by the owner on Nov 30, 2023. It is now read-only.
/
variable.go
89 lines (72 loc) · 2.44 KB
/
variable.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
package rule
import (
"strings"
)
// variable encodes a variable for interpolation, eg. ${foo.bar.baz}, or a
// segment of one, e.g. ${foo.bar} of ${foo.bar.baz}
type variable struct {
segment string // e.g. "bar" from ${foo.bar.baz}
segmentName string // e.g. "foo.bar" from ${foo.bar.baz}
fullName string // e.g. "foo.bar.baz" from ${foo.bar.baz}
}
// VariableResolver resolves a variable (a string of form "${foo.bar.baz}"), and returns
// a list of values
type VariableResolver interface {
Resolve(varString string) ([]string, error)
}
// VariablePinner is a variable resolver that can pin variables to specific values
type VariablePinner interface {
VariableResolver
Pin(variable, value string) VariablePinner // return a VariablePinner that pins a variable to the given value
}
type passThroughResolver struct{}
func (passThroughResolver) Resolve(varString string) ([]string, error) {
return []string{varString}, nil
}
// IsVariable determines if a string is a variable (e.g. of the form '${foo.bar.baz}')
func IsVariable(text string) bool {
return strings.HasPrefix(text, "${") &&
strings.HasSuffix(text, "}")
}
// toVariable creates a Variable from a string like '${foo.bar.baz}' (dollar sign and braces required)
func toVariable(text string) (variable, bool) {
if !IsVariable(text) {
return variable{}, false
}
return variable{
fullName: strings.TrimRight(strings.TrimLeft(text, "${"), "}"),
}, true
}
// shift is used for producing a segment of a variable, e.g. Shift() of ${foo.bar.baz},
// is ${foo}. Shift() of that ${foo} is ${foo.bar}, and Shift() of ${foo.bar} is ${foo.bar.baz}
func (v variable) shift() (variable, bool) {
remaining := strings.TrimLeft(strings.TrimPrefix(v.fullName, v.segmentName), ".")
// no more variable segments
if remaining == "" {
return v, false
}
shifted := variable{
fullName: v.fullName,
}
if v.segment == "" {
shifted.segment = strings.Split(v.fullName, ".")[0]
shifted.segmentName = shifted.segment
} else {
parts := strings.Split(remaining, ".")
shifted.segment = parts[0]
shifted.segmentName = strings.Join([]string{v.segmentName, parts[0]}, ".")
}
return shifted, true
}
func (v variable) prev() variable {
prev := variable{
fullName: v.fullName,
}
if v.segment == "" {
return prev
}
prev.segmentName = strings.Trim(strings.TrimSuffix(v.segmentName, v.segment), ".")
segments := strings.Split(prev.segmentName, ".")
prev.segment = segments[len(segments)-1]
return prev
}