1package zerolog
2
3import (
4	"encoding/json"
5	"net"
6	"sort"
7	"time"
8	"unsafe"
9)
10
11func isNilValue(i interface{}) bool {
12	return (*[2]uintptr)(unsafe.Pointer(&i))[1] == 0
13}
14
15func appendFields(dst []byte, fields interface{}) []byte {
16	switch fields := fields.(type) {
17	case []interface{}:
18		if n := len(fields); n&0x1 == 1 { // odd number
19			fields = fields[:n-1]
20		}
21		dst = appendFieldList(dst, fields)
22	case map[string]interface{}:
23		keys := make([]string, 0, len(fields))
24		for key := range fields {
25			keys = append(keys, key)
26		}
27		sort.Strings(keys)
28		kv := make([]interface{}, 2)
29		for _, key := range keys {
30			kv[0], kv[1] = key, fields[key]
31			dst = appendFieldList(dst, kv)
32		}
33	}
34	return dst
35}
36
37func appendFieldList(dst []byte, kvList []interface{}) []byte {
38	for i, n := 0, len(kvList); i < n; i += 2 {
39		key, val := kvList[i], kvList[i+1]
40		if key, ok := key.(string); ok {
41			dst = enc.AppendKey(dst, key)
42		} else {
43			continue
44		}
45		if val, ok := val.(LogObjectMarshaler); ok {
46			e := newEvent(nil, 0)
47			e.buf = e.buf[:0]
48			e.appendObject(val)
49			dst = append(dst, e.buf...)
50			putEvent(e)
51			continue
52		}
53		switch val := val.(type) {
54		case string:
55			dst = enc.AppendString(dst, val)
56		case []byte:
57			dst = enc.AppendBytes(dst, val)
58		case error:
59			switch m := ErrorMarshalFunc(val).(type) {
60			case LogObjectMarshaler:
61				e := newEvent(nil, 0)
62				e.buf = e.buf[:0]
63				e.appendObject(m)
64				dst = append(dst, e.buf...)
65				putEvent(e)
66			case error:
67				if m == nil || isNilValue(m) {
68					dst = enc.AppendNil(dst)
69				} else {
70					dst = enc.AppendString(dst, m.Error())
71				}
72			case string:
73				dst = enc.AppendString(dst, m)
74			default:
75				dst = enc.AppendInterface(dst, m)
76			}
77		case []error:
78			dst = enc.AppendArrayStart(dst)
79			for i, err := range val {
80				switch m := ErrorMarshalFunc(err).(type) {
81				case LogObjectMarshaler:
82					e := newEvent(nil, 0)
83					e.buf = e.buf[:0]
84					e.appendObject(m)
85					dst = append(dst, e.buf...)
86					putEvent(e)
87				case error:
88					if m == nil || isNilValue(m) {
89						dst = enc.AppendNil(dst)
90					} else {
91						dst = enc.AppendString(dst, m.Error())
92					}
93				case string:
94					dst = enc.AppendString(dst, m)
95				default:
96					dst = enc.AppendInterface(dst, m)
97				}
98
99				if i < (len(val) - 1) {
100					enc.AppendArrayDelim(dst)
101				}
102			}
103			dst = enc.AppendArrayEnd(dst)
104		case bool:
105			dst = enc.AppendBool(dst, val)
106		case int:
107			dst = enc.AppendInt(dst, val)
108		case int8:
109			dst = enc.AppendInt8(dst, val)
110		case int16:
111			dst = enc.AppendInt16(dst, val)
112		case int32:
113			dst = enc.AppendInt32(dst, val)
114		case int64:
115			dst = enc.AppendInt64(dst, val)
116		case uint:
117			dst = enc.AppendUint(dst, val)
118		case uint8:
119			dst = enc.AppendUint8(dst, val)
120		case uint16:
121			dst = enc.AppendUint16(dst, val)
122		case uint32:
123			dst = enc.AppendUint32(dst, val)
124		case uint64:
125			dst = enc.AppendUint64(dst, val)
126		case float32:
127			dst = enc.AppendFloat32(dst, val)
128		case float64:
129			dst = enc.AppendFloat64(dst, val)
130		case time.Time:
131			dst = enc.AppendTime(dst, val, TimeFieldFormat)
132		case time.Duration:
133			dst = enc.AppendDuration(dst, val, DurationFieldUnit, DurationFieldInteger)
134		case *string:
135			if val != nil {
136				dst = enc.AppendString(dst, *val)
137			} else {
138				dst = enc.AppendNil(dst)
139			}
140		case *bool:
141			if val != nil {
142				dst = enc.AppendBool(dst, *val)
143			} else {
144				dst = enc.AppendNil(dst)
145			}
146		case *int:
147			if val != nil {
148				dst = enc.AppendInt(dst, *val)
149			} else {
150				dst = enc.AppendNil(dst)
151			}
152		case *int8:
153			if val != nil {
154				dst = enc.AppendInt8(dst, *val)
155			} else {
156				dst = enc.AppendNil(dst)
157			}
158		case *int16:
159			if val != nil {
160				dst = enc.AppendInt16(dst, *val)
161			} else {
162				dst = enc.AppendNil(dst)
163			}
164		case *int32:
165			if val != nil {
166				dst = enc.AppendInt32(dst, *val)
167			} else {
168				dst = enc.AppendNil(dst)
169			}
170		case *int64:
171			if val != nil {
172				dst = enc.AppendInt64(dst, *val)
173			} else {
174				dst = enc.AppendNil(dst)
175			}
176		case *uint:
177			if val != nil {
178				dst = enc.AppendUint(dst, *val)
179			} else {
180				dst = enc.AppendNil(dst)
181			}
182		case *uint8:
183			if val != nil {
184				dst = enc.AppendUint8(dst, *val)
185			} else {
186				dst = enc.AppendNil(dst)
187			}
188		case *uint16:
189			if val != nil {
190				dst = enc.AppendUint16(dst, *val)
191			} else {
192				dst = enc.AppendNil(dst)
193			}
194		case *uint32:
195			if val != nil {
196				dst = enc.AppendUint32(dst, *val)
197			} else {
198				dst = enc.AppendNil(dst)
199			}
200		case *uint64:
201			if val != nil {
202				dst = enc.AppendUint64(dst, *val)
203			} else {
204				dst = enc.AppendNil(dst)
205			}
206		case *float32:
207			if val != nil {
208				dst = enc.AppendFloat32(dst, *val)
209			} else {
210				dst = enc.AppendNil(dst)
211			}
212		case *float64:
213			if val != nil {
214				dst = enc.AppendFloat64(dst, *val)
215			} else {
216				dst = enc.AppendNil(dst)
217			}
218		case *time.Time:
219			if val != nil {
220				dst = enc.AppendTime(dst, *val, TimeFieldFormat)
221			} else {
222				dst = enc.AppendNil(dst)
223			}
224		case *time.Duration:
225			if val != nil {
226				dst = enc.AppendDuration(dst, *val, DurationFieldUnit, DurationFieldInteger)
227			} else {
228				dst = enc.AppendNil(dst)
229			}
230		case []string:
231			dst = enc.AppendStrings(dst, val)
232		case []bool:
233			dst = enc.AppendBools(dst, val)
234		case []int:
235			dst = enc.AppendInts(dst, val)
236		case []int8:
237			dst = enc.AppendInts8(dst, val)
238		case []int16:
239			dst = enc.AppendInts16(dst, val)
240		case []int32:
241			dst = enc.AppendInts32(dst, val)
242		case []int64:
243			dst = enc.AppendInts64(dst, val)
244		case []uint:
245			dst = enc.AppendUints(dst, val)
246		// case []uint8:
247		// 	dst = enc.AppendUints8(dst, val)
248		case []uint16:
249			dst = enc.AppendUints16(dst, val)
250		case []uint32:
251			dst = enc.AppendUints32(dst, val)
252		case []uint64:
253			dst = enc.AppendUints64(dst, val)
254		case []float32:
255			dst = enc.AppendFloats32(dst, val)
256		case []float64:
257			dst = enc.AppendFloats64(dst, val)
258		case []time.Time:
259			dst = enc.AppendTimes(dst, val, TimeFieldFormat)
260		case []time.Duration:
261			dst = enc.AppendDurations(dst, val, DurationFieldUnit, DurationFieldInteger)
262		case nil:
263			dst = enc.AppendNil(dst)
264		case net.IP:
265			dst = enc.AppendIPAddr(dst, val)
266		case net.IPNet:
267			dst = enc.AppendIPPrefix(dst, val)
268		case net.HardwareAddr:
269			dst = enc.AppendMACAddr(dst, val)
270		case json.RawMessage:
271			dst = appendJSON(dst, val)
272		default:
273			dst = enc.AppendInterface(dst, val)
274		}
275	}
276	return dst
277}
278