1package json
2
3import (
4	"fmt"
5	"math"
6	"net"
7	"strconv"
8)
9
10// AppendNil inserts a 'Nil' object into the dst byte array.
11func (Encoder) AppendNil(dst []byte) []byte {
12	return append(dst, "null"...)
13}
14
15// AppendBeginMarker inserts a map start into the dst byte array.
16func (Encoder) AppendBeginMarker(dst []byte) []byte {
17	return append(dst, '{')
18}
19
20// AppendEndMarker inserts a map end into the dst byte array.
21func (Encoder) AppendEndMarker(dst []byte) []byte {
22	return append(dst, '}')
23}
24
25// AppendLineBreak appends a line break.
26func (Encoder) AppendLineBreak(dst []byte) []byte {
27	return append(dst, '\n')
28}
29
30// AppendArrayStart adds markers to indicate the start of an array.
31func (Encoder) AppendArrayStart(dst []byte) []byte {
32	return append(dst, '[')
33}
34
35// AppendArrayEnd adds markers to indicate the end of an array.
36func (Encoder) AppendArrayEnd(dst []byte) []byte {
37	return append(dst, ']')
38}
39
40// AppendArrayDelim adds markers to indicate end of a particular array element.
41func (Encoder) AppendArrayDelim(dst []byte) []byte {
42	if len(dst) > 0 {
43		return append(dst, ',')
44	}
45	return dst
46}
47
48// AppendBool converts the input bool to a string and
49// appends the encoded string to the input byte slice.
50func (Encoder) AppendBool(dst []byte, val bool) []byte {
51	return strconv.AppendBool(dst, val)
52}
53
54// AppendBools encodes the input bools to json and
55// appends the encoded string list to the input byte slice.
56func (Encoder) AppendBools(dst []byte, vals []bool) []byte {
57	if len(vals) == 0 {
58		return append(dst, '[', ']')
59	}
60	dst = append(dst, '[')
61	dst = strconv.AppendBool(dst, vals[0])
62	if len(vals) > 1 {
63		for _, val := range vals[1:] {
64			dst = strconv.AppendBool(append(dst, ','), val)
65		}
66	}
67	dst = append(dst, ']')
68	return dst
69}
70
71// AppendInt converts the input int to a string and
72// appends the encoded string to the input byte slice.
73func (Encoder) AppendInt(dst []byte, val int) []byte {
74	return strconv.AppendInt(dst, int64(val), 10)
75}
76
77// AppendInts encodes the input ints to json and
78// appends the encoded string list to the input byte slice.
79func (Encoder) AppendInts(dst []byte, vals []int) []byte {
80	if len(vals) == 0 {
81		return append(dst, '[', ']')
82	}
83	dst = append(dst, '[')
84	dst = strconv.AppendInt(dst, int64(vals[0]), 10)
85	if len(vals) > 1 {
86		for _, val := range vals[1:] {
87			dst = strconv.AppendInt(append(dst, ','), int64(val), 10)
88		}
89	}
90	dst = append(dst, ']')
91	return dst
92}
93
94// AppendInt8 converts the input []int8 to a string and
95// appends the encoded string to the input byte slice.
96func (Encoder) AppendInt8(dst []byte, val int8) []byte {
97	return strconv.AppendInt(dst, int64(val), 10)
98}
99
100// AppendInts8 encodes the input int8s to json and
101// appends the encoded string list to the input byte slice.
102func (Encoder) AppendInts8(dst []byte, vals []int8) []byte {
103	if len(vals) == 0 {
104		return append(dst, '[', ']')
105	}
106	dst = append(dst, '[')
107	dst = strconv.AppendInt(dst, int64(vals[0]), 10)
108	if len(vals) > 1 {
109		for _, val := range vals[1:] {
110			dst = strconv.AppendInt(append(dst, ','), int64(val), 10)
111		}
112	}
113	dst = append(dst, ']')
114	return dst
115}
116
117// AppendInt16 converts the input int16 to a string and
118// appends the encoded string to the input byte slice.
119func (Encoder) AppendInt16(dst []byte, val int16) []byte {
120	return strconv.AppendInt(dst, int64(val), 10)
121}
122
123// AppendInts16 encodes the input int16s to json and
124// appends the encoded string list to the input byte slice.
125func (Encoder) AppendInts16(dst []byte, vals []int16) []byte {
126	if len(vals) == 0 {
127		return append(dst, '[', ']')
128	}
129	dst = append(dst, '[')
130	dst = strconv.AppendInt(dst, int64(vals[0]), 10)
131	if len(vals) > 1 {
132		for _, val := range vals[1:] {
133			dst = strconv.AppendInt(append(dst, ','), int64(val), 10)
134		}
135	}
136	dst = append(dst, ']')
137	return dst
138}
139
140// AppendInt32 converts the input int32 to a string and
141// appends the encoded string to the input byte slice.
142func (Encoder) AppendInt32(dst []byte, val int32) []byte {
143	return strconv.AppendInt(dst, int64(val), 10)
144}
145
146// AppendInts32 encodes the input int32s to json and
147// appends the encoded string list to the input byte slice.
148func (Encoder) AppendInts32(dst []byte, vals []int32) []byte {
149	if len(vals) == 0 {
150		return append(dst, '[', ']')
151	}
152	dst = append(dst, '[')
153	dst = strconv.AppendInt(dst, int64(vals[0]), 10)
154	if len(vals) > 1 {
155		for _, val := range vals[1:] {
156			dst = strconv.AppendInt(append(dst, ','), int64(val), 10)
157		}
158	}
159	dst = append(dst, ']')
160	return dst
161}
162
163// AppendInt64 converts the input int64 to a string and
164// appends the encoded string to the input byte slice.
165func (Encoder) AppendInt64(dst []byte, val int64) []byte {
166	return strconv.AppendInt(dst, val, 10)
167}
168
169// AppendInts64 encodes the input int64s to json and
170// appends the encoded string list to the input byte slice.
171func (Encoder) AppendInts64(dst []byte, vals []int64) []byte {
172	if len(vals) == 0 {
173		return append(dst, '[', ']')
174	}
175	dst = append(dst, '[')
176	dst = strconv.AppendInt(dst, vals[0], 10)
177	if len(vals) > 1 {
178		for _, val := range vals[1:] {
179			dst = strconv.AppendInt(append(dst, ','), val, 10)
180		}
181	}
182	dst = append(dst, ']')
183	return dst
184}
185
186// AppendUint converts the input uint to a string and
187// appends the encoded string to the input byte slice.
188func (Encoder) AppendUint(dst []byte, val uint) []byte {
189	return strconv.AppendUint(dst, uint64(val), 10)
190}
191
192// AppendUints encodes the input uints to json and
193// appends the encoded string list to the input byte slice.
194func (Encoder) AppendUints(dst []byte, vals []uint) []byte {
195	if len(vals) == 0 {
196		return append(dst, '[', ']')
197	}
198	dst = append(dst, '[')
199	dst = strconv.AppendUint(dst, uint64(vals[0]), 10)
200	if len(vals) > 1 {
201		for _, val := range vals[1:] {
202			dst = strconv.AppendUint(append(dst, ','), uint64(val), 10)
203		}
204	}
205	dst = append(dst, ']')
206	return dst
207}
208
209// AppendUint8 converts the input uint8 to a string and
210// appends the encoded string to the input byte slice.
211func (Encoder) AppendUint8(dst []byte, val uint8) []byte {
212	return strconv.AppendUint(dst, uint64(val), 10)
213}
214
215// AppendUints8 encodes the input uint8s to json and
216// appends the encoded string list to the input byte slice.
217func (Encoder) AppendUints8(dst []byte, vals []uint8) []byte {
218	if len(vals) == 0 {
219		return append(dst, '[', ']')
220	}
221	dst = append(dst, '[')
222	dst = strconv.AppendUint(dst, uint64(vals[0]), 10)
223	if len(vals) > 1 {
224		for _, val := range vals[1:] {
225			dst = strconv.AppendUint(append(dst, ','), uint64(val), 10)
226		}
227	}
228	dst = append(dst, ']')
229	return dst
230}
231
232// AppendUint16 converts the input uint16 to a string and
233// appends the encoded string to the input byte slice.
234func (Encoder) AppendUint16(dst []byte, val uint16) []byte {
235	return strconv.AppendUint(dst, uint64(val), 10)
236}
237
238// AppendUints16 encodes the input uint16s to json and
239// appends the encoded string list to the input byte slice.
240func (Encoder) AppendUints16(dst []byte, vals []uint16) []byte {
241	if len(vals) == 0 {
242		return append(dst, '[', ']')
243	}
244	dst = append(dst, '[')
245	dst = strconv.AppendUint(dst, uint64(vals[0]), 10)
246	if len(vals) > 1 {
247		for _, val := range vals[1:] {
248			dst = strconv.AppendUint(append(dst, ','), uint64(val), 10)
249		}
250	}
251	dst = append(dst, ']')
252	return dst
253}
254
255// AppendUint32 converts the input uint32 to a string and
256// appends the encoded string to the input byte slice.
257func (Encoder) AppendUint32(dst []byte, val uint32) []byte {
258	return strconv.AppendUint(dst, uint64(val), 10)
259}
260
261// AppendUints32 encodes the input uint32s to json and
262// appends the encoded string list to the input byte slice.
263func (Encoder) AppendUints32(dst []byte, vals []uint32) []byte {
264	if len(vals) == 0 {
265		return append(dst, '[', ']')
266	}
267	dst = append(dst, '[')
268	dst = strconv.AppendUint(dst, uint64(vals[0]), 10)
269	if len(vals) > 1 {
270		for _, val := range vals[1:] {
271			dst = strconv.AppendUint(append(dst, ','), uint64(val), 10)
272		}
273	}
274	dst = append(dst, ']')
275	return dst
276}
277
278// AppendUint64 converts the input uint64 to a string and
279// appends the encoded string to the input byte slice.
280func (Encoder) AppendUint64(dst []byte, val uint64) []byte {
281	return strconv.AppendUint(dst, uint64(val), 10)
282}
283
284// AppendUints64 encodes the input uint64s to json and
285// appends the encoded string list to the input byte slice.
286func (Encoder) AppendUints64(dst []byte, vals []uint64) []byte {
287	if len(vals) == 0 {
288		return append(dst, '[', ']')
289	}
290	dst = append(dst, '[')
291	dst = strconv.AppendUint(dst, vals[0], 10)
292	if len(vals) > 1 {
293		for _, val := range vals[1:] {
294			dst = strconv.AppendUint(append(dst, ','), val, 10)
295		}
296	}
297	dst = append(dst, ']')
298	return dst
299}
300
301func appendFloat(dst []byte, val float64, bitSize int) []byte {
302	// JSON does not permit NaN or Infinity. A typical JSON encoder would fail
303	// with an error, but a logging library wants the data to get thru so we
304	// make a tradeoff and store those types as string.
305	switch {
306	case math.IsNaN(val):
307		return append(dst, `"NaN"`...)
308	case math.IsInf(val, 1):
309		return append(dst, `"+Inf"`...)
310	case math.IsInf(val, -1):
311		return append(dst, `"-Inf"`...)
312	}
313	return strconv.AppendFloat(dst, val, 'f', -1, bitSize)
314}
315
316// AppendFloat32 converts the input float32 to a string and
317// appends the encoded string to the input byte slice.
318func (Encoder) AppendFloat32(dst []byte, val float32) []byte {
319	return appendFloat(dst, float64(val), 32)
320}
321
322// AppendFloats32 encodes the input float32s to json and
323// appends the encoded string list to the input byte slice.
324func (Encoder) AppendFloats32(dst []byte, vals []float32) []byte {
325	if len(vals) == 0 {
326		return append(dst, '[', ']')
327	}
328	dst = append(dst, '[')
329	dst = appendFloat(dst, float64(vals[0]), 32)
330	if len(vals) > 1 {
331		for _, val := range vals[1:] {
332			dst = appendFloat(append(dst, ','), float64(val), 32)
333		}
334	}
335	dst = append(dst, ']')
336	return dst
337}
338
339// AppendFloat64 converts the input float64 to a string and
340// appends the encoded string to the input byte slice.
341func (Encoder) AppendFloat64(dst []byte, val float64) []byte {
342	return appendFloat(dst, val, 64)
343}
344
345// AppendFloats64 encodes the input float64s to json and
346// appends the encoded string list to the input byte slice.
347func (Encoder) AppendFloats64(dst []byte, vals []float64) []byte {
348	if len(vals) == 0 {
349		return append(dst, '[', ']')
350	}
351	dst = append(dst, '[')
352	dst = appendFloat(dst, vals[0], 64)
353	if len(vals) > 1 {
354		for _, val := range vals[1:] {
355			dst = appendFloat(append(dst, ','), val, 64)
356		}
357	}
358	dst = append(dst, ']')
359	return dst
360}
361
362// AppendInterface marshals the input interface to a string and
363// appends the encoded string to the input byte slice.
364func (e Encoder) AppendInterface(dst []byte, i interface{}) []byte {
365	marshaled, err := JSONMarshalFunc(i)
366	if err != nil {
367		return e.AppendString(dst, fmt.Sprintf("marshaling error: %v", err))
368	}
369	return append(dst, marshaled...)
370}
371
372// AppendObjectData takes in an object that is already in a byte array
373// and adds it to the dst.
374func (Encoder) AppendObjectData(dst []byte, o []byte) []byte {
375	// Three conditions apply here:
376	// 1. new content starts with '{' - which should be dropped   OR
377	// 2. new content starts with '{' - which should be replaced with ','
378	//    to separate with existing content OR
379	// 3. existing content has already other fields
380	if o[0] == '{' {
381		if len(dst) > 1 {
382			dst = append(dst, ',')
383		}
384		o = o[1:]
385	} else if len(dst) > 1 {
386		dst = append(dst, ',')
387	}
388	return append(dst, o...)
389}
390
391// AppendIPAddr adds IPv4 or IPv6 address to dst.
392func (e Encoder) AppendIPAddr(dst []byte, ip net.IP) []byte {
393	return e.AppendString(dst, ip.String())
394}
395
396// AppendIPPrefix adds IPv4 or IPv6 Prefix (address & mask) to dst.
397func (e Encoder) AppendIPPrefix(dst []byte, pfx net.IPNet) []byte {
398	return e.AppendString(dst, pfx.String())
399
400}
401
402// AppendMACAddr adds MAC address to dst.
403func (e Encoder) AppendMACAddr(dst []byte, ha net.HardwareAddr) []byte {
404	return e.AppendString(dst, ha.String())
405}
406