(name string, data interface{}, val reflect.Value)
| 1220 | } |
| 1221 | |
| 1222 | func (d *Decoder) decodeStruct(name string, data interface{}, val reflect.Value) error { |
| 1223 | dataVal := reflect.Indirect(reflect.ValueOf(data)) |
| 1224 | |
| 1225 | // If the type of the value to write to and the data match directly, |
| 1226 | // then we just set it directly instead of recursing into the structure. |
| 1227 | if dataVal.Type() == val.Type() { |
| 1228 | val.Set(dataVal) |
| 1229 | return nil |
| 1230 | } |
| 1231 | |
| 1232 | dataValKind := dataVal.Kind() |
| 1233 | switch dataValKind { |
| 1234 | case reflect.Map: |
| 1235 | return d.decodeStructFromMap(name, dataVal, val) |
| 1236 | |
| 1237 | case reflect.Struct: |
| 1238 | // Not the most efficient way to do this but we can optimize later if |
| 1239 | // we want to. To convert from struct to struct we go to map first |
| 1240 | // as an intermediary. |
| 1241 | |
| 1242 | // Make a new map to hold our result |
| 1243 | mapType := reflect.TypeOf((map[string]interface{})(nil)) |
| 1244 | mval := reflect.MakeMap(mapType) |
| 1245 | |
| 1246 | // Creating a pointer to a map so that other methods can completely |
| 1247 | // overwrite the map if need be (looking at you decodeMapFromMap). The |
| 1248 | // indirection allows the underlying map to be settable (CanSet() == true) |
| 1249 | // where as reflect.MakeMap returns an unsettable map. |
| 1250 | addrVal := reflect.New(mval.Type()) |
| 1251 | |
| 1252 | reflect.Indirect(addrVal).Set(mval) |
| 1253 | if err := d.decodeMapFromStruct(name, dataVal, reflect.Indirect(addrVal), mval); err != nil { |
| 1254 | return err |
| 1255 | } |
| 1256 | |
| 1257 | result := d.decodeStructFromMap(name, reflect.Indirect(addrVal), val) |
| 1258 | return result |
| 1259 | |
| 1260 | default: |
| 1261 | return fmt.Errorf("'%s' expected a map, got '%s'", name, dataVal.Kind()) |
| 1262 | } |
| 1263 | } |
| 1264 | |
| 1265 | func (d *Decoder) decodeStructFromMap(name string, dataVal, val reflect.Value) error { |
| 1266 | dataValType := dataVal.Type() |
no test coverage detected