-
Notifications
You must be signed in to change notification settings - Fork 97
/
Copy pathpath.go
176 lines (144 loc) · 4.91 KB
/
path.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
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0
package path
import (
"github.com/hashicorp/terraform-plugin-framework/attr"
)
// Path represents exact traversal steps into a schema or schema-based data.
// These steps always start from the root of the schema, which is an object
// with zero or more attributes and blocks.
//
// Use the Root() function to create a Path with an initial AtName() step. Path
// functionality follows a builder pattern, which allows for chaining method
// calls to construct a full path. The available traversal steps after Path
// creation are:
//
// - AtListIndex(): Step into a list at a specific 0-based index
// - AtMapKey(): Step into a map at a specific key
// - AtName(): Step into an attribute or block with a specific name
// - AtSetValue(): Step into a set at a specific attr.Value element
//
// For example, to represent the first list element with a root list attribute
// named "some_attribute":
//
// path.MatchRoot("some_attribute").AtListIndex(0)
//
// Path is used for functionality which must exactly match the underlying
// schema structure and types, such as diagnostics that are intended for a
// specific attribute or working with specific attribute values in a schema
// based data structure such as tfsdk.Config, tfsdk.Plan, or tfsdk.State.
//
// Refer to Expression for situations where relative or wildcard step logic is
// desirable for schema defined functionality, such as attribute validators or
// attribute plan modifiers.
type Path struct {
// steps is the transversals included with the path. In general, operations
// against the path should protect against modification of the original.
steps PathSteps
}
// AtListIndex returns a copied path with a new list index step at the end.
// The returned path is safe to modify without affecting the original.
//
// List indices are 0-based. The first element of a list is 0.
func (p Path) AtListIndex(index int) Path {
copiedPath := p.Copy()
copiedPath.steps.Append(PathStepElementKeyInt(index))
return copiedPath
}
// AtTupleIndex returns a copied path with a new tuple index step at the end.
// The returned path is safe to modify without affecting the original.
//
// Tuple indices are 0-based. The first element of a tuple is 0.
func (p Path) AtTupleIndex(index int) Path {
copiedPath := p.Copy()
copiedPath.steps.Append(PathStepElementKeyInt(index))
return copiedPath
}
// AtMapKey returns a copied path with a new map key step at the end.
// The returned path is safe to modify without affecting the original.
func (p Path) AtMapKey(key string) Path {
copiedPath := p.Copy()
copiedPath.steps.Append(PathStepElementKeyString(key))
return copiedPath
}
// AtName returns a copied path with a new attribute or block name step at the
// end. The returned path is safe to modify without affecting the original.
func (p Path) AtName(name string) Path {
copiedPath := p.Copy()
copiedPath.steps.Append(PathStepAttributeName(name))
return copiedPath
}
// AtSetValue returns a copied path with a new set value step at the end.
// The returned path is safe to modify without affecting the original.
func (p Path) AtSetValue(value attr.Value) Path {
copiedPath := p.Copy()
copiedPath.steps.Append(PathStepElementKeyValue{Value: value})
return copiedPath
}
// Copy returns a duplicate of the path that is safe to modify without
// affecting the original.
func (p Path) Copy() Path {
return Path{
steps: p.Steps(),
}
}
// Equal returns true if the given path is exactly equivalent.
func (p Path) Equal(o Path) bool {
if p.steps == nil && o.steps == nil {
return true
}
if p.steps == nil {
return false
}
if !p.steps.Equal(o.steps) {
return false
}
return true
}
// Expression returns an Expression which exactly matches the Path.
func (p Path) Expression() Expression {
return Expression{
root: true,
steps: p.steps.ExpressionSteps(),
}
}
// ParentPath returns a copy of the path with the last step removed.
//
// If the current path is empty, an empty path is returned.
func (p Path) ParentPath() Path {
if len(p.steps) == 0 {
return Empty()
}
_, remainingSteps := p.steps.Copy().LastStep()
return Path{
steps: remainingSteps,
}
}
// Steps returns a copy of the underlying path steps. Returns an empty
// collection of steps if path is nil.
func (p Path) Steps() PathSteps {
if len(p.steps) == 0 {
return PathSteps{}
}
return p.steps.Copy()
}
// String returns the human-readable representation of the path.
// It is intended for logging and error messages and is not protected by
// compatibility guarantees.
func (p Path) String() string {
return p.steps.String()
}
// Empty creates an empty attribute path. Provider code should use Root.
func Empty() Path {
return Path{
steps: PathSteps{},
}
}
// Root creates an attribute path starting with a PathStepAttributeName.
func Root(rootAttributeName string) Path {
return Path{
steps: PathSteps{
PathStepAttributeName(rootAttributeName),
},
}
}