Skip to content

Commit 26e5da2

Browse files
authored
allow iterating over a fieldpath's ShapeRefs (#250)
Adds a few utility methods to `pkg/fieldpath.Path` to make it easier to inspect associated ShapeRefs at different parts of the path: * `Path.At(int)` returns the path part at the supplied index. * `Path.CopyAt(int)` returns a new Path up to the supplied index. * `Path.ShapeRefAt(*shapeRef, int)` returns a ShapeRef corresponding to the path part at the supplied index. * `Path.IterShapeRefs(*shapeRef)` returns a slice of *ShapeRef that can be used to iterate over the ShapeRefs associated with each of the Path's parts. Signed-off-by: Jay Pipes <[email protected]> By submitting this pull request, I confirm that my contribution is made under the terms of the Apache 2.0 license.
1 parent 285d87b commit 26e5da2

File tree

2 files changed

+83
-0
lines changed

2 files changed

+83
-0
lines changed

pkg/fieldpath/path.go

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,15 @@ func (p *Path) Pop() (part string) {
5555
return part
5656
}
5757

58+
// At returns the part of the Path at the supplied index, or empty string if
59+
// index exceeds boundary.
60+
func (p *Path) At(index int) string {
61+
if index < 0 || len(p.parts) == 0 || index > len(p.parts)-1 {
62+
return ""
63+
}
64+
return p.parts[index]
65+
}
66+
5867
// Front returns the first part of the Path or empty string if the Path has no
5968
// parts.
6069
func (p *Path) Front() string {
@@ -92,6 +101,18 @@ func (p *Path) Copy() *Path {
92101
return &Path{p.parts}
93102
}
94103

104+
// CopyAt returns a new Path that is a copy of this Path up to the supplied
105+
// index.
106+
//
107+
// e.g. given Path $A containing "X.Y", $A.CopyAt(0) would return a new Path
108+
// containing just "X". $A.CopyAt(1) would return a new Path containing "X.Y".
109+
func (p *Path) CopyAt(index int) *Path {
110+
if index < 0 || len(p.parts) == 0 || index > len(p.parts)-1 {
111+
return nil
112+
}
113+
return &Path{p.parts[0 : index+1]}
114+
}
115+
95116
// Empty returns true if there are no parts to the Path
96117
func (p *Path) Empty() bool {
97118
return len(p.parts) == 0
@@ -175,6 +196,36 @@ func (p *Path) ShapeRef(
175196
return compare
176197
}
177198

199+
// ShapeRefAt returns an aws-sdk-go ShapeRef within the supplied ShapeRef that
200+
// matches the Path at the supplied index. Returns nil if no matching ShapeRef
201+
// could be found or index out of bounds.
202+
func (p *Path) ShapeRefAt(
203+
subject *awssdkmodel.ShapeRef,
204+
index int,
205+
) *awssdkmodel.ShapeRef {
206+
if subject == nil || p == nil || len(p.parts) == 0 {
207+
return nil
208+
}
209+
210+
cp := p.CopyAt(index)
211+
if cp == nil {
212+
return nil
213+
}
214+
return cp.ShapeRef(subject)
215+
}
216+
217+
// IterShapeRefs returns a slice of ShapeRef pointers representing each part of
218+
// the path
219+
func (p *Path) IterShapeRefs(
220+
subject *awssdkmodel.ShapeRef,
221+
) []*awssdkmodel.ShapeRef {
222+
res := make([]*awssdkmodel.ShapeRef, len(p.parts))
223+
for idx, _ := range p.parts {
224+
res[idx] = p.ShapeRefAt(subject, idx)
225+
}
226+
return res
227+
}
228+
178229
// memberShapeRef returns the named member ShapeRef of the supplied
179230
// ShapeRef
180231
func memberShapeRef(

pkg/fieldpath/path_test.go

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,14 @@ func TestBasics(t *testing.T) {
3434
require.Equal("Author", pstate.Front())
3535
require.Equal("State", pstate.Back())
3636

37+
require.Equal("Author", pstate.At(0))
38+
require.Equal("Address", pstate.At(1))
39+
require.Equal("State", pstate.At(2))
40+
require.Equal("", pstate.At(3))
41+
42+
pauth := pstate.CopyAt(0)
43+
require.Equal("Author", pauth.String())
44+
3745
last := pstate.Pop()
3846
require.Equal("State", last)
3947
require.Equal("Address", pstate.Back())
@@ -148,6 +156,30 @@ func TestShapeRef(t *testing.T) {
148156
require.Equal("Name", ref.ShapeName)
149157
require.Equal("string", ref.Shape.Type)
150158

159+
p = fieldpath.FromString("Author")
160+
ref = p.ShapeRefAt(authShapeRef, 0)
161+
require.NotNil(ref)
162+
require.Equal("Author", ref.ShapeName)
163+
ref = p.ShapeRefAt(authShapeRef, 1)
164+
require.Nil(ref)
165+
166+
p = fieldpath.FromString("Author.Address")
167+
ref = p.ShapeRefAt(authShapeRef, 0)
168+
require.NotNil(ref)
169+
require.Equal("Author", ref.ShapeName)
170+
ref = p.ShapeRefAt(authShapeRef, 1)
171+
require.NotNil(ref)
172+
require.Equal("Address", ref.ShapeName)
173+
ref = p.ShapeRefAt(authShapeRef, 2)
174+
require.Nil(ref)
175+
176+
for idx, shapeRef := range p.IterShapeRefs(authShapeRef) {
177+
ref = p.ShapeRefAt(authShapeRef, idx)
178+
require.NotNil(shapeRef)
179+
require.NotNil(ref)
180+
require.Equal(ref.ShapeName, shapeRef.ShapeName)
181+
}
182+
151183
// Path needs to match on outer-most shape first before going into member
152184
// refs
153185
p = fieldpath.FromString("Address")

0 commit comments

Comments
 (0)