github.com/nhannv/mattermost-server@v5.11.1+incompatible/cmd/mattermost/commands/utils.go (about)

     1  // Copyright (c) 2019-present Mattermost, Inc. All Rights Reserved.
     2  // See License.txt for license information.
     3  
     4  package commands
     5  
     6  import (
     7  	"bytes"
     8  	"fmt"
     9  	"reflect"
    10  	"strings"
    11  
    12  	"github.com/mattermost/mattermost-server/mlog"
    13  )
    14  
    15  // prettyPrintStruct will return a prettyPrint version of a given struct
    16  func prettyPrintStruct(t interface{}) string {
    17  	return prettyPrintMap(structToMap(t))
    18  }
    19  
    20  // structToMap converts a struct into a map
    21  func structToMap(t interface{}) map[string]interface{} {
    22  	defer func() {
    23  		if r := recover(); r != nil {
    24  			mlog.Error(fmt.Sprintf("Panicked in structToMap. This should never happen. %v", r))
    25  		}
    26  	}()
    27  
    28  	val := reflect.ValueOf(t)
    29  
    30  	if val.Kind() != reflect.Struct {
    31  		return nil
    32  	}
    33  
    34  	out := map[string]interface{}{}
    35  
    36  	for i := 0; i < val.NumField(); i++ {
    37  		field := val.Field(i)
    38  
    39  		var value interface{}
    40  
    41  		switch field.Kind() {
    42  		case reflect.Struct:
    43  			value = structToMap(field.Interface())
    44  		case reflect.Ptr:
    45  			indirectType := field.Elem()
    46  
    47  			if indirectType.Kind() == reflect.Struct {
    48  				value = structToMap(indirectType.Interface())
    49  			} else {
    50  				value = indirectType.Interface()
    51  			}
    52  		default:
    53  			value = field.Interface()
    54  		}
    55  
    56  		out[val.Type().Field(i).Name] = value
    57  	}
    58  
    59  	return out
    60  }
    61  
    62  // prettyPrintMap will return a prettyPrint version of a given map
    63  func prettyPrintMap(configMap map[string]interface{}) string {
    64  	value := reflect.ValueOf(configMap)
    65  	return printMap(value, 0)
    66  }
    67  
    68  // printMap takes a reflect.Value and prints it out, recursively if it's a map with the given tab settings
    69  func printMap(value reflect.Value, tabVal int) string {
    70  	out := &bytes.Buffer{}
    71  
    72  	for _, key := range value.MapKeys() {
    73  		val := value.MapIndex(key)
    74  		if newVal, ok := val.Interface().(map[string]interface{}); !ok {
    75  			fmt.Fprintf(out, "%s", strings.Repeat("\t", tabVal))
    76  			fmt.Fprintf(out, "%v: \"%v\"\n", key.Interface(), val.Interface())
    77  		} else {
    78  			fmt.Fprintf(out, "%s", strings.Repeat("\t", tabVal))
    79  			fmt.Fprintf(out, "%v:\n", key.Interface())
    80  			// going one level in, increase the tab
    81  			tabVal++
    82  			fmt.Fprintf(out, "%s", printMap(reflect.ValueOf(newVal), tabVal))
    83  			// coming back one level, decrease the tab
    84  			tabVal--
    85  		}
    86  	}
    87  
    88  	return out.String()
    89  }