1//
2// Copyright 2017, Sander van Harmelen
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15//
16
17package gitlab
18
19import (
20 "bytes"
21 "fmt"
22
23 "reflect"
24)
25
26// Stringify attempts to create a reasonable string representation of types in
27// the GitHub library. It does things like resolve pointers to their values
28// and omits struct fields with nil values.
29func Stringify(message interface{}) string {
30 var buf bytes.Buffer
31 v := reflect.ValueOf(message)
32 stringifyValue(&buf, v)
33 return buf.String()
34}
35
36// stringifyValue was heavily inspired by the goprotobuf library.
37func stringifyValue(buf *bytes.Buffer, val reflect.Value) {
38 if val.Kind() == reflect.Ptr && val.IsNil() {
39 buf.WriteString("<nil>")
40 return
41 }
42
43 v := reflect.Indirect(val)
44
45 switch v.Kind() {
46 case reflect.String:
47 fmt.Fprintf(buf, `"%s"`, v)
48 case reflect.Slice:
49 buf.WriteByte('[')
50 for i := 0; i < v.Len(); i++ {
51 if i > 0 {
52 buf.WriteByte(' ')
53 }
54
55 stringifyValue(buf, v.Index(i))
56 }
57
58 buf.WriteByte(']')
59 return
60 case reflect.Struct:
61 if v.Type().Name() != "" {
62 buf.WriteString(v.Type().String())
63 }
64
65 buf.WriteByte('{')
66
67 var sep bool
68 for i := 0; i < v.NumField(); i++ {
69 fv := v.Field(i)
70 if fv.Kind() == reflect.Ptr && fv.IsNil() {
71 continue
72 }
73 if fv.Kind() == reflect.Slice && fv.IsNil() {
74 continue
75 }
76
77 if sep {
78 buf.WriteString(", ")
79 } else {
80 sep = true
81 }
82
83 buf.WriteString(v.Type().Field(i).Name)
84 buf.WriteByte(':')
85 stringifyValue(buf, fv)
86 }
87
88 buf.WriteByte('}')
89 default:
90 if v.CanInterface() {
91 fmt.Fprint(buf, v.Interface())
92 }
93 }
94}