-
Notifications
You must be signed in to change notification settings - Fork 364
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Replace FillDefaults -> WithDefaults. Let WithDefaults() and Merge() return interface{} types. After go generics are available, these will be typed. Introduce generated getters for all fields of expconf structs, which are correctly typed according to whether a defaulted object will have fields defaulted or not.
- Loading branch information
1 parent
cfa00f7
commit 8e07c66
Showing
26 changed files
with
1,128 additions
and
1,262 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2816,4 +2816,3 @@ | |
""" | ||
), | ||
} | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
package schemas | ||
|
||
import ( | ||
"fmt" | ||
"reflect" | ||
) | ||
|
||
// cpy is for deep copying, but it will only work on "nice" objects, which should include our | ||
// schema objects. Useful to other reflect code. | ||
func cpy(v reflect.Value) reflect.Value { | ||
// fmt.Printf("cpy(%T)\n", v.Interface()) | ||
var out reflect.Value | ||
|
||
switch v.Kind() { | ||
case reflect.Ptr: | ||
if v.IsZero() { | ||
return v | ||
} | ||
out = reflect.New(v.Elem().Type()) | ||
out.Elem().Set(cpy(v.Elem())) | ||
|
||
case reflect.Interface: | ||
if v.IsZero() { | ||
return v.Elem() | ||
} | ||
out = cpy(v.Elem()) | ||
|
||
case reflect.Struct: | ||
out = reflect.New(v.Type()).Elem() | ||
// Recurse into each field of the struct. | ||
for i := 0; i < v.NumField(); i++ { | ||
out.Field(i).Set(cpy(v.Field(i))) | ||
} | ||
|
||
case reflect.Map: | ||
typ := reflect.MapOf(v.Type().Key(), v.Type().Elem()) | ||
if v.IsZero() { | ||
// unallocated map | ||
out = reflect.Zero(typ) | ||
} else { | ||
out = reflect.MakeMap(typ) | ||
// Recurse into each key of the map. | ||
for _, key := range v.MapKeys() { | ||
val := v.MapIndex(key) | ||
out.SetMapIndex(key, cpy(val)) | ||
} | ||
} | ||
|
||
case reflect.Slice: | ||
typ := reflect.SliceOf(v.Type().Elem()) | ||
if v.IsZero() { | ||
// unallocated slice | ||
out = reflect.Zero(typ) | ||
} else { | ||
out = reflect.MakeSlice(typ, 0, v.Len()) | ||
// Recurse into each element of the slice. | ||
for i := 0; i < v.Len(); i++ { | ||
val := v.Index(i) | ||
out = reflect.Append(out, cpy(val)) | ||
} | ||
} | ||
|
||
// Assert that none of the "complex" kinds are present. | ||
case reflect.Array, | ||
reflect.Chan, | ||
reflect.Func, | ||
reflect.UnsafePointer: | ||
panic(fmt.Sprintf("unable to cpy %T of kind %v", v.Interface(), v.Kind())) | ||
|
||
default: | ||
// Simple types like string or int can be passed directly. | ||
return v | ||
} | ||
|
||
return out | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,82 @@ | ||
package schemas | ||
|
||
import ( | ||
"reflect" | ||
"testing" | ||
|
||
"gotest.tools/assert" | ||
) | ||
|
||
// Copy is the non-reflect version of copy, but mostly the reflect version is called from other | ||
// reflect code, so it's defined here in test code. | ||
func Copy(src interface{}) interface{} { | ||
return cpy(reflect.ValueOf(src)).Interface() | ||
} | ||
|
||
func TestCopyAllocatedSlice(t *testing.T) { | ||
src := []string{} | ||
obj := Copy(src).([]string) | ||
assert.DeepEqual(t, obj, src) | ||
} | ||
|
||
func TestCopyUnallocatedSlice(t *testing.T) { | ||
// Copying an unallocated slice encodes to null. | ||
var src []string | ||
obj := Copy(src).([]string) | ||
assert.DeepEqual(t, obj, src) | ||
} | ||
|
||
func TestCopyAllocatedMap(t *testing.T) { | ||
// Copying an allocated map encodes to []. | ||
src := map[string]string{} | ||
|
||
obj := Copy(src).(map[string]string) | ||
assert.DeepEqual(t, obj, src) | ||
} | ||
|
||
func TestCopyUnallocatedMap(t *testing.T) { | ||
// Copying an unallocated map encodes to null. | ||
var src map[string]string | ||
|
||
obj := Copy(src).(map[string]string) | ||
assert.DeepEqual(t, obj, src) | ||
} | ||
|
||
type A struct { | ||
M map[string]string | ||
S []int | ||
B B | ||
} | ||
|
||
type B struct { | ||
I int | ||
S string | ||
C []C | ||
} | ||
|
||
type C struct { | ||
I int | ||
D map[string]D | ||
} | ||
|
||
type D struct { | ||
I int | ||
S string | ||
} | ||
|
||
func TestCopyNested(t *testing.T) { | ||
src := A{ | ||
M: map[string]string{"eeny": "meeny", "miney": "moe"}, | ||
S: []int{1, 2, 3, 4}, | ||
B: B{ | ||
I: 5, | ||
S: "five", | ||
C: []C{ | ||
{I: 6, D: map[string]D{"one": {I: 1, S: "fish"}, "two": {I: 2, S: "fish"}}}, | ||
{I: 6, D: map[string]D{"red": {I: 3, S: "fish"}, "blue": {I: 4, S: "fish"}}}, | ||
}, | ||
}, | ||
} | ||
obj := Copy(src).(A) | ||
assert.DeepEqual(t, obj, src) | ||
} |
Oops, something went wrong.