1package zerolog
2
3import (
4	"net"
5	"sync"
6	"time"
7)
8
9var arrayPool = &sync.Pool{
10	New: func() interface{} {
11		return &Array{
12			buf: make([]byte, 0, 500),
13		}
14	},
15}
16
17// Array is used to prepopulate an array of items
18// which can be re-used to add to log messages.
19type Array struct {
20	buf []byte
21}
22
23func putArray(a *Array) {
24	// Proper usage of a sync.Pool requires each entry to have approximately
25	// the same memory cost. To obtain this property when the stored type
26	// contains a variably-sized buffer, we add a hard limit on the maximum buffer
27	// to place back in the pool.
28	//
29	// See https://golang.org/issue/23199
30	const maxSize = 1 << 16 // 64KiB
31	if cap(a.buf) > maxSize {
32		return
33	}
34	arrayPool.Put(a)
35}
36
37// Arr creates an array to be added to an Event or Context.
38func Arr() *Array {
39	a := arrayPool.Get().(*Array)
40	a.buf = a.buf[:0]
41	return a
42}
43
44// MarshalZerologArray method here is no-op - since data is
45// already in the needed format.
46func (*Array) MarshalZerologArray(*Array) {
47}
48
49func (a *Array) write(dst []byte) []byte {
50	dst = enc.AppendArrayStart(dst)
51	if len(a.buf) > 0 {
52		dst = append(append(dst, a.buf...))
53	}
54	dst = enc.AppendArrayEnd(dst)
55	putArray(a)
56	return dst
57}
58
59// Object marshals an object that implement the LogObjectMarshaler
60// interface and append append it to the array.
61func (a *Array) Object(obj LogObjectMarshaler) *Array {
62	e := Dict()
63	obj.MarshalZerologObject(e)
64	e.buf = enc.AppendEndMarker(e.buf)
65	a.buf = append(enc.AppendArrayDelim(a.buf), e.buf...)
66	putEvent(e)
67	return a
68}
69
70// Str append append the val as a string to the array.
71func (a *Array) Str(val string) *Array {
72	a.buf = enc.AppendString(enc.AppendArrayDelim(a.buf), val)
73	return a
74}
75
76// Bytes append append the val as a string to the array.
77func (a *Array) Bytes(val []byte) *Array {
78	a.buf = enc.AppendBytes(enc.AppendArrayDelim(a.buf), val)
79	return a
80}
81
82// Hex append append the val as a hex string to the array.
83func (a *Array) Hex(val []byte) *Array {
84	a.buf = enc.AppendHex(enc.AppendArrayDelim(a.buf), val)
85	return a
86}
87
88// RawJSON adds already encoded JSON to the array.
89func (a *Array) RawJSON(val []byte) *Array {
90	a.buf = appendJSON(enc.AppendArrayDelim(a.buf), val)
91	return a
92}
93
94// Err serializes and appends the err to the array.
95func (a *Array) Err(err error) *Array {
96	switch m := ErrorMarshalFunc(err).(type) {
97	case LogObjectMarshaler:
98		e := newEvent(nil, 0)
99		e.buf = e.buf[:0]
100		e.appendObject(m)
101		a.buf = append(enc.AppendArrayDelim(a.buf), e.buf...)
102		putEvent(e)
103	case error:
104		if m == nil || isNilValue(m) {
105			a.buf = enc.AppendNil(enc.AppendArrayDelim(a.buf))
106		} else {
107			a.buf = enc.AppendString(enc.AppendArrayDelim(a.buf), m.Error())
108		}
109	case string:
110		a.buf = enc.AppendString(enc.AppendArrayDelim(a.buf), m)
111	default:
112		a.buf = enc.AppendInterface(enc.AppendArrayDelim(a.buf), m)
113	}
114
115	return a
116}
117
118// Bool append append the val as a bool to the array.
119func (a *Array) Bool(b bool) *Array {
120	a.buf = enc.AppendBool(enc.AppendArrayDelim(a.buf), b)
121	return a
122}
123
124// Int append append i as a int to the array.
125func (a *Array) Int(i int) *Array {
126	a.buf = enc.AppendInt(enc.AppendArrayDelim(a.buf), i)
127	return a
128}
129
130// Int8 append append i as a int8 to the array.
131func (a *Array) Int8(i int8) *Array {
132	a.buf = enc.AppendInt8(enc.AppendArrayDelim(a.buf), i)
133	return a
134}
135
136// Int16 append append i as a int16 to the array.
137func (a *Array) Int16(i int16) *Array {
138	a.buf = enc.AppendInt16(enc.AppendArrayDelim(a.buf), i)
139	return a
140}
141
142// Int32 append append i as a int32 to the array.
143func (a *Array) Int32(i int32) *Array {
144	a.buf = enc.AppendInt32(enc.AppendArrayDelim(a.buf), i)
145	return a
146}
147
148// Int64 append append i as a int64 to the array.
149func (a *Array) Int64(i int64) *Array {
150	a.buf = enc.AppendInt64(enc.AppendArrayDelim(a.buf), i)
151	return a
152}
153
154// Uint append append i as a uint to the array.
155func (a *Array) Uint(i uint) *Array {
156	a.buf = enc.AppendUint(enc.AppendArrayDelim(a.buf), i)
157	return a
158}
159
160// Uint8 append append i as a uint8 to the array.
161func (a *Array) Uint8(i uint8) *Array {
162	a.buf = enc.AppendUint8(enc.AppendArrayDelim(a.buf), i)
163	return a
164}
165
166// Uint16 append append i as a uint16 to the array.
167func (a *Array) Uint16(i uint16) *Array {
168	a.buf = enc.AppendUint16(enc.AppendArrayDelim(a.buf), i)
169	return a
170}
171
172// Uint32 append append i as a uint32 to the array.
173func (a *Array) Uint32(i uint32) *Array {
174	a.buf = enc.AppendUint32(enc.AppendArrayDelim(a.buf), i)
175	return a
176}
177
178// Uint64 append append i as a uint64 to the array.
179func (a *Array) Uint64(i uint64) *Array {
180	a.buf = enc.AppendUint64(enc.AppendArrayDelim(a.buf), i)
181	return a
182}
183
184// Float32 append append f as a float32 to the array.
185func (a *Array) Float32(f float32) *Array {
186	a.buf = enc.AppendFloat32(enc.AppendArrayDelim(a.buf), f)
187	return a
188}
189
190// Float64 append append f as a float64 to the array.
191func (a *Array) Float64(f float64) *Array {
192	a.buf = enc.AppendFloat64(enc.AppendArrayDelim(a.buf), f)
193	return a
194}
195
196// Time append append t formated as string using zerolog.TimeFieldFormat.
197func (a *Array) Time(t time.Time) *Array {
198	a.buf = enc.AppendTime(enc.AppendArrayDelim(a.buf), t, TimeFieldFormat)
199	return a
200}
201
202// Dur append append d to the array.
203func (a *Array) Dur(d time.Duration) *Array {
204	a.buf = enc.AppendDuration(enc.AppendArrayDelim(a.buf), d, DurationFieldUnit, DurationFieldInteger)
205	return a
206}
207
208// Interface append append i marshaled using reflection.
209func (a *Array) Interface(i interface{}) *Array {
210	if obj, ok := i.(LogObjectMarshaler); ok {
211		return a.Object(obj)
212	}
213	a.buf = enc.AppendInterface(enc.AppendArrayDelim(a.buf), i)
214	return a
215}
216
217// IPAddr adds IPv4 or IPv6 address to the array
218func (a *Array) IPAddr(ip net.IP) *Array {
219	a.buf = enc.AppendIPAddr(enc.AppendArrayDelim(a.buf), ip)
220	return a
221}
222
223// IPPrefix adds IPv4 or IPv6 Prefix (IP + mask) to the array
224func (a *Array) IPPrefix(pfx net.IPNet) *Array {
225	a.buf = enc.AppendIPPrefix(enc.AppendArrayDelim(a.buf), pfx)
226	return a
227}
228
229// MACAddr adds a MAC (Ethernet) address to the array
230func (a *Array) MACAddr(ha net.HardwareAddr) *Array {
231	a.buf = enc.AppendMACAddr(enc.AppendArrayDelim(a.buf), ha)
232	return a
233}
234