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

Commit

Permalink
shallow copying was broken, more detailed test
Browse files Browse the repository at this point in the history
The issue was that our "ignoreDepth" approach wasn't actually working
and reflectwalk would attempt to enter the struct. Instead of going that
route, let's just assign the value directly.
  • Loading branch information
mitchellh committed Feb 2, 2021
1 parent 552f94d commit 1e4d1a1
Show file tree
Hide file tree
Showing 2 changed files with 43 additions and 12 deletions.
27 changes: 15 additions & 12 deletions copystructure.go
Original file line number Diff line number Diff line change
Expand Up @@ -419,26 +419,29 @@ func (w *walker) StructField(f reflect.StructField, v reflect.Value) error {
return reflectwalk.SkipEntry
}

// Push the field onto the stack, we'll handle it when we exit
// the struct field in Exit...
w.valPush(reflect.ValueOf(f))

// If we're shallow copying then push the value as-is onto the stack.
switch f.Tag.Get(tagKey) {
case "shallow":
w.valPush(v)
// If we're shallow copying then assign the value directly to the
// struct and skip the entry.
if v.IsValid() {
s := w.cs[len(w.cs)-1]
sf := reflect.Indirect(s).FieldByName(f.Name)
if sf.CanSet() {
sf.Set(v)
}
}

// set ignore depth one level deeper so we don't ignore the value
// we put on the stack but we do ignore diving into it.
w.ignoreDepth = w.depth + 1
return reflectwalk.SkipEntry

case "ignore":
// Do nothing, we have to pop off our structfield so we undo any
// prior work in this func
w.valPop()
// Do nothing
return reflectwalk.SkipEntry
}

// Push the field onto the stack, we'll handle it when we exit
// the struct field in Exit...
w.valPush(reflect.ValueOf(f))

return nil
}

Expand Down
28 changes: 28 additions & 0 deletions copystructure_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"sync"
"testing"
"time"
"unsafe"
)

func TestCopy_complex(t *testing.T) {
Expand Down Expand Up @@ -245,6 +246,33 @@ func TestCopy_structShallow(t *testing.T) {
}
}

func TestCopy_structShallowWithUnsafe(t *testing.T) {
type nested struct {
v unsafe.Pointer
}

type test struct {
Value string
Value2 *nested `copy:"shallow"`
}

value2 := &nested{}
v := test{Value: "foo", Value2: value2}

result, err := Copy(v)
if err != nil {
t.Fatalf("err: %s", err)
}
if !reflect.DeepEqual(result, v) {
t.Fatalf("bad: %#v", result)
}

vcopy := result.(test)
if vcopy.Value2 != v.Value2 {
t.Fatal("should shallow copy the pointer")
}
}

func TestCopy_structIgnore(t *testing.T) {
type test struct {
Value string
Expand Down

0 comments on commit 1e4d1a1

Please sign in to comment.