blob: eb4f697f0ae6b8d8b20c3419c6c9c7aa200e9adc [file] [log] [blame]
khenaidooac637102019-01-14 15:44:34 -05001package cbor
2
3import (
4 "encoding/json"
5 "fmt"
6 "math"
7 "net"
8)
9
10// AppendNil inserts a 'Nil' object into the dst byte array.
11func (Encoder) AppendNil(dst []byte) []byte {
12 return append(dst, byte(majorTypeSimpleAndFloat|additionalTypeNull))
13}
14
15// AppendBeginMarker inserts a map start into the dst byte array.
16func (Encoder) AppendBeginMarker(dst []byte) []byte {
17 return append(dst, byte(majorTypeMap|additionalTypeInfiniteCount))
18}
19
20// AppendEndMarker inserts a map end into the dst byte array.
21func (Encoder) AppendEndMarker(dst []byte) []byte {
22 return append(dst, byte(majorTypeSimpleAndFloat|additionalTypeBreak))
23}
24
25// AppendObjectData takes an object in form of a byte array and appends to dst.
26func (Encoder) AppendObjectData(dst []byte, o []byte) []byte {
27 // BeginMarker is present in the dst, which
28 // should not be copied when appending to existing data.
29 return append(dst, o[1:]...)
30}
31
32// AppendArrayStart adds markers to indicate the start of an array.
33func (Encoder) AppendArrayStart(dst []byte) []byte {
34 return append(dst, byte(majorTypeArray|additionalTypeInfiniteCount))
35}
36
37// AppendArrayEnd adds markers to indicate the end of an array.
38func (Encoder) AppendArrayEnd(dst []byte) []byte {
39 return append(dst, byte(majorTypeSimpleAndFloat|additionalTypeBreak))
40}
41
42// AppendArrayDelim adds markers to indicate end of a particular array element.
43func (Encoder) AppendArrayDelim(dst []byte) []byte {
44 //No delimiters needed in cbor
45 return dst
46}
47
48// AppendLineBreak is a noop that keep API compat with json encoder.
49func (Encoder) AppendLineBreak(dst []byte) []byte {
50 // No line breaks needed in binary format.
51 return dst
52}
53
54// AppendBool encodes and inserts a boolean value into the dst byte array.
55func (Encoder) AppendBool(dst []byte, val bool) []byte {
56 b := additionalTypeBoolFalse
57 if val {
58 b = additionalTypeBoolTrue
59 }
60 return append(dst, byte(majorTypeSimpleAndFloat|b))
61}
62
63// AppendBools encodes and inserts an array of boolean values into the dst byte array.
64func (e Encoder) AppendBools(dst []byte, vals []bool) []byte {
65 major := majorTypeArray
66 l := len(vals)
67 if l == 0 {
68 return e.AppendArrayEnd(e.AppendArrayStart(dst))
69 }
70 if l <= additionalMax {
71 lb := byte(l)
72 dst = append(dst, byte(major|lb))
73 } else {
74 dst = appendCborTypePrefix(dst, major, uint64(l))
75 }
76 for _, v := range vals {
77 dst = e.AppendBool(dst, v)
78 }
79 return dst
80}
81
82// AppendInt encodes and inserts an integer value into the dst byte array.
83func (Encoder) AppendInt(dst []byte, val int) []byte {
84 major := majorTypeUnsignedInt
85 contentVal := val
86 if val < 0 {
87 major = majorTypeNegativeInt
88 contentVal = -val - 1
89 }
90 if contentVal <= additionalMax {
91 lb := byte(contentVal)
92 dst = append(dst, byte(major|lb))
93 } else {
94 dst = appendCborTypePrefix(dst, major, uint64(contentVal))
95 }
96 return dst
97}
98
99// AppendInts encodes and inserts an array of integer values into the dst byte array.
100func (e Encoder) AppendInts(dst []byte, vals []int) []byte {
101 major := majorTypeArray
102 l := len(vals)
103 if l == 0 {
104 return e.AppendArrayEnd(e.AppendArrayStart(dst))
105 }
106 if l <= additionalMax {
107 lb := byte(l)
108 dst = append(dst, byte(major|lb))
109 } else {
110 dst = appendCborTypePrefix(dst, major, uint64(l))
111 }
112 for _, v := range vals {
113 dst = e.AppendInt(dst, v)
114 }
115 return dst
116}
117
118// AppendInt8 encodes and inserts an int8 value into the dst byte array.
119func (e Encoder) AppendInt8(dst []byte, val int8) []byte {
120 return e.AppendInt(dst, int(val))
121}
122
123// AppendInts8 encodes and inserts an array of integer values into the dst byte array.
124func (e Encoder) AppendInts8(dst []byte, vals []int8) []byte {
125 major := majorTypeArray
126 l := len(vals)
127 if l == 0 {
128 return e.AppendArrayEnd(e.AppendArrayStart(dst))
129 }
130 if l <= additionalMax {
131 lb := byte(l)
132 dst = append(dst, byte(major|lb))
133 } else {
134 dst = appendCborTypePrefix(dst, major, uint64(l))
135 }
136 for _, v := range vals {
137 dst = e.AppendInt(dst, int(v))
138 }
139 return dst
140}
141
142// AppendInt16 encodes and inserts a int16 value into the dst byte array.
143func (e Encoder) AppendInt16(dst []byte, val int16) []byte {
144 return e.AppendInt(dst, int(val))
145}
146
147// AppendInts16 encodes and inserts an array of int16 values into the dst byte array.
148func (e Encoder) AppendInts16(dst []byte, vals []int16) []byte {
149 major := majorTypeArray
150 l := len(vals)
151 if l == 0 {
152 return e.AppendArrayEnd(e.AppendArrayStart(dst))
153 }
154 if l <= additionalMax {
155 lb := byte(l)
156 dst = append(dst, byte(major|lb))
157 } else {
158 dst = appendCborTypePrefix(dst, major, uint64(l))
159 }
160 for _, v := range vals {
161 dst = e.AppendInt(dst, int(v))
162 }
163 return dst
164}
165
166// AppendInt32 encodes and inserts a int32 value into the dst byte array.
167func (e Encoder) AppendInt32(dst []byte, val int32) []byte {
168 return e.AppendInt(dst, int(val))
169}
170
171// AppendInts32 encodes and inserts an array of int32 values into the dst byte array.
172func (e Encoder) AppendInts32(dst []byte, vals []int32) []byte {
173 major := majorTypeArray
174 l := len(vals)
175 if l == 0 {
176 return e.AppendArrayEnd(e.AppendArrayStart(dst))
177 }
178 if l <= additionalMax {
179 lb := byte(l)
180 dst = append(dst, byte(major|lb))
181 } else {
182 dst = appendCborTypePrefix(dst, major, uint64(l))
183 }
184 for _, v := range vals {
185 dst = e.AppendInt(dst, int(v))
186 }
187 return dst
188}
189
190// AppendInt64 encodes and inserts a int64 value into the dst byte array.
191func (Encoder) AppendInt64(dst []byte, val int64) []byte {
192 major := majorTypeUnsignedInt
193 contentVal := val
194 if val < 0 {
195 major = majorTypeNegativeInt
196 contentVal = -val - 1
197 }
198 if contentVal <= additionalMax {
199 lb := byte(contentVal)
200 dst = append(dst, byte(major|lb))
201 } else {
202 dst = appendCborTypePrefix(dst, major, uint64(contentVal))
203 }
204 return dst
205}
206
207// AppendInts64 encodes and inserts an array of int64 values into the dst byte array.
208func (e Encoder) AppendInts64(dst []byte, vals []int64) []byte {
209 major := majorTypeArray
210 l := len(vals)
211 if l == 0 {
212 return e.AppendArrayEnd(e.AppendArrayStart(dst))
213 }
214 if l <= additionalMax {
215 lb := byte(l)
216 dst = append(dst, byte(major|lb))
217 } else {
218 dst = appendCborTypePrefix(dst, major, uint64(l))
219 }
220 for _, v := range vals {
221 dst = e.AppendInt64(dst, v)
222 }
223 return dst
224}
225
226// AppendUint encodes and inserts an unsigned integer value into the dst byte array.
227func (e Encoder) AppendUint(dst []byte, val uint) []byte {
228 return e.AppendInt64(dst, int64(val))
229}
230
231// AppendUints encodes and inserts an array of unsigned integer values into the dst byte array.
232func (e Encoder) AppendUints(dst []byte, vals []uint) []byte {
233 major := majorTypeArray
234 l := len(vals)
235 if l == 0 {
236 return e.AppendArrayEnd(e.AppendArrayStart(dst))
237 }
238 if l <= additionalMax {
239 lb := byte(l)
240 dst = append(dst, byte(major|lb))
241 } else {
242 dst = appendCborTypePrefix(dst, major, uint64(l))
243 }
244 for _, v := range vals {
245 dst = e.AppendUint(dst, v)
246 }
247 return dst
248}
249
250// AppendUint8 encodes and inserts a unsigned int8 value into the dst byte array.
251func (e Encoder) AppendUint8(dst []byte, val uint8) []byte {
252 return e.AppendUint(dst, uint(val))
253}
254
255// AppendUints8 encodes and inserts an array of uint8 values into the dst byte array.
256func (e Encoder) AppendUints8(dst []byte, vals []uint8) []byte {
257 major := majorTypeArray
258 l := len(vals)
259 if l == 0 {
260 return e.AppendArrayEnd(e.AppendArrayStart(dst))
261 }
262 if l <= additionalMax {
263 lb := byte(l)
264 dst = append(dst, byte(major|lb))
265 } else {
266 dst = appendCborTypePrefix(dst, major, uint64(l))
267 }
268 for _, v := range vals {
269 dst = e.AppendUint8(dst, v)
270 }
271 return dst
272}
273
274// AppendUint16 encodes and inserts a uint16 value into the dst byte array.
275func (e Encoder) AppendUint16(dst []byte, val uint16) []byte {
276 return e.AppendUint(dst, uint(val))
277}
278
279// AppendUints16 encodes and inserts an array of uint16 values into the dst byte array.
280func (e Encoder) AppendUints16(dst []byte, vals []uint16) []byte {
281 major := majorTypeArray
282 l := len(vals)
283 if l == 0 {
284 return e.AppendArrayEnd(e.AppendArrayStart(dst))
285 }
286 if l <= additionalMax {
287 lb := byte(l)
288 dst = append(dst, byte(major|lb))
289 } else {
290 dst = appendCborTypePrefix(dst, major, uint64(l))
291 }
292 for _, v := range vals {
293 dst = e.AppendUint16(dst, v)
294 }
295 return dst
296}
297
298// AppendUint32 encodes and inserts a uint32 value into the dst byte array.
299func (e Encoder) AppendUint32(dst []byte, val uint32) []byte {
300 return e.AppendUint(dst, uint(val))
301}
302
303// AppendUints32 encodes and inserts an array of uint32 values into the dst byte array.
304func (e Encoder) AppendUints32(dst []byte, vals []uint32) []byte {
305 major := majorTypeArray
306 l := len(vals)
307 if l == 0 {
308 return e.AppendArrayEnd(e.AppendArrayStart(dst))
309 }
310 if l <= additionalMax {
311 lb := byte(l)
312 dst = append(dst, byte(major|lb))
313 } else {
314 dst = appendCborTypePrefix(dst, major, uint64(l))
315 }
316 for _, v := range vals {
317 dst = e.AppendUint32(dst, v)
318 }
319 return dst
320}
321
322// AppendUint64 encodes and inserts a uint64 value into the dst byte array.
323func (Encoder) AppendUint64(dst []byte, val uint64) []byte {
324 major := majorTypeUnsignedInt
325 contentVal := val
326 if contentVal <= additionalMax {
327 lb := byte(contentVal)
328 dst = append(dst, byte(major|lb))
329 } else {
330 dst = appendCborTypePrefix(dst, major, uint64(contentVal))
331 }
332 return dst
333}
334
335// AppendUints64 encodes and inserts an array of uint64 values into the dst byte array.
336func (e Encoder) AppendUints64(dst []byte, vals []uint64) []byte {
337 major := majorTypeArray
338 l := len(vals)
339 if l == 0 {
340 return e.AppendArrayEnd(e.AppendArrayStart(dst))
341 }
342 if l <= additionalMax {
343 lb := byte(l)
344 dst = append(dst, byte(major|lb))
345 } else {
346 dst = appendCborTypePrefix(dst, major, uint64(l))
347 }
348 for _, v := range vals {
349 dst = e.AppendUint64(dst, v)
350 }
351 return dst
352}
353
354// AppendFloat32 encodes and inserts a single precision float value into the dst byte array.
355func (Encoder) AppendFloat32(dst []byte, val float32) []byte {
356 switch {
357 case math.IsNaN(float64(val)):
358 return append(dst, "\xfa\x7f\xc0\x00\x00"...)
359 case math.IsInf(float64(val), 1):
360 return append(dst, "\xfa\x7f\x80\x00\x00"...)
361 case math.IsInf(float64(val), -1):
362 return append(dst, "\xfa\xff\x80\x00\x00"...)
363 }
364 major := majorTypeSimpleAndFloat
365 subType := additionalTypeFloat32
366 n := math.Float32bits(val)
367 var buf [4]byte
368 for i := uint(0); i < 4; i++ {
369 buf[i] = byte(n >> ((3 - i) * 8))
370 }
371 return append(append(dst, byte(major|subType)), buf[0], buf[1], buf[2], buf[3])
372}
373
374// AppendFloats32 encodes and inserts an array of single precision float value into the dst byte array.
375func (e Encoder) AppendFloats32(dst []byte, vals []float32) []byte {
376 major := majorTypeArray
377 l := len(vals)
378 if l == 0 {
379 return e.AppendArrayEnd(e.AppendArrayStart(dst))
380 }
381 if l <= additionalMax {
382 lb := byte(l)
383 dst = append(dst, byte(major|lb))
384 } else {
385 dst = appendCborTypePrefix(dst, major, uint64(l))
386 }
387 for _, v := range vals {
388 dst = e.AppendFloat32(dst, v)
389 }
390 return dst
391}
392
393// AppendFloat64 encodes and inserts a double precision float value into the dst byte array.
394func (Encoder) AppendFloat64(dst []byte, val float64) []byte {
395 switch {
396 case math.IsNaN(val):
397 return append(dst, "\xfb\x7f\xf8\x00\x00\x00\x00\x00\x00"...)
398 case math.IsInf(val, 1):
399 return append(dst, "\xfb\x7f\xf0\x00\x00\x00\x00\x00\x00"...)
400 case math.IsInf(val, -1):
401 return append(dst, "\xfb\xff\xf0\x00\x00\x00\x00\x00\x00"...)
402 }
403 major := majorTypeSimpleAndFloat
404 subType := additionalTypeFloat64
405 n := math.Float64bits(val)
406 dst = append(dst, byte(major|subType))
407 for i := uint(1); i <= 8; i++ {
408 b := byte(n >> ((8 - i) * 8))
409 dst = append(dst, b)
410 }
411 return dst
412}
413
414// AppendFloats64 encodes and inserts an array of double precision float values into the dst byte array.
415func (e Encoder) AppendFloats64(dst []byte, vals []float64) []byte {
416 major := majorTypeArray
417 l := len(vals)
418 if l == 0 {
419 return e.AppendArrayEnd(e.AppendArrayStart(dst))
420 }
421 if l <= additionalMax {
422 lb := byte(l)
423 dst = append(dst, byte(major|lb))
424 } else {
425 dst = appendCborTypePrefix(dst, major, uint64(l))
426 }
427 for _, v := range vals {
428 dst = e.AppendFloat64(dst, v)
429 }
430 return dst
431}
432
433// AppendInterface takes an arbitrary object and converts it to JSON and embeds it dst.
434func (e Encoder) AppendInterface(dst []byte, i interface{}) []byte {
435 marshaled, err := json.Marshal(i)
436 if err != nil {
437 return e.AppendString(dst, fmt.Sprintf("marshaling error: %v", err))
438 }
439 return AppendEmbeddedJSON(dst, marshaled)
440}
441
442// AppendIPAddr encodes and inserts an IP Address (IPv4 or IPv6).
443func (e Encoder) AppendIPAddr(dst []byte, ip net.IP) []byte {
444 dst = append(dst, byte(majorTypeTags|additionalTypeIntUint16))
445 dst = append(dst, byte(additionalTypeTagNetworkAddr>>8))
446 dst = append(dst, byte(additionalTypeTagNetworkAddr&0xff))
447 return e.AppendBytes(dst, ip)
448}
449
450// AppendIPPrefix encodes and inserts an IP Address Prefix (Address + Mask Length).
451func (e Encoder) AppendIPPrefix(dst []byte, pfx net.IPNet) []byte {
452 dst = append(dst, byte(majorTypeTags|additionalTypeIntUint16))
453 dst = append(dst, byte(additionalTypeTagNetworkPrefix>>8))
454 dst = append(dst, byte(additionalTypeTagNetworkPrefix&0xff))
455
456 // Prefix is a tuple (aka MAP of 1 pair of elements) -
457 // first element is prefix, second is mask length.
458 dst = append(dst, byte(majorTypeMap|0x1))
459 dst = e.AppendBytes(dst, pfx.IP)
460 maskLen, _ := pfx.Mask.Size()
461 return e.AppendUint8(dst, uint8(maskLen))
462}
463
464// AppendMACAddr encodes and inserts an Hardware (MAC) address.
465func (e Encoder) AppendMACAddr(dst []byte, ha net.HardwareAddr) []byte {
466 dst = append(dst, byte(majorTypeTags|additionalTypeIntUint16))
467 dst = append(dst, byte(additionalTypeTagNetworkAddr>>8))
468 dst = append(dst, byte(additionalTypeTagNetworkAddr&0xff))
469 return e.AppendBytes(dst, ha)
470}
471
472// AppendHex adds a TAG and inserts a hex bytes as a string.
473func (e Encoder) AppendHex(dst []byte, val []byte) []byte {
474 dst = append(dst, byte(majorTypeTags|additionalTypeIntUint16))
475 dst = append(dst, byte(additionalTypeTagHexString>>8))
476 dst = append(dst, byte(additionalTypeTagHexString&0xff))
477 return e.AppendBytes(dst, val)
478}