copyExportedFields iterates downward through nested data structures and creates a copy that only contains the exported struct fields.
(expected interface{})
| 84 | // copyExportedFields iterates downward through nested data structures and creates a copy |
| 85 | // that only contains the exported struct fields. |
| 86 | func copyExportedFields(expected interface{}) interface{} { |
| 87 | if isNil(expected) { |
| 88 | return expected |
| 89 | } |
| 90 | |
| 91 | expectedType := reflect.TypeOf(expected) |
| 92 | expectedKind := expectedType.Kind() |
| 93 | expectedValue := reflect.ValueOf(expected) |
| 94 | |
| 95 | switch expectedKind { |
| 96 | case reflect.Struct: |
| 97 | result := reflect.New(expectedType).Elem() |
| 98 | for i := 0; i < expectedType.NumField(); i++ { |
| 99 | field := expectedType.Field(i) |
| 100 | isExported := field.IsExported() |
| 101 | if isExported { |
| 102 | fieldValue := expectedValue.Field(i) |
| 103 | if isNil(fieldValue) || isNil(fieldValue.Interface()) { |
| 104 | continue |
| 105 | } |
| 106 | newValue := copyExportedFields(fieldValue.Interface()) |
| 107 | result.Field(i).Set(reflect.ValueOf(newValue)) |
| 108 | } |
| 109 | } |
| 110 | return result.Interface() |
| 111 | |
| 112 | case reflect.Ptr: |
| 113 | result := reflect.New(expectedType.Elem()) |
| 114 | unexportedRemoved := copyExportedFields(expectedValue.Elem().Interface()) |
| 115 | result.Elem().Set(reflect.ValueOf(unexportedRemoved)) |
| 116 | return result.Interface() |
| 117 | |
| 118 | case reflect.Array, reflect.Slice: |
| 119 | var result reflect.Value |
| 120 | if expectedKind == reflect.Array { |
| 121 | result = reflect.New(reflect.ArrayOf(expectedValue.Len(), expectedType.Elem())).Elem() |
| 122 | } else { |
| 123 | result = reflect.MakeSlice(expectedType, expectedValue.Len(), expectedValue.Len()) |
| 124 | } |
| 125 | for i := 0; i < expectedValue.Len(); i++ { |
| 126 | index := expectedValue.Index(i) |
| 127 | if isNil(index) { |
| 128 | continue |
| 129 | } |
| 130 | unexportedRemoved := copyExportedFields(index.Interface()) |
| 131 | result.Index(i).Set(reflect.ValueOf(unexportedRemoved)) |
| 132 | } |
| 133 | return result.Interface() |
| 134 | |
| 135 | case reflect.Map: |
| 136 | result := reflect.MakeMap(expectedType) |
| 137 | for _, k := range expectedValue.MapKeys() { |
| 138 | index := expectedValue.MapIndex(k) |
| 139 | unexportedRemoved := copyExportedFields(index.Interface()) |
| 140 | result.SetMapIndex(k, reflect.ValueOf(unexportedRemoved)) |
| 141 | } |
| 142 | return result.Interface() |
| 143 |