|  | package mapstructure | 
|  |  | 
|  | import ( | 
|  | "encoding/json" | 
|  | "testing" | 
|  | ) | 
|  |  | 
|  | func Benchmark_Decode(b *testing.B) { | 
|  | type Person struct { | 
|  | Name   string | 
|  | Age    int | 
|  | Emails []string | 
|  | Extra  map[string]string | 
|  | } | 
|  |  | 
|  | input := map[string]interface{}{ | 
|  | "name":   "Mitchell", | 
|  | "age":    91, | 
|  | "emails": []string{"one", "two", "three"}, | 
|  | "extra": map[string]string{ | 
|  | "twitter": "mitchellh", | 
|  | }, | 
|  | } | 
|  |  | 
|  | var result Person | 
|  | for i := 0; i < b.N; i++ { | 
|  | Decode(input, &result) | 
|  | } | 
|  | } | 
|  |  | 
|  | // decodeViaJSON takes the map data and passes it through encoding/json to convert it into the | 
|  | // given Go native structure pointed to by v. v must be a pointer to a struct. | 
|  | func decodeViaJSON(data interface{}, v interface{}) error { | 
|  | // Perform the task by simply marshalling the input into JSON, | 
|  | // then unmarshalling it into target native Go struct. | 
|  | b, err := json.Marshal(data) | 
|  | if err != nil { | 
|  | return err | 
|  | } | 
|  | return json.Unmarshal(b, v) | 
|  | } | 
|  |  | 
|  | func Benchmark_DecodeViaJSON(b *testing.B) { | 
|  | type Person struct { | 
|  | Name   string | 
|  | Age    int | 
|  | Emails []string | 
|  | Extra  map[string]string | 
|  | } | 
|  |  | 
|  | input := map[string]interface{}{ | 
|  | "name":   "Mitchell", | 
|  | "age":    91, | 
|  | "emails": []string{"one", "two", "three"}, | 
|  | "extra": map[string]string{ | 
|  | "twitter": "mitchellh", | 
|  | }, | 
|  | } | 
|  |  | 
|  | var result Person | 
|  | for i := 0; i < b.N; i++ { | 
|  | decodeViaJSON(input, &result) | 
|  | } | 
|  | } | 
|  |  | 
|  | func Benchmark_DecodeBasic(b *testing.B) { | 
|  | input := map[string]interface{}{ | 
|  | "vstring": "foo", | 
|  | "vint":    42, | 
|  | "Vuint":   42, | 
|  | "vbool":   true, | 
|  | "Vfloat":  42.42, | 
|  | "vsilent": true, | 
|  | "vdata":   42, | 
|  | } | 
|  |  | 
|  | var result Basic | 
|  | for i := 0; i < b.N; i++ { | 
|  | Decode(input, &result) | 
|  | } | 
|  | } | 
|  |  | 
|  | func Benchmark_DecodeEmbedded(b *testing.B) { | 
|  | input := map[string]interface{}{ | 
|  | "vstring": "foo", | 
|  | "Basic": map[string]interface{}{ | 
|  | "vstring": "innerfoo", | 
|  | }, | 
|  | "vunique": "bar", | 
|  | } | 
|  |  | 
|  | var result Embedded | 
|  | for i := 0; i < b.N; i++ { | 
|  | Decode(input, &result) | 
|  | } | 
|  | } | 
|  |  | 
|  | func Benchmark_DecodeTypeConversion(b *testing.B) { | 
|  | input := map[string]interface{}{ | 
|  | "IntToFloat":    42, | 
|  | "IntToUint":     42, | 
|  | "IntToBool":     1, | 
|  | "IntToString":   42, | 
|  | "UintToInt":     42, | 
|  | "UintToFloat":   42, | 
|  | "UintToBool":    42, | 
|  | "UintToString":  42, | 
|  | "BoolToInt":     true, | 
|  | "BoolToUint":    true, | 
|  | "BoolToFloat":   true, | 
|  | "BoolToString":  true, | 
|  | "FloatToInt":    42.42, | 
|  | "FloatToUint":   42.42, | 
|  | "FloatToBool":   42.42, | 
|  | "FloatToString": 42.42, | 
|  | "StringToInt":   "42", | 
|  | "StringToUint":  "42", | 
|  | "StringToBool":  "1", | 
|  | "StringToFloat": "42.42", | 
|  | "SliceToMap":    []interface{}{}, | 
|  | "MapToSlice":    map[string]interface{}{}, | 
|  | } | 
|  |  | 
|  | var resultStrict TypeConversionResult | 
|  | for i := 0; i < b.N; i++ { | 
|  | Decode(input, &resultStrict) | 
|  | } | 
|  | } | 
|  |  | 
|  | func Benchmark_DecodeMap(b *testing.B) { | 
|  | input := map[string]interface{}{ | 
|  | "vfoo": "foo", | 
|  | "vother": map[interface{}]interface{}{ | 
|  | "foo": "foo", | 
|  | "bar": "bar", | 
|  | }, | 
|  | } | 
|  |  | 
|  | var result Map | 
|  | for i := 0; i < b.N; i++ { | 
|  | Decode(input, &result) | 
|  | } | 
|  | } | 
|  |  | 
|  | func Benchmark_DecodeMapOfStruct(b *testing.B) { | 
|  | input := map[string]interface{}{ | 
|  | "value": map[string]interface{}{ | 
|  | "foo": map[string]string{"vstring": "one"}, | 
|  | "bar": map[string]string{"vstring": "two"}, | 
|  | }, | 
|  | } | 
|  |  | 
|  | var result MapOfStruct | 
|  | for i := 0; i < b.N; i++ { | 
|  | Decode(input, &result) | 
|  | } | 
|  | } | 
|  |  | 
|  | func Benchmark_DecodeSlice(b *testing.B) { | 
|  | input := map[string]interface{}{ | 
|  | "vfoo": "foo", | 
|  | "vbar": []string{"foo", "bar", "baz"}, | 
|  | } | 
|  |  | 
|  | var result Slice | 
|  | for i := 0; i < b.N; i++ { | 
|  | Decode(input, &result) | 
|  | } | 
|  | } | 
|  |  | 
|  | func Benchmark_DecodeSliceOfStruct(b *testing.B) { | 
|  | input := map[string]interface{}{ | 
|  | "value": []map[string]interface{}{ | 
|  | {"vstring": "one"}, | 
|  | {"vstring": "two"}, | 
|  | }, | 
|  | } | 
|  |  | 
|  | var result SliceOfStruct | 
|  | for i := 0; i < b.N; i++ { | 
|  | Decode(input, &result) | 
|  | } | 
|  | } | 
|  |  | 
|  | func Benchmark_DecodeWeaklyTypedInput(b *testing.B) { | 
|  | type Person struct { | 
|  | Name   string | 
|  | Age    int | 
|  | Emails []string | 
|  | } | 
|  |  | 
|  | // This input can come from anywhere, but typically comes from | 
|  | // something like decoding JSON, generated by a weakly typed language | 
|  | // such as PHP. | 
|  | input := map[string]interface{}{ | 
|  | "name":   123,                      // number => string | 
|  | "age":    "42",                     // string => number | 
|  | "emails": map[string]interface{}{}, // empty map => empty array | 
|  | } | 
|  |  | 
|  | var result Person | 
|  | config := &DecoderConfig{ | 
|  | WeaklyTypedInput: true, | 
|  | Result:           &result, | 
|  | } | 
|  |  | 
|  | decoder, err := NewDecoder(config) | 
|  | if err != nil { | 
|  | panic(err) | 
|  | } | 
|  |  | 
|  | for i := 0; i < b.N; i++ { | 
|  | decoder.Decode(input) | 
|  | } | 
|  | } | 
|  |  | 
|  | func Benchmark_DecodeMetadata(b *testing.B) { | 
|  | type Person struct { | 
|  | Name string | 
|  | Age  int | 
|  | } | 
|  |  | 
|  | input := map[string]interface{}{ | 
|  | "name":  "Mitchell", | 
|  | "age":   91, | 
|  | "email": "foo@bar.com", | 
|  | } | 
|  |  | 
|  | var md Metadata | 
|  | var result Person | 
|  | config := &DecoderConfig{ | 
|  | Metadata: &md, | 
|  | Result:   &result, | 
|  | } | 
|  |  | 
|  | decoder, err := NewDecoder(config) | 
|  | if err != nil { | 
|  | panic(err) | 
|  | } | 
|  |  | 
|  | for i := 0; i < b.N; i++ { | 
|  | decoder.Decode(input) | 
|  | } | 
|  | } | 
|  |  | 
|  | func Benchmark_DecodeMetadataEmbedded(b *testing.B) { | 
|  | input := map[string]interface{}{ | 
|  | "vstring": "foo", | 
|  | "vunique": "bar", | 
|  | } | 
|  |  | 
|  | var md Metadata | 
|  | var result EmbeddedSquash | 
|  | config := &DecoderConfig{ | 
|  | Metadata: &md, | 
|  | Result:   &result, | 
|  | } | 
|  |  | 
|  | decoder, err := NewDecoder(config) | 
|  | if err != nil { | 
|  | b.Fatalf("err: %s", err) | 
|  | } | 
|  |  | 
|  | for i := 0; i < b.N; i++ { | 
|  | decoder.Decode(input) | 
|  | } | 
|  | } | 
|  |  | 
|  | func Benchmark_DecodeTagged(b *testing.B) { | 
|  | input := map[string]interface{}{ | 
|  | "foo": "bar", | 
|  | "bar": "value", | 
|  | } | 
|  |  | 
|  | var result Tagged | 
|  | for i := 0; i < b.N; i++ { | 
|  | Decode(input, &result) | 
|  | } | 
|  | } |