Skip to content
This repository was archived by the owner on Jul 22, 2024. It is now read-only.

Commit e0c24fd

Browse files
authored
Merge pull request #25 from vancluever/add-pointer-value-walker
Add PointerValueWalker for walking pointer values
2 parents 3e2c75d + b5b75d0 commit e0c24fd

File tree

2 files changed

+87
-0
lines changed

2 files changed

+87
-0
lines changed

reflectwalk.go

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,13 @@ type PointerWalker interface {
6969
PointerExit(bool) error
7070
}
7171

72+
// PointerValueWalker implementations are notified with the value of
73+
// a particular pointer when a pointer is walked. Pointer is called
74+
// right before PointerEnter.
75+
type PointerValueWalker interface {
76+
Pointer(reflect.Value) error
77+
}
78+
7279
// SkipEntry can be returned from walk functions to skip walking
7380
// the value of this field. This is only valid in the following functions:
7481
//
@@ -130,6 +137,17 @@ func walk(v reflect.Value, w interface{}) (err error) {
130137
}
131138

132139
if pointerV.Kind() == reflect.Ptr {
140+
if pw, ok := w.(PointerValueWalker); ok {
141+
if err = pw.Pointer(pointerV); err != nil {
142+
if err == SkipEntry {
143+
// Skip the rest of this entry but clear the error
144+
return nil
145+
}
146+
147+
return
148+
}
149+
}
150+
133151
pointer = true
134152
v = reflect.Indirect(pointerV)
135153
}

reflectwalk_test.go

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,20 @@ func (t *TestPointerWalker) PointerExit(v bool) error {
4949
return nil
5050
}
5151

52+
type TestPointerValueWalker struct {
53+
skip bool
54+
pointers []reflect.Type
55+
}
56+
57+
func (t *TestPointerValueWalker) Pointer(v reflect.Value) error {
58+
t.pointers = append(t.pointers, v.Type())
59+
if t.skip {
60+
return SkipEntry
61+
}
62+
63+
return nil
64+
}
65+
5266
type TestPrimitiveWalker struct {
5367
Value reflect.Value
5468
}
@@ -482,6 +496,61 @@ func TestWalk_PointerPointer(t *testing.T) {
482496
}
483497
}
484498

499+
func TestWalk_PointerValue(t *testing.T) {
500+
type X struct{}
501+
type T struct {
502+
x *X
503+
}
504+
505+
v := &T{x: &X{}}
506+
507+
expected := []reflect.Type{
508+
reflect.TypeOf(v),
509+
reflect.TypeOf(v.x),
510+
}
511+
512+
w := new(TestPointerValueWalker)
513+
err := Walk(v, w)
514+
if err != nil {
515+
t.Fatal(err)
516+
}
517+
518+
if !reflect.DeepEqual(expected, w.pointers) {
519+
t.Fatalf("unexpected pointer order or length (expected len=%d, actual len=%d)", len(expected), len(w.pointers))
520+
}
521+
}
522+
523+
func TestWalk_PointerValueSkip(t *testing.T) {
524+
type T struct{}
525+
type W struct {
526+
TestPointerValueWalker
527+
TestPointerWalker
528+
}
529+
530+
v := &T{}
531+
w := &W{
532+
TestPointerValueWalker: TestPointerValueWalker{
533+
skip: true,
534+
},
535+
}
536+
err := Walk(v, w)
537+
if err != nil {
538+
t.Fatal(err)
539+
}
540+
541+
if len(w.TestPointerValueWalker.pointers) != 1 {
542+
t.Errorf("expected len=1, got len=%d", len(w.TestPointerValueWalker.pointers))
543+
}
544+
545+
if w.TestPointerValueWalker.pointers[0] != reflect.TypeOf(v) {
546+
t.Error("pointer value type mismatch")
547+
}
548+
549+
if w.enters != 0 || w.exits != 0 {
550+
t.Error("should have been skipped and have zero enters or exits")
551+
}
552+
}
553+
485554
func TestWalk_Slice(t *testing.T) {
486555
w := new(TestSliceWalker)
487556

0 commit comments

Comments
 (0)