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
15
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
25 type Encoder struct {
26 w io.Writer
27 scratch bytes.Buffer
28 needSep bool
29 }
30
31
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
46
47
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
70
71
72
73
74
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
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
110
111 var ErrNilKey = errors.New("nil key")
112
113
114
115 var ErrInvalidKey = errors.New("invalid key")
116
117
118
119 var ErrUnsupportedKeyType = errors.New("unsupported key type")
120
121
122
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
169
170
171
172 func keyRuneFilter(r rune) rune {
173 if r <= ' ' || r == '=' || r == '"' || r == utf8.RuneError {
174 return -1
175 }
176 return r
177 }
178
179 func writeStringKey(w io.Writer, key string) error {
180 k := strings.Map(keyRuneFilter, key)
181 if k == "" {
182 return ErrInvalidKey
183 }
184 _, err := io.WriteString(w, k)
185 return err
186 }
187
188 func writeBytesKey(w io.Writer, key []byte) error {
189 k := bytes.Map(keyRuneFilter, key)
190 if len(k) == 0 {
191 return ErrInvalidKey
192 }
193 _, err := w.Write(k)
194 return err
195 }
196
197 func writeValue(w io.Writer, value interface{}) error {
198 switch v := value.(type) {
199 case nil:
200 return writeBytesValue(w, null)
201 case string:
202 return writeStringValue(w, v, true)
203 case []byte:
204 return writeBytesValue(w, v)
205 case encoding.TextMarshaler:
206 vb, err := safeMarshal(v)
207 if err != nil {
208 return err
209 }
210 if vb == nil {
211 vb = null
212 }
213 return writeBytesValue(w, vb)
214 case error:
215 se, ok := safeError(v)
216 return writeStringValue(w, se, ok)
217 case fmt.Stringer:
218 ss, ok := safeString(v)
219 return writeStringValue(w, ss, ok)
220 default:
221 rvalue := reflect.ValueOf(value)
222 switch rvalue.Kind() {
223 case reflect.Array, reflect.Chan, reflect.Func, reflect.Map, reflect.Slice, reflect.Struct:
224 return ErrUnsupportedValueType
225 case reflect.Ptr:
226 if rvalue.IsNil() {
227 return writeBytesValue(w, null)
228 }
229 return writeValue(w, rvalue.Elem().Interface())
230 }
231 return writeStringValue(w, fmt.Sprint(v), true)
232 }
233 }
234
235 func needsQuotedValueRune(r rune) bool {
236 return r <= ' ' || r == '=' || r == '"' || r == utf8.RuneError
237 }
238
239 func writeStringValue(w io.Writer, value string, ok bool) error {
240 var err error
241 if ok && value == "null" {
242 _, err = io.WriteString(w, `"null"`)
243 } else if strings.IndexFunc(value, needsQuotedValueRune) != -1 {
244 _, err = writeQuotedString(w, value)
245 } else {
246 _, err = io.WriteString(w, value)
247 }
248 return err
249 }
250
251 func writeBytesValue(w io.Writer, value []byte) error {
252 var err error
253 if bytes.IndexFunc(value, needsQuotedValueRune) != -1 {
254 _, err = writeQuotedBytes(w, value)
255 } else {
256 _, err = w.Write(value)
257 }
258 return err
259 }
260
261
262
263 func (enc *Encoder) EndRecord() error {
264 _, err := enc.w.Write(newline)
265 if err == nil {
266 enc.needSep = false
267 }
268 return err
269 }
270
271
272 func (enc *Encoder) Reset() {
273 enc.needSep = false
274 }
275
276 func safeError(err error) (s string, ok bool) {
277 defer func() {
278 if panicVal := recover(); panicVal != nil {
279 if v := reflect.ValueOf(err); v.Kind() == reflect.Ptr && v.IsNil() {
280 s, ok = "null", false
281 } else {
282 s, ok = fmt.Sprintf("PANIC:%v", panicVal), false
283 }
284 }
285 }()
286 s, ok = err.Error(), true
287 return
288 }
289
290 func safeString(str fmt.Stringer) (s string, ok bool) {
291 defer func() {
292 if panicVal := recover(); panicVal != nil {
293 if v := reflect.ValueOf(str); v.Kind() == reflect.Ptr && v.IsNil() {
294 s, ok = "null", false
295 } else {
296 s, ok = fmt.Sprintf("PANIC:%v", panicVal), true
297 }
298 }
299 }()
300 s, ok = str.String(), true
301 return
302 }
303
304 func safeMarshal(tm encoding.TextMarshaler) (b []byte, err error) {
305 defer func() {
306 if panicVal := recover(); panicVal != nil {
307 if v := reflect.ValueOf(tm); v.Kind() == reflect.Ptr && v.IsNil() {
308 b, err = nil, nil
309 } else {
310 b, err = nil, fmt.Errorf("panic when marshalling: %s", panicVal)
311 }
312 }
313 }()
314 b, err = tm.MarshalText()
315 if err != nil {
316 return nil, &MarshalerError{
317 Type: reflect.TypeOf(tm),
318 Err: err,
319 }
320 }
321 return
322 }
323
View as plain text