...
1 package slog
2
3 import (
4 "bytes"
5 "encoding/json"
6 "fmt"
7 "reflect"
8 "strings"
9
10 "golang.org/x/xerrors"
11 )
12
13
14 type Map []Field
15
16 var _ json.Marshaler = Map(nil)
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38 func (m Map) MarshalJSON() ([]byte, error) {
39 b := &bytes.Buffer{}
40 b.WriteByte('{')
41 for i, f := range m {
42 b.WriteByte('\n')
43 b.Write(encode(f.Name))
44 b.WriteByte(':')
45 b.Write(encode(f.Value))
46
47 if i < len(m)-1 {
48 b.WriteByte(',')
49 }
50 }
51 b.WriteByte('}')
52
53 return b.Bytes(), nil
54 }
55
56 func marshalList(rv reflect.Value) []byte {
57 b := &bytes.Buffer{}
58 b.WriteByte('[')
59 for i := 0; i < rv.Len(); i++ {
60 b.WriteByte('\n')
61 b.Write(encode(rv.Index(i).Interface()))
62
63 if i < rv.Len()-1 {
64 b.WriteByte(',')
65 }
66 }
67 b.WriteByte(']')
68
69 return b.Bytes()
70 }
71
72 func encode(v interface{}) []byte {
73 switch v := v.(type) {
74 case json.Marshaler:
75 return encodeJSON(v)
76 case xerrors.Formatter:
77 return encode(errorChain(v))
78 }
79
80 rv := reflect.Indirect(reflect.ValueOf(v))
81 if !rv.IsValid() {
82 return encodeJSON(v)
83 }
84
85 if rv.Kind() == reflect.Struct {
86 b, ok := encodeStruct(rv)
87 if ok {
88 return b
89 }
90 }
91
92 switch v.(type) {
93 case error, fmt.Stringer:
94 return encode(fmt.Sprint(v))
95 }
96
97 switch rv.Type().Kind() {
98 case reflect.Slice:
99 if !rv.IsNil() {
100 return marshalList(rv)
101 }
102 case reflect.Array:
103 return marshalList(rv)
104 case reflect.Struct, reflect.Chan, reflect.Complex64, reflect.Complex128, reflect.Func:
105
106
107 return encodeJSON(fmt.Sprintf("%+v", v))
108 }
109
110 return encodeJSON(v)
111 }
112
113 func encodeStruct(rv reflect.Value) ([]byte, bool) {
114 if rv.Kind() == reflect.Struct {
115 for i := 0; i < rv.NumField(); i++ {
116 ft := rv.Type().Field(i)
117
118 if ft.Tag.Get("json") != "" {
119 return encodeJSON(rv.Interface()), true
120 }
121 }
122 }
123
124 return nil, false
125 }
126
127 func encodeJSON(v interface{}) []byte {
128 b, err := json.Marshal(v)
129 if err != nil {
130 return encode(M(
131 Error(xerrors.Errorf("failed to marshal to JSON: %w", err)),
132 F("type", reflect.TypeOf(v)),
133 F("value", fmt.Sprintf("%+v", v)),
134 ))
135 }
136 return b
137 }
138
139 func errorChain(f xerrors.Formatter) []interface{} {
140 var errs []interface{}
141
142 next := error(f)
143 for {
144 f, ok := next.(xerrors.Formatter)
145 if !ok {
146 errs = append(errs, next)
147 return errs
148 }
149
150 p := &xerrorPrinter{}
151 next = f.FormatError(p)
152 errs = append(errs, p.e)
153 }
154 }
155
156 type wrapError struct {
157 Msg string `json:"msg"`
158 Fun string `json:"fun"`
159
160 Loc string `json:"loc"`
161 }
162
163 type xerrorPrinter struct {
164 e wrapError
165 }
166
167 func (p *xerrorPrinter) Print(v ...interface{}) {
168 s := fmt.Sprint(v...)
169 p.write(s)
170 }
171
172 func (p *xerrorPrinter) Printf(f string, v ...interface{}) {
173 s := fmt.Sprintf(f, v...)
174 p.write(s)
175 }
176
177 func (p *xerrorPrinter) Detail() bool {
178 return true
179 }
180
181 func (p *xerrorPrinter) write(s string) {
182 s = strings.TrimSpace(s)
183 switch {
184 case p.e.Msg == "":
185 p.e.Msg = s
186 case p.e.Fun == "":
187 p.e.Fun = s
188 case p.e.Loc == "":
189 p.e.Loc = s
190 }
191 }
192
193 func (m Map) append(m2 Map) Map {
194 m3 := make(Map, 0, len(m)+len(m2))
195 m3 = append(m3, m...)
196 m3 = append(m3, m2...)
197 return m3
198 }
199
View as plain text