github.com/KevinKlinger/open_terraform@v0.11.12-beta1/flatmap/flatten.go (about)

     1  package flatmap
     2  
     3  import (
     4  	"fmt"
     5  	"reflect"
     6  )
     7  
     8  // Flatten takes a structure and turns into a flat map[string]string.
     9  //
    10  // Within the "thing" parameter, only primitive values are allowed. Structs are
    11  // not supported. Therefore, it can only be slices, maps, primitives, and
    12  // any combination of those together.
    13  //
    14  // See the tests for examples of what inputs are turned into.
    15  func Flatten(thing map[string]interface{}) Map {
    16  	result := make(map[string]string)
    17  
    18  	for k, raw := range thing {
    19  		flatten(result, k, reflect.ValueOf(raw))
    20  	}
    21  
    22  	return Map(result)
    23  }
    24  
    25  func flatten(result map[string]string, prefix string, v reflect.Value) {
    26  	if v.Kind() == reflect.Interface {
    27  		v = v.Elem()
    28  	}
    29  
    30  	switch v.Kind() {
    31  	case reflect.Bool:
    32  		if v.Bool() {
    33  			result[prefix] = "true"
    34  		} else {
    35  			result[prefix] = "false"
    36  		}
    37  	case reflect.Int:
    38  		result[prefix] = fmt.Sprintf("%d", v.Int())
    39  	case reflect.Map:
    40  		flattenMap(result, prefix, v)
    41  	case reflect.Slice:
    42  		flattenSlice(result, prefix, v)
    43  	case reflect.String:
    44  		result[prefix] = v.String()
    45  	default:
    46  		panic(fmt.Sprintf("Unknown: %s", v))
    47  	}
    48  }
    49  
    50  func flattenMap(result map[string]string, prefix string, v reflect.Value) {
    51  	for _, k := range v.MapKeys() {
    52  		if k.Kind() == reflect.Interface {
    53  			k = k.Elem()
    54  		}
    55  
    56  		if k.Kind() != reflect.String {
    57  			panic(fmt.Sprintf("%s: map key is not string: %s", prefix, k))
    58  		}
    59  
    60  		flatten(result, fmt.Sprintf("%s.%s", prefix, k.String()), v.MapIndex(k))
    61  	}
    62  }
    63  
    64  func flattenSlice(result map[string]string, prefix string, v reflect.Value) {
    65  	prefix = prefix + "."
    66  
    67  	result[prefix+"#"] = fmt.Sprintf("%d", v.Len())
    68  	for i := 0; i < v.Len(); i++ {
    69  		flatten(result, fmt.Sprintf("%s%d", prefix, i), v.Index(i))
    70  	}
    71  }