Skip to content

Commit 7d12f2a

Browse files
committed
fix edge cases for pathIter, test for pathIter
1 parent 4a4fe33 commit 7d12f2a

File tree

2 files changed

+41
-9
lines changed

2 files changed

+41
-9
lines changed

cache.go

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -45,26 +45,32 @@ func (c *cache) registerConverter(value interface{}, converterFunc Converter) {
4545
// var it pathIter
4646
// for key, ok := it.start(path); ok; key, ok = it.advance() {}
4747
type pathIter struct {
48-
rest string
48+
rest string
49+
lastFound bool
4950
}
5051

5152
// start initializes the iteration, and returns the first key.
5253
func (p *pathIter) start(path string) (string, bool) {
53-
return p.next(path)
54+
// init the iter for the first call to next, so that the first call will either
55+
// cut on "." and return the "before", or it will return path if it does not contain
56+
// ".".
57+
p.rest = path
58+
p.lastFound = true
59+
return p.next()
5460
}
5561

5662
// advance advances the iteration to the next key.
5763
func (p *pathIter) advance() (string, bool) {
58-
return p.next(p.rest)
64+
return p.next()
5965
}
6066

61-
// next should only be used by (*pathIter).start and (*pathIter).advance. it will cut path,
67+
// next should only be used by (*pathIter).start and (*pathIter).advance. it will cut p.rest,
6268
// and return the "before", storing the "after" for the subsequent call.
63-
// if path does not contain "." and is non-empty, it will return (path, true), storing "".
64-
// if path is empty, it will return ("", false). this means the end of iteration.
65-
func (p *pathIter) next(path string) (key string, ok bool) {
66-
key, p.rest, _ = strings.Cut(path, ".")
67-
ok = key != ""
69+
func (p *pathIter) next() (key string, ok bool) {
70+
var found bool
71+
key, p.rest, found = strings.Cut(p.rest, ".")
72+
ok = found || p.lastFound
73+
p.lastFound = found
6874
return key, ok
6975
}
7076

decoder_test.go

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2566,3 +2566,29 @@ func BenchmarkSliceOfStruct(b *testing.B) {
25662566
_ = d.Decode(in, v)
25672567
}
25682568
}
2569+
2570+
func TestPathIter(t *testing.T) {
2571+
testcases := []string{
2572+
"a",
2573+
"a.b",
2574+
".b.",
2575+
".",
2576+
"..",
2577+
"",
2578+
}
2579+
for _, tc := range testcases {
2580+
t.Run(tc, func(t *testing.T) {
2581+
var (
2582+
it pathIter
2583+
split = strings.Split(tc, ".")
2584+
collect = make([]string, 0, len(split))
2585+
)
2586+
for k, ok := it.start(tc); ok; k, ok = it.advance() {
2587+
collect = append(collect, k)
2588+
}
2589+
if !reflect.DeepEqual(split, collect) {
2590+
t.Fatalf("expected: %q | got: %q", split, collect)
2591+
}
2592+
})
2593+
}
2594+
}

0 commit comments

Comments
 (0)