github.com/anjalikarhana/fabric@v2.1.1+incompatible/orderer/common/localconfig/flatten.go (about) 1 /* 2 Copyright IBM Corp. All Rights Reserved. 3 4 SPDX-License-Identifier: Apache-2.0 5 */ 6 7 package localconfig 8 9 import ( 10 "fmt" 11 "reflect" 12 ) 13 14 // Flatten performs a depth-first serialization of a struct to a slice of 15 // strings. Each string will be formatted at 'path.to.leaf = value'. 16 func Flatten(i interface{}) []string { 17 var res []string 18 flatten("", &res, reflect.ValueOf(i)) 19 return res 20 } 21 22 // flatten recursively retrieves every leaf node in a struct in depth-first fashion 23 // and aggregate the results into given string slice with format: "path.to.leaf = value" 24 // in the order of definition. Root name is ignored in the path. This helper function is 25 // useful to pretty-print a struct, such as configs. 26 // for example, given data structure: 27 // A{ 28 // B{ 29 // C: "foo", 30 // D: 42, 31 // }, 32 // E: nil, 33 // } 34 // it should yield a slice of string containing following items: 35 // [ 36 // "B.C = \"foo\"", 37 // "B.D = 42", 38 // "E =", 39 // ] 40 func flatten(k string, m *[]string, v reflect.Value) { 41 delimiter := "." 42 if k == "" { 43 delimiter = "" 44 } 45 46 switch v.Kind() { 47 case reflect.Ptr: 48 if v.IsNil() { 49 *m = append(*m, fmt.Sprintf("%s =", k)) 50 return 51 } 52 flatten(k, m, v.Elem()) 53 case reflect.Struct: 54 if x, ok := v.Interface().(fmt.Stringer); ok { 55 *m = append(*m, fmt.Sprintf("%s = %v", k, x)) 56 return 57 } 58 59 for i := 0; i < v.NumField(); i++ { 60 flatten(k+delimiter+v.Type().Field(i).Name, m, v.Field(i)) 61 } 62 case reflect.String: 63 // It is useful to quote string values 64 *m = append(*m, fmt.Sprintf("%s = \"%s\"", k, v)) 65 default: 66 *m = append(*m, fmt.Sprintf("%s = %v", k, v)) 67 } 68 }