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