OSDN Git Service

new repo
[bytom/vapor.git] / vendor / github.com / go-logfmt / logfmt / encode.go
1 package logfmt
2
3 import (
4         "bytes"
5         "encoding"
6         "errors"
7         "fmt"
8         "io"
9         "reflect"
10         "strings"
11         "unicode/utf8"
12 )
13
14 // MarshalKeyvals returns the logfmt encoding of keyvals, a variadic sequence
15 // of alternating keys and values.
16 func MarshalKeyvals(keyvals ...interface{}) ([]byte, error) {
17         buf := &bytes.Buffer{}
18         if err := NewEncoder(buf).EncodeKeyvals(keyvals...); err != nil {
19                 return nil, err
20         }
21         return buf.Bytes(), nil
22 }
23
24 // An Encoder writes logfmt data to an output stream.
25 type Encoder struct {
26         w       io.Writer
27         scratch bytes.Buffer
28         needSep bool
29 }
30
31 // NewEncoder returns a new encoder that writes to w.
32 func NewEncoder(w io.Writer) *Encoder {
33         return &Encoder{
34                 w: w,
35         }
36 }
37
38 var (
39         space   = []byte(" ")
40         equals  = []byte("=")
41         newline = []byte("\n")
42         null    = []byte("null")
43 )
44
45 // EncodeKeyval writes the logfmt encoding of key and value to the stream. A
46 // single space is written before the second and subsequent keys in a record.
47 // Nothing is written if a non-nil error is returned.
48 func (enc *Encoder) EncodeKeyval(key, value interface{}) error {
49         enc.scratch.Reset()
50         if enc.needSep {
51                 if _, err := enc.scratch.Write(space); err != nil {
52                         return err
53                 }
54         }
55         if err := writeKey(&enc.scratch, key); err != nil {
56                 return err
57         }
58         if _, err := enc.scratch.Write(equals); err != nil {
59                 return err
60         }
61         if err := writeValue(&enc.scratch, value); err != nil {
62                 return err
63         }
64         _, err := enc.w.Write(enc.scratch.Bytes())
65         enc.needSep = true
66         return err
67 }
68
69 // EncodeKeyvals writes the logfmt encoding of keyvals to the stream. Keyvals
70 // is a variadic sequence of alternating keys and values. Keys of unsupported
71 // type are skipped along with their corresponding value. Values of
72 // unsupported type or that cause a MarshalerError are replaced by their error
73 // but do not cause EncodeKeyvals to return an error. If a non-nil error is
74 // returned some key/value pairs may not have be written.
75 func (enc *Encoder) EncodeKeyvals(keyvals ...interface{}) error {
76         if len(keyvals) == 0 {
77                 return nil
78         }
79         if len(keyvals)%2 == 1 {
80                 keyvals = append(keyvals, nil)
81         }
82         for i := 0; i < len(keyvals); i += 2 {
83                 k, v := keyvals[i], keyvals[i+1]
84                 err := enc.EncodeKeyval(k, v)
85                 if err == ErrUnsupportedKeyType {
86                         continue
87                 }
88                 if _, ok := err.(*MarshalerError); ok || err == ErrUnsupportedValueType {
89                         v = err
90                         err = enc.EncodeKeyval(k, v)
91                 }
92                 if err != nil {
93                         return err
94                 }
95         }
96         return nil
97 }
98
99 // MarshalerError represents an error encountered while marshaling a value.
100 type MarshalerError struct {
101         Type reflect.Type
102         Err  error
103 }
104
105 func (e *MarshalerError) Error() string {
106         return "error marshaling value of type " + e.Type.String() + ": " + e.Err.Error()
107 }
108
109 // ErrNilKey is returned by Marshal functions and Encoder methods if a key is
110 // a nil interface or pointer value.
111 var ErrNilKey = errors.New("nil key")
112
113 // ErrInvalidKey is returned by Marshal functions and Encoder methods if a key
114 // contains an invalid character.
115 var ErrInvalidKey = errors.New("invalid key")
116
117 // ErrUnsupportedKeyType is returned by Encoder methods if a key has an
118 // unsupported type.
119 var ErrUnsupportedKeyType = errors.New("unsupported key type")
120
121 // ErrUnsupportedValueType is returned by Encoder methods if a value has an
122 // unsupported type.
123 var ErrUnsupportedValueType = errors.New("unsupported value type")
124
125 func writeKey(w io.Writer, key interface{}) error {
126         if key == nil {
127                 return ErrNilKey
128         }
129
130         switch k := key.(type) {
131         case string:
132                 return writeStringKey(w, k)
133         case []byte:
134                 if k == nil {
135                         return ErrNilKey
136                 }
137                 return writeBytesKey(w, k)
138         case encoding.TextMarshaler:
139                 kb, err := safeMarshal(k)
140                 if err != nil {
141                         return err
142                 }
143                 if kb == nil {
144                         return ErrNilKey
145                 }
146                 return writeBytesKey(w, kb)
147         case fmt.Stringer:
148                 ks, ok := safeString(k)
149                 if !ok {
150                         return ErrNilKey
151                 }
152                 return writeStringKey(w, ks)
153         default:
154                 rkey := reflect.ValueOf(key)
155                 switch rkey.Kind() {
156                 case reflect.Array, reflect.Chan, reflect.Func, reflect.Map, reflect.Slice, reflect.Struct:
157                         return ErrUnsupportedKeyType
158                 case reflect.Ptr:
159                         if rkey.IsNil() {
160                                 return ErrNilKey
161                         }
162                         return writeKey(w, rkey.Elem().Interface())
163                 }
164                 return writeStringKey(w, fmt.Sprint(k))
165         }
166 }
167
168 func invalidKeyRune(r rune) bool {
169         return r <= ' ' || r == '=' || r == '"' || r == utf8.RuneError
170 }
171
172 func invalidKeyString(key string) bool {
173         return len(key) == 0 || strings.IndexFunc(key, invalidKeyRune) != -1
174 }
175
176 func invalidKey(key []byte) bool {
177         return len(key) == 0 || bytes.IndexFunc(key, invalidKeyRune) != -1
178 }
179
180 func writeStringKey(w io.Writer, key string) error {
181         if invalidKeyString(key) {
182                 return ErrInvalidKey
183         }
184         _, err := io.WriteString(w, key)
185         return err
186 }
187
188 func writeBytesKey(w io.Writer, key []byte) error {
189         if invalidKey(key) {
190                 return ErrInvalidKey
191         }
192         _, err := w.Write(key)
193         return err
194 }
195
196 func writeValue(w io.Writer, value interface{}) error {
197         switch v := value.(type) {
198         case nil:
199                 return writeBytesValue(w, null)
200         case string:
201                 return writeStringValue(w, v, true)
202         case []byte:
203                 return writeBytesValue(w, v)
204         case encoding.TextMarshaler:
205                 vb, err := safeMarshal(v)
206                 if err != nil {
207                         return err
208                 }
209                 if vb == nil {
210                         vb = null
211                 }
212                 return writeBytesValue(w, vb)
213         case error:
214                 se, ok := safeError(v)
215                 return writeStringValue(w, se, ok)
216         case fmt.Stringer:
217                 ss, ok := safeString(v)
218                 return writeStringValue(w, ss, ok)
219         default:
220                 rvalue := reflect.ValueOf(value)
221                 switch rvalue.Kind() {
222                 case reflect.Array, reflect.Chan, reflect.Func, reflect.Map, reflect.Slice, reflect.Struct:
223                         return ErrUnsupportedValueType
224                 case reflect.Ptr:
225                         if rvalue.IsNil() {
226                                 return writeBytesValue(w, null)
227                         }
228                         return writeValue(w, rvalue.Elem().Interface())
229                 }
230                 return writeStringValue(w, fmt.Sprint(v), true)
231         }
232 }
233
234 func needsQuotedValueRune(r rune) bool {
235         return r <= ' ' || r == '=' || r == '"' || r == utf8.RuneError
236 }
237
238 func writeStringValue(w io.Writer, value string, ok bool) error {
239         var err error
240         if ok && value == "null" {
241                 _, err = io.WriteString(w, `"null"`)
242         } else if strings.IndexFunc(value, needsQuotedValueRune) != -1 {
243                 _, err = writeQuotedString(w, value)
244         } else {
245                 _, err = io.WriteString(w, value)
246         }
247         return err
248 }
249
250 func writeBytesValue(w io.Writer, value []byte) error {
251         var err error
252         if bytes.IndexFunc(value, needsQuotedValueRune) != -1 {
253                 _, err = writeQuotedBytes(w, value)
254         } else {
255                 _, err = w.Write(value)
256         }
257         return err
258 }
259
260 // EndRecord writes a newline character to the stream and resets the encoder
261 // to the beginning of a new record.
262 func (enc *Encoder) EndRecord() error {
263         _, err := enc.w.Write(newline)
264         if err == nil {
265                 enc.needSep = false
266         }
267         return err
268 }
269
270 // Reset resets the encoder to the beginning of a new record.
271 func (enc *Encoder) Reset() {
272         enc.needSep = false
273 }
274
275 func safeError(err error) (s string, ok bool) {
276         defer func() {
277                 if panicVal := recover(); panicVal != nil {
278                         if v := reflect.ValueOf(err); v.Kind() == reflect.Ptr && v.IsNil() {
279                                 s, ok = "null", false
280                         } else {
281                                 panic(panicVal)
282                         }
283                 }
284         }()
285         s, ok = err.Error(), true
286         return
287 }
288
289 func safeString(str fmt.Stringer) (s string, ok bool) {
290         defer func() {
291                 if panicVal := recover(); panicVal != nil {
292                         if v := reflect.ValueOf(str); v.Kind() == reflect.Ptr && v.IsNil() {
293                                 s, ok = "null", false
294                         } else {
295                                 panic(panicVal)
296                         }
297                 }
298         }()
299         s, ok = str.String(), true
300         return
301 }
302
303 func safeMarshal(tm encoding.TextMarshaler) (b []byte, err error) {
304         defer func() {
305                 if panicVal := recover(); panicVal != nil {
306                         if v := reflect.ValueOf(tm); v.Kind() == reflect.Ptr && v.IsNil() {
307                                 b, err = nil, nil
308                         } else {
309                                 panic(panicVal)
310                         }
311                 }
312         }()
313         b, err = tm.MarshalText()
314         if err != nil {
315                 return nil, &MarshalerError{
316                         Type: reflect.TypeOf(tm),
317                         Err:  err,
318                 }
319         }
320         return
321 }