1package util
2
3import (
4	"bytes"
5	"encoding/xml"
6	"fmt"
7	"go/format"
8	"io"
9	"reflect"
10	"regexp"
11	"strings"
12
13	"github.com/aws/aws-sdk-go/private/protocol/xml/xmlutil"
14)
15
16// GoFmt returns the Go formated string of the input.
17//
18// Panics if the format fails.
19func GoFmt(buf string) string {
20	formatted, err := format.Source([]byte(buf))
21	if err != nil {
22		panic(fmt.Errorf("%s\nOriginal code:\n%s", err.Error(), buf))
23	}
24	return string(formatted)
25}
26
27var reTrim = regexp.MustCompile(`\s{2,}`)
28
29// Trim removes all leading and trailing white space.
30//
31// All consecutive spaces will be reduced to a single space.
32func Trim(s string) string {
33	return strings.TrimSpace(reTrim.ReplaceAllString(s, " "))
34}
35
36// Capitalize capitalizes the first character of the string.
37func Capitalize(s string) string {
38	if len(s) == 1 {
39		return strings.ToUpper(s)
40	}
41	return strings.ToUpper(s[0:1]) + s[1:]
42}
43
44// SortXML sorts the reader's XML elements
45//
46// Deprecated: incorrectly handles XML namespaces, should not be used.
47func SortXML(r io.Reader) string {
48	var buf bytes.Buffer
49	d := xml.NewDecoder(r)
50	root, _ := xmlutil.XMLToStruct(d, nil)
51	e := xml.NewEncoder(&buf)
52	xmlutil.StructToXML(e, root, true)
53	return buf.String()
54}
55
56// PrettyPrint generates a human readable representation of the value v.
57// All values of v are recursively found and pretty printed also.
58func PrettyPrint(v interface{}) string {
59	value := reflect.ValueOf(v)
60	switch value.Kind() {
61	case reflect.Struct:
62		str := fullName(value.Type()) + "{\n"
63		for i := 0; i < value.NumField(); i++ {
64			l := string(value.Type().Field(i).Name[0])
65			if strings.ToUpper(l) == l {
66				str += value.Type().Field(i).Name + ": "
67				str += PrettyPrint(value.Field(i).Interface())
68				str += ",\n"
69			}
70		}
71		str += "}"
72		return str
73	case reflect.Map:
74		str := "map[" + fullName(value.Type().Key()) + "]" + fullName(value.Type().Elem()) + "{\n"
75		for _, k := range value.MapKeys() {
76			str += "\"" + k.String() + "\": "
77			str += PrettyPrint(value.MapIndex(k).Interface())
78			str += ",\n"
79		}
80		str += "}"
81		return str
82	case reflect.Ptr:
83		if e := value.Elem(); e.IsValid() {
84			return "&" + PrettyPrint(e.Interface())
85		}
86		return "nil"
87	case reflect.Slice:
88		str := "[]" + fullName(value.Type().Elem()) + "{\n"
89		for i := 0; i < value.Len(); i++ {
90			str += PrettyPrint(value.Index(i).Interface())
91			str += ",\n"
92		}
93		str += "}"
94		return str
95	default:
96		return fmt.Sprintf("%#v", v)
97	}
98}
99
100func pkgName(t reflect.Type) string {
101	pkg := t.PkgPath()
102	c := strings.Split(pkg, "/")
103	return c[len(c)-1]
104}
105
106func fullName(t reflect.Type) string {
107	if pkg := pkgName(t); pkg != "" {
108		return pkg + "." + t.Name()
109	}
110	return t.Name()
111}
112