summaryrefslogtreecommitdiffstats
path: root/vendor/github.com/rs/zerolog/internal/cbor
diff options
context:
space:
mode:
authormsglm <msglm@techchud.xyz>2023-10-27 07:08:25 -0500
committermsglm <msglm@techchud.xyz>2023-10-27 07:08:25 -0500
commit032a7e0c1188d3507b8d9a9571f2446a43cf775b (patch)
tree2bd38c01bc7761a6195e426082ce7191ebc765a1 /vendor/github.com/rs/zerolog/internal/cbor
parent56e7bd01ca09ad52b0c4f48f146a20a4f1b78696 (diff)
downloadmatterbridge-msglm-1.26.0+0.1.0.tar.gz
matterbridge-msglm-1.26.0+0.1.0.tar.bz2
matterbridge-msglm-1.26.0+0.1.0.zip
apply https://github.com/42wim/matterbridge/pull/1864v1.26.0+0.1.0
Diffstat (limited to 'vendor/github.com/rs/zerolog/internal/cbor')
-rw-r--r--vendor/github.com/rs/zerolog/internal/cbor/README.md56
-rw-r--r--vendor/github.com/rs/zerolog/internal/cbor/base.go19
-rw-r--r--vendor/github.com/rs/zerolog/internal/cbor/cbor.go101
-rw-r--r--vendor/github.com/rs/zerolog/internal/cbor/decode_stream.go614
-rw-r--r--vendor/github.com/rs/zerolog/internal/cbor/string.go95
-rw-r--r--vendor/github.com/rs/zerolog/internal/cbor/time.go93
-rw-r--r--vendor/github.com/rs/zerolog/internal/cbor/types.go486
7 files changed, 1464 insertions, 0 deletions
diff --git a/vendor/github.com/rs/zerolog/internal/cbor/README.md b/vendor/github.com/rs/zerolog/internal/cbor/README.md
new file mode 100644
index 00000000..92c2e8c7
--- /dev/null
+++ b/vendor/github.com/rs/zerolog/internal/cbor/README.md
@@ -0,0 +1,56 @@
+## Reference:
+ CBOR Encoding is described in [RFC7049](https://tools.ietf.org/html/rfc7049)
+
+## Comparison of JSON vs CBOR
+
+Two main areas of reduction are:
+
+1. CPU usage to write a log msg
+2. Size (in bytes) of log messages.
+
+
+CPU Usage savings are below:
+```
+name JSON time/op CBOR time/op delta
+Info-32 15.3ns ± 1% 11.7ns ± 3% -23.78% (p=0.000 n=9+10)
+ContextFields-32 16.2ns ± 2% 12.3ns ± 3% -23.97% (p=0.000 n=9+9)
+ContextAppend-32 6.70ns ± 0% 6.20ns ± 0% -7.44% (p=0.000 n=9+9)
+LogFields-32 66.4ns ± 0% 24.6ns ± 2% -62.89% (p=0.000 n=10+9)
+LogArrayObject-32 911ns ±11% 768ns ± 6% -15.64% (p=0.000 n=10+10)
+LogFieldType/Floats-32 70.3ns ± 2% 29.5ns ± 1% -57.98% (p=0.000 n=10+10)
+LogFieldType/Err-32 14.0ns ± 3% 12.1ns ± 8% -13.20% (p=0.000 n=8+10)
+LogFieldType/Dur-32 17.2ns ± 2% 13.1ns ± 1% -24.27% (p=0.000 n=10+9)
+LogFieldType/Object-32 54.3ns ±11% 52.3ns ± 7% ~ (p=0.239 n=10+10)
+LogFieldType/Ints-32 20.3ns ± 2% 15.1ns ± 2% -25.50% (p=0.000 n=9+10)
+LogFieldType/Interfaces-32 642ns ±11% 621ns ± 9% ~ (p=0.118 n=10+10)
+LogFieldType/Interface(Objects)-32 635ns ±13% 632ns ± 9% ~ (p=0.592 n=10+10)
+LogFieldType/Times-32 294ns ± 0% 27ns ± 1% -90.71% (p=0.000 n=10+9)
+LogFieldType/Durs-32 121ns ± 0% 33ns ± 2% -72.44% (p=0.000 n=9+9)
+LogFieldType/Interface(Object)-32 56.6ns ± 8% 52.3ns ± 8% -7.54% (p=0.007 n=10+10)
+LogFieldType/Errs-32 17.8ns ± 3% 16.1ns ± 2% -9.71% (p=0.000 n=10+9)
+LogFieldType/Time-32 40.5ns ± 1% 12.7ns ± 6% -68.66% (p=0.000 n=8+9)
+LogFieldType/Bool-32 12.0ns ± 5% 10.2ns ± 2% -15.18% (p=0.000 n=10+8)
+LogFieldType/Bools-32 17.2ns ± 2% 12.6ns ± 4% -26.63% (p=0.000 n=10+10)
+LogFieldType/Int-32 12.3ns ± 2% 11.2ns ± 4% -9.27% (p=0.000 n=9+10)
+LogFieldType/Float-32 16.7ns ± 1% 12.6ns ± 2% -24.42% (p=0.000 n=7+9)
+LogFieldType/Str-32 12.7ns ± 7% 11.3ns ± 7% -10.88% (p=0.000 n=10+9)
+LogFieldType/Strs-32 20.3ns ± 3% 18.2ns ± 3% -10.25% (p=0.000 n=9+10)
+LogFieldType/Interface-32 183ns ±12% 175ns ± 9% ~ (p=0.078 n=10+10)
+```
+
+Log message size savings is greatly dependent on the number and type of fields in the log message.
+Assuming this log message (with an Integer, timestamp and string, in addition to level).
+
+`{"level":"error","Fault":41650,"time":"2018-04-01T15:18:19-07:00","message":"Some Message"}`
+
+Two measurements were done for the log file sizes - one without any compression, second
+using [compress/zlib](https://golang.org/pkg/compress/zlib/).
+
+Results for 10,000 log messages:
+
+| Log Format | Plain File Size (in KB) | Compressed File Size (in KB) |
+| :--- | :---: | :---: |
+| JSON | 920 | 28 |
+| CBOR | 550 | 28 |
+
+The example used to calculate the above data is available in [Examples](examples).
diff --git a/vendor/github.com/rs/zerolog/internal/cbor/base.go b/vendor/github.com/rs/zerolog/internal/cbor/base.go
new file mode 100644
index 00000000..51fe86c9
--- /dev/null
+++ b/vendor/github.com/rs/zerolog/internal/cbor/base.go
@@ -0,0 +1,19 @@
+package cbor
+
+// JSONMarshalFunc is used to marshal interface to JSON encoded byte slice.
+// Making it package level instead of embedded in Encoder brings
+// some extra efforts at importing, but avoids value copy when the functions
+// of Encoder being invoked.
+// DO REMEMBER to set this variable at importing, or
+// you might get a nil pointer dereference panic at runtime.
+var JSONMarshalFunc func(v interface{}) ([]byte, error)
+
+type Encoder struct{}
+
+// AppendKey adds a key (string) to the binary encoded log message
+func (e Encoder) AppendKey(dst []byte, key string) []byte {
+ if len(dst) < 1 {
+ dst = e.AppendBeginMarker(dst)
+ }
+ return e.AppendString(dst, key)
+}
diff --git a/vendor/github.com/rs/zerolog/internal/cbor/cbor.go b/vendor/github.com/rs/zerolog/internal/cbor/cbor.go
new file mode 100644
index 00000000..bc54e37a
--- /dev/null
+++ b/vendor/github.com/rs/zerolog/internal/cbor/cbor.go
@@ -0,0 +1,101 @@
+// Package cbor provides primitives for storing different data
+// in the CBOR (binary) format. CBOR is defined in RFC7049.
+package cbor
+
+import "time"
+
+const (
+ majorOffset = 5
+ additionalMax = 23
+
+ // Non Values.
+ additionalTypeBoolFalse byte = 20
+ additionalTypeBoolTrue byte = 21
+ additionalTypeNull byte = 22
+
+ // Integer (+ve and -ve) Sub-types.
+ additionalTypeIntUint8 byte = 24
+ additionalTypeIntUint16 byte = 25
+ additionalTypeIntUint32 byte = 26
+ additionalTypeIntUint64 byte = 27
+
+ // Float Sub-types.
+ additionalTypeFloat16 byte = 25
+ additionalTypeFloat32 byte = 26
+ additionalTypeFloat64 byte = 27
+ additionalTypeBreak byte = 31
+
+ // Tag Sub-types.
+ additionalTypeTimestamp byte = 01
+
+ // Extended Tags - from https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml
+ additionalTypeTagNetworkAddr uint16 = 260
+ additionalTypeTagNetworkPrefix uint16 = 261
+ additionalTypeEmbeddedJSON uint16 = 262
+ additionalTypeTagHexString uint16 = 263
+
+ // Unspecified number of elements.
+ additionalTypeInfiniteCount byte = 31
+)
+const (
+ majorTypeUnsignedInt byte = iota << majorOffset // Major type 0
+ majorTypeNegativeInt // Major type 1
+ majorTypeByteString // Major type 2
+ majorTypeUtf8String // Major type 3
+ majorTypeArray // Major type 4
+ majorTypeMap // Major type 5
+ majorTypeTags // Major type 6
+ majorTypeSimpleAndFloat // Major type 7
+)
+
+const (
+ maskOutAdditionalType byte = (7 << majorOffset)
+ maskOutMajorType byte = 31
+)
+
+const (
+ float32Nan = "\xfa\x7f\xc0\x00\x00"
+ float32PosInfinity = "\xfa\x7f\x80\x00\x00"
+ float32NegInfinity = "\xfa\xff\x80\x00\x00"
+ float64Nan = "\xfb\x7f\xf8\x00\x00\x00\x00\x00\x00"
+ float64PosInfinity = "\xfb\x7f\xf0\x00\x00\x00\x00\x00\x00"
+ float64NegInfinity = "\xfb\xff\xf0\x00\x00\x00\x00\x00\x00"
+)
+
+// IntegerTimeFieldFormat indicates the format of timestamp decoded
+// from an integer (time in seconds).
+var IntegerTimeFieldFormat = time.RFC3339
+
+// NanoTimeFieldFormat indicates the format of timestamp decoded
+// from a float value (time in seconds and nanoseconds).
+var NanoTimeFieldFormat = time.RFC3339Nano
+
+func appendCborTypePrefix(dst []byte, major byte, number uint64) []byte {
+ byteCount := 8
+ var minor byte
+ switch {
+ case number < 256:
+ byteCount = 1
+ minor = additionalTypeIntUint8
+
+ case number < 65536:
+ byteCount = 2
+ minor = additionalTypeIntUint16
+
+ case number < 4294967296:
+ byteCount = 4
+ minor = additionalTypeIntUint32
+
+ default:
+ byteCount = 8
+ minor = additionalTypeIntUint64
+
+ }
+
+ dst = append(dst, major|minor)
+ byteCount--
+ for ; byteCount >= 0; byteCount-- {
+ dst = append(dst, byte(number>>(uint(byteCount)*8)))
+ }
+ return dst
+}
diff --git a/vendor/github.com/rs/zerolog/internal/cbor/decode_stream.go b/vendor/github.com/rs/zerolog/internal/cbor/decode_stream.go
new file mode 100644
index 00000000..fc16f98c
--- /dev/null
+++ b/vendor/github.com/rs/zerolog/internal/cbor/decode_stream.go
@@ -0,0 +1,614 @@
+package cbor
+
+// This file contains code to decode a stream of CBOR Data into JSON.
+
+import (
+ "bufio"
+ "bytes"
+ "fmt"
+ "io"
+ "math"
+ "net"
+ "runtime"
+ "strconv"
+ "strings"
+ "time"
+ "unicode/utf8"
+)
+
+var decodeTimeZone *time.Location
+
+const hexTable = "0123456789abcdef"
+
+const isFloat32 = 4
+const isFloat64 = 8
+
+func readNBytes(src *bufio.Reader, n int) []byte {
+ ret := make([]byte, n)
+ for i := 0; i < n; i++ {
+ ch, e := src.ReadByte()
+ if e != nil {
+ panic(fmt.Errorf("Tried to Read %d Bytes.. But hit end of file", n))
+ }
+ ret[i] = ch
+ }
+ return ret
+}
+
+func readByte(src *bufio.Reader) byte {
+ b, e := src.ReadByte()
+ if e != nil {
+ panic(fmt.Errorf("Tried to Read 1 Byte.. But hit end of file"))
+ }
+ return b
+}
+
+func decodeIntAdditionalType(src *bufio.Reader, minor byte) int64 {
+ val := int64(0)
+ if minor <= 23 {
+ val = int64(minor)
+ } else {
+ bytesToRead := 0
+ switch minor {
+ case additionalTypeIntUint8:
+ bytesToRead = 1
+ case additionalTypeIntUint16:
+ bytesToRead = 2
+ case additionalTypeIntUint32:
+ bytesToRead = 4
+ case additionalTypeIntUint64:
+ bytesToRead = 8
+ default:
+ panic(fmt.Errorf("Invalid Additional Type: %d in decodeInteger (expected <28)", minor))
+ }
+ pb := readNBytes(src, bytesToRead)
+ for i := 0; i < bytesToRead; i++ {
+ val = val * 256
+ val += int64(pb[i])
+ }
+ }
+ return val
+}
+
+func decodeInteger(src *bufio.Reader) int64 {
+ pb := readByte(src)
+ major := pb & maskOutAdditionalType
+ minor := pb & maskOutMajorType
+ if major != majorTypeUnsignedInt && major != majorTypeNegativeInt {
+ panic(fmt.Errorf("Major type is: %d in decodeInteger!! (expected 0 or 1)", major))
+ }
+ val := decodeIntAdditionalType(src, minor)
+ if major == 0 {
+ return val
+ }
+ return (-1 - val)
+}
+
+func decodeFloat(src *bufio.Reader) (float64, int) {
+ pb := readByte(src)
+ major := pb & maskOutAdditionalType
+ minor := pb & maskOutMajorType
+ if major != majorTypeSimpleAndFloat {
+ panic(fmt.Errorf("Incorrect Major type is: %d in decodeFloat", major))
+ }
+
+ switch minor {
+ case additionalTypeFloat16:
+ panic(fmt.Errorf("float16 is not suppported in decodeFloat"))
+
+ case additionalTypeFloat32:
+ pb := readNBytes(src, 4)
+ switch string(pb) {
+ case float32Nan:
+ return math.NaN(), isFloat32
+ case float32PosInfinity:
+ return math.Inf(0), isFloat32
+ case float32NegInfinity:
+ return math.Inf(-1), isFloat32
+ }
+ n := uint32(0)
+ for i := 0; i < 4; i++ {
+ n = n * 256
+ n += uint32(pb[i])
+ }
+ val := math.Float32frombits(n)
+ return float64(val), isFloat32
+ case additionalTypeFloat64:
+ pb := readNBytes(src, 8)
+ switch string(pb) {
+ case float64Nan:
+ return math.NaN(), isFloat64
+ case float64PosInfinity:
+ return math.Inf(0), isFloat64
+ case float64NegInfinity:
+ return math.Inf(-1), isFloat64
+ }
+ n := uint64(0)
+ for i := 0; i < 8; i++ {
+ n = n * 256
+ n += uint64(pb[i])
+ }
+ val := math.Float64frombits(n)
+ return val, isFloat64
+ }
+ panic(fmt.Errorf("Invalid Additional Type: %d in decodeFloat", minor))
+}
+
+func decodeStringComplex(dst []byte, s string, pos uint) []byte {
+ i := int(pos)
+ start := 0
+
+ for i < len(s) {
+ b := s[i]
+ if b >= utf8.RuneSelf {
+ r, size := utf8.DecodeRuneInString(s[i:])
+ if r == utf8.RuneError && size == 1 {
+ // In case of error, first append previous simple characters to
+ // the byte slice if any and append a replacement character code
+ // in place of the invalid sequence.
+ if start < i {
+ dst = append(dst, s[start:i]...)
+ }
+ dst = append(dst, `\ufffd`...)
+ i += size
+ start = i
+ continue
+ }
+ i += size
+ continue
+ }
+ if b >= 0x20 && b <= 0x7e && b != '\\' && b != '"' {
+ i++
+ continue
+ }
+ // We encountered a character that needs to be encoded.
+ // Let's append the previous simple characters to the byte slice
+ // and switch our operation to read and encode the remainder
+ // characters byte-by-byte.
+ if start < i {
+ dst = append(dst, s[start:i]...)
+ }
+ switch b {
+ case '"', '\\':
+ dst = append(dst, '\\', b)
+ case '\b':
+ dst = append(dst, '\\', 'b')
+ case '\f':
+ dst = append(dst, '\\', 'f')
+ case '\n':
+ dst = append(dst, '\\', 'n')
+ case '\r':
+ dst = append(dst, '\\', 'r')
+ case '\t':
+ dst = append(dst, '\\', 't')
+ default:
+ dst = append(dst, '\\', 'u', '0', '0', hexTable[b>>4], hexTable[b&0xF])
+ }
+ i++
+ start = i
+ }
+ if start < len(s) {
+ dst = append(dst, s[start:]...)
+ }
+ return dst
+}
+
+func decodeString(src *bufio.Reader, noQuotes bool) []byte {
+ pb := readByte(src)
+ major := pb & maskOutAdditionalType
+ minor := pb & maskOutMajorType
+ if major != majorTypeByteString {
+ panic(fmt.Errorf("Major type is: %d in decodeString", major))
+ }
+ result := []byte{}
+ if !noQuotes {
+ result = append(result, '"')
+ }
+ length := decodeIntAdditionalType(src, minor)
+ len := int(length)
+ pbs := readNBytes(src, len)
+ result = append(result, pbs...)
+ if noQuotes {
+ return result
+ }
+ return append(result, '"')
+}
+
+func decodeUTF8String(src *bufio.Reader) []byte {
+ pb := readByte(src)
+ major := pb & maskOutAdditionalType
+ minor := pb & maskOutMajorType
+ if major != majorTypeUtf8String {
+ panic(fmt.Errorf("Major type is: %d in decodeUTF8String", major))
+ }
+ result := []byte{'"'}
+ length := decodeIntAdditionalType(src, minor)
+ len := int(length)
+ pbs := readNBytes(src, len)
+
+ for i := 0; i < len; i++ {
+ // Check if the character needs encoding. Control characters, slashes,
+ // and the double quote need json encoding. Bytes above the ascii
+ // boundary needs utf8 encoding.
+ if pbs[i] < 0x20 || pbs[i] > 0x7e || pbs[i] == '\\' || pbs[i] == '"' {
+ // We encountered a character that needs to be encoded. Switch
+ // to complex version of the algorithm.
+ dst := []byte{'"'}
+ dst = decodeStringComplex(dst, string(pbs), uint(i))
+ return append(dst, '"')
+ }
+ }
+ // The string has no need for encoding and therefore is directly
+ // appended to the byte slice.
+ result = append(result, pbs...)
+ return append(result, '"')
+}
+
+func array2Json(src *bufio.Reader, dst io.Writer) {
+ dst.Write([]byte{'['})
+ pb := readByte(src)
+ major := pb & maskOutAdditionalType
+ minor := pb & maskOutMajorType
+ if major != majorTypeArray {
+ panic(fmt.Errorf("Major type is: %d in array2Json", major))
+ }
+ len := 0
+ unSpecifiedCount := false
+ if minor == additionalTypeInfiniteCount {
+ unSpecifiedCount = true
+ } else {
+ length := decodeIntAdditionalType(src, minor)
+ len = int(length)
+ }
+ for i := 0; unSpecifiedCount || i < len; i++ {
+ if unSpecifiedCount {
+ pb, e := src.Peek(1)
+ if e != nil {
+ panic(e)
+ }
+ if pb[0] == majorTypeSimpleAndFloat|additionalTypeBreak {
+ readByte(src)
+ break
+ }
+ }
+ cbor2JsonOneObject(src, dst)
+ if unSpecifiedCount {
+ pb, e := src.Peek(1)
+ if e != nil {
+ panic(e)
+ }
+ if pb[0] == majorTypeSimpleAndFloat|additionalTypeBreak {
+ readByte(src)
+ break
+ }
+ dst.Write([]byte{','})
+ } else if i+1 < len {
+ dst.Write([]byte{','})
+ }
+ }
+ dst.Write([]byte{']'})
+}
+
+func map2Json(src *bufio.Reader, dst io.Writer) {
+ pb := readByte(src)
+ major := pb & maskOutAdditionalType
+ minor := pb & maskOutMajorType
+ if major != majorTypeMap {
+ panic(fmt.Errorf("Major type is: %d in map2Json", major))
+ }
+ len := 0
+ unSpecifiedCount := false
+ if minor == additionalTypeInfiniteCount {
+ unSpecifiedCount = true
+ } else {
+ length := decodeIntAdditionalType(src, minor)
+ len = int(length)
+ }
+ dst.Write([]byte{'{'})
+ for i := 0; unSpecifiedCount || i < len; i++ {
+ if unSpecifiedCount {
+ pb, e := src.Peek(1)
+ if e != nil {
+ panic(e)
+ }
+ if pb[0] == majorTypeSimpleAndFloat|additionalTypeBreak {
+ readByte(src)
+ break
+ }
+ }
+ cbor2JsonOneObject(src, dst)
+ if i%2 == 0 {
+ // Even position values are keys.
+ dst.Write([]byte{':'})
+ } else {
+ if unSpecifiedCount {
+ pb, e := src.Peek(1)
+ if e != nil {
+ panic(e)
+ }
+ if pb[0] == majorTypeSimpleAndFloat|additionalTypeBreak {
+ readByte(src)
+ break
+ }
+ dst.Write([]byte{','})
+ } else if i+1 < len {
+ dst.Write([]byte{','})
+ }
+ }
+ }
+ dst.Write([]byte{'}'})
+}
+
+func decodeTagData(src *bufio.Reader) []byte {
+ pb := readByte(src)
+ major := pb & maskOutAdditionalType
+ minor := pb & maskOutMajorType
+ if major != majorTypeTags {
+ panic(fmt.Errorf("Major type is: %d in decodeTagData", major))
+ }
+ switch minor {
+ case additionalTypeTimestamp:
+ return decodeTimeStamp(src)
+
+ // Tag value is larger than 256 (so uint16).
+ case additionalTypeIntUint16:
+ val := decodeIntAdditionalType(src, minor)
+
+ switch uint16(val) {
+ case additionalTypeEmbeddedJSON:
+ pb := readByte(src)
+ dataMajor := pb & maskOutAdditionalType
+ if dataMajor != majorTypeByteString {
+ panic(fmt.Errorf("Unsupported embedded Type: %d in decodeEmbeddedJSON", dataMajor))
+ }
+ src.UnreadByte()
+ return decodeString(src, true)
+
+ case additionalTypeTagNetworkAddr:
+ octets := decodeString(src, true)
+ ss := []byte{'"'}
+ switch len(octets) {
+ case 6: // MAC address.
+ ha := net.HardwareAddr(octets)
+ ss = append(append(ss, ha.String()...), '"')
+ case 4: // IPv4 address.
+ fallthrough
+ case 16: // IPv6 address.
+ ip := net.IP(octets)
+ ss = append(append(ss, ip.String()...), '"')
+ default:
+ panic(fmt.Errorf("Unexpected Network Address length: %d (expected 4,6,16)", len(octets)))
+ }
+ return ss
+
+ case additionalTypeTagNetworkPrefix:
+ pb := readByte(src)
+ if pb != majorTypeMap|0x1 {
+ panic(fmt.Errorf("IP Prefix is NOT of MAP of 1 elements as expected"))
+ }
+ octets := decodeString(src, true)
+ val := decodeInteger(src)
+ ip := net.IP(octets)
+ var mask net.IPMask
+ pfxLen := int(val)
+ if len(octets) == 4 {
+ mask = net.CIDRMask(pfxLen, 32)
+ } else {
+ mask = net.CIDRMask(pfxLen, 128)
+ }
+ ipPfx := net.IPNet{IP: ip, Mask: mask}
+ ss := []byte{'"'}
+ ss = append(append(ss, ipPfx.String()...), '"')
+ return ss
+
+ case additionalTypeTagHexString:
+ octets := decodeString(src, true)
+ ss := []byte{'"'}
+ for _, v := range octets {
+ ss = append(ss, hexTable[v>>4], hexTable[v&0x0f])
+ }
+ return append(ss, '"')
+
+ default:
+ panic(fmt.Errorf("Unsupported Additional Tag Type: %d in decodeTagData", val))
+ }
+ }
+ panic(fmt.Errorf("Unsupported Additional Type: %d in decodeTagData", minor))
+}
+
+func decodeTimeStamp(src *bufio.Reader) []byte {
+ pb := readByte(src)
+ src.UnreadByte()
+ tsMajor := pb & maskOutAdditionalType
+ if tsMajor == majorTypeUnsignedInt || tsMajor == majorTypeNegativeInt {
+ n := decodeInteger(src)
+ t := time.Unix(n, 0)
+ if decodeTimeZone != nil {
+ t = t.In(decodeTimeZone)
+ } else {
+ t = t.In(time.UTC)
+ }
+ tsb := []byte{}
+ tsb = append(tsb, '"')
+ tsb = t.AppendFormat(tsb, IntegerTimeFieldFormat)
+ tsb = append(tsb, '"')
+ return tsb
+ } else if tsMajor == majorTypeSimpleAndFloat {
+ n, _ := decodeFloat(src)
+ secs := int64(n)
+ n -= float64(secs)
+ n *= float64(1e9)
+ t := time.Unix(secs, int64(n))
+ if decodeTimeZone != nil {
+ t = t.In(decodeTimeZone)
+ } else {
+ t = t.In(time.UTC)
+ }
+ tsb := []byte{}
+ tsb = append(tsb, '"')
+ tsb = t.AppendFormat(tsb, NanoTimeFieldFormat)
+ tsb = append(tsb, '"')
+ return tsb
+ }
+ panic(fmt.Errorf("TS format is neigther int nor float: %d", tsMajor))
+}
+
+func decodeSimpleFloat(src *bufio.Reader) []byte {
+ pb := readByte(src)
+ major := pb & maskOutAdditionalType
+ minor := pb & maskOutMajorType
+ if major != majorTypeSimpleAndFloat {
+ panic(fmt.Errorf("Major type is: %d in decodeSimpleFloat", major))
+ }
+ switch minor {
+ case additionalTypeBoolTrue:
+ return []byte("true")
+ case additionalTypeBoolFalse:
+ return []byte("false")
+ case additionalTypeNull:
+ return []byte("null")
+ case additionalTypeFloat16:
+ fallthrough
+ case additionalTypeFloat32:
+ fallthrough
+ case additionalTypeFloat64:
+ src.UnreadByte()
+ v, bc := decodeFloat(src)
+ ba := []byte{}
+ switch {
+ case math.IsNaN(v):
+ return []byte("\"NaN\"")
+ case math.IsInf(v, 1):
+ return []byte("\"+Inf\"")
+ case math.IsInf(v, -1):
+ return []byte("\"-Inf\"")
+ }
+ if bc == isFloat32 {
+ ba = strconv.AppendFloat(ba, v, 'f', -1, 32)
+ } else if bc == isFloat64 {
+ ba = strconv.AppendFloat(ba, v, 'f', -1, 64)
+ } else {
+ panic(fmt.Errorf("Invalid Float precision from decodeFloat: %d", bc))
+ }
+ return ba
+ default:
+ panic(fmt.Errorf("Invalid Additional Type: %d in decodeSimpleFloat", minor))
+ }
+}
+
+func cbor2JsonOneObject(src *bufio.Reader, dst io.Writer) {
+ pb, e := src.Peek(1)
+ if e != nil {
+ panic(e)
+ }
+ major := (pb[0] & maskOutAdditionalType)
+
+ switch major {
+ case majorTypeUnsignedInt:
+ fallthrough
+ case majorTypeNegativeInt:
+ n := decodeInteger(src)
+ dst.Write([]byte(strconv.Itoa(int(n))))
+
+ case majorTypeByteString:
+ s := decodeString(src, false)
+ dst.Write(s)
+
+ case majorTypeUtf8String:
+ s := decodeUTF8String(src)
+ dst.Write(s)
+
+ case majorTypeArray:
+ array2Json(src, dst)
+
+ case majorTypeMap:
+ map2Json(src, dst)
+
+ case majorTypeTags:
+ s := decodeTagData(src)
+ dst.Write(s)
+
+ case majorTypeSimpleAndFloat:
+ s := decodeSimpleFloat(src)
+ dst.Write(s)
+ }
+}
+
+func moreBytesToRead(src *bufio.Reader) bool {
+ _, e := src.ReadByte()
+ if e == nil {
+ src.UnreadByte()
+ return true
+ }
+ return false
+}
+
+// Cbor2JsonManyObjects decodes all the CBOR Objects read from src
+// reader. It keeps on decoding until reader returns EOF (error when reading).
+// Decoded string is written to the dst. At the end of every CBOR Object
+// newline is written to the output stream.
+//
+// Returns error (if any) that was encountered during decode.
+// The child functions will generate a panic when error is encountered and
+// this function will recover non-runtime Errors and return the reason as error.
+func Cbor2JsonManyObjects(src io.Reader, dst io.Writer) (err error) {
+ defer func() {
+ if r := recover(); r != nil {
+ if _, ok := r.(runtime.Error); ok {
+ panic(r)
+ }
+ err = r.(error)
+ }
+ }()
+ bufRdr := bufio.NewReader(src)
+ for moreBytesToRead(bufRdr) {
+ cbor2JsonOneObject(bufRdr, dst)
+ dst.Write([]byte("\n"))
+ }
+ return nil
+}
+
+// Detect if the bytes to be printed is Binary or not.
+func binaryFmt(p []byte) bool {
+ if len(p) > 0 && p[0] > 0x7F {
+ return true
+ }
+ return false
+}
+
+func getReader(str string) *bufio.Reader {
+ return bufio.NewReader(strings.NewReader(str))
+}
+
+// DecodeIfBinaryToString converts a binary formatted log msg to a
+// JSON formatted String Log message - suitable for printing to Console/Syslog.
+func DecodeIfBinaryToString(in []byte) string {
+ if binaryFmt(in) {
+ var b bytes.Buffer
+ Cbor2JsonManyObjects(strings.NewReader(string(in)), &b)
+ return b.String()
+ }
+ return string(in)
+}
+
+// DecodeObjectToStr checks if the input is a binary format, if so,
+// it will decode a single Object and return the decoded string.
+func DecodeObjectToStr(in []byte) string {
+ if binaryFmt(in) {
+ var b bytes.Buffer
+ cbor2JsonOneObject(getReader(string(in)), &b)
+ return b.String()
+ }
+ return string(in)
+}
+
+// DecodeIfBinaryToBytes checks if the input is a binary format, if so,
+// it will decode all Objects and return the decoded string as byte array.
+func DecodeIfBinaryToBytes(in []byte) []byte {
+ if binaryFmt(in) {
+ var b bytes.Buffer
+ Cbor2JsonManyObjects(bytes.NewReader(in), &b)
+ return b.Bytes()
+ }
+ return in
+}
diff --git a/vendor/github.com/rs/zerolog/internal/cbor/string.go b/vendor/github.com/rs/zerolog/internal/cbor/string.go
new file mode 100644
index 00000000..a33890a5
--- /dev/null
+++ b/vendor/github.com/rs/zerolog/internal/cbor/string.go
@@ -0,0 +1,95 @@
+package cbor
+
+import "fmt"
+
+// AppendStrings encodes and adds an array of strings to the dst byte array.
+func (e Encoder) AppendStrings(dst []byte, vals []string) []byte {
+ major := majorTypeArray
+ l := len(vals)
+ if l <= additionalMax {
+ lb := byte(l)
+ dst = append(dst, major|lb)
+ } else {
+ dst = appendCborTypePrefix(dst, major, uint64(l))
+ }
+ for _, v := range vals {
+ dst = e.AppendString(dst, v)
+ }
+ return dst
+}
+
+// AppendString encodes and adds a string to the dst byte array.
+func (Encoder) AppendString(dst []byte, s string) []byte {
+ major := majorTypeUtf8String
+
+ l := len(s)
+ if l <= additionalMax {
+ lb := byte(l)
+ dst = append(dst, major|lb)
+ } else {
+ dst = appendCborTypePrefix(dst, majorTypeUtf8String, uint64(l))
+ }
+ return append(dst, s...)
+}
+
+// AppendStringers encodes and adds an array of Stringer values
+// to the dst byte array.
+func (e Encoder) AppendStringers(dst []byte, vals []fmt.Stringer) []byte {
+ if len(vals) == 0 {
+ return e.AppendArrayEnd(e.AppendArrayStart(dst))
+ }
+ dst = e.AppendArrayStart(dst)
+ dst = e.AppendStringer(dst, vals[0])
+ if len(vals) > 1 {
+ for _, val := range vals[1:] {
+ dst = e.AppendStringer(dst, val)
+ }
+ }
+ return e.AppendArrayEnd(dst)
+}
+
+// AppendStringer encodes and adds the Stringer value to the dst
+// byte array.
+func (e Encoder) AppendStringer(dst []byte, val fmt.Stringer) []byte {
+ if val == nil {
+ return e.AppendNil(dst)
+ }
+ return e.AppendString(dst, val.String())
+}
+
+// AppendBytes encodes and adds an array of bytes to the dst byte array.
+func (Encoder) AppendBytes(dst, s []byte) []byte {
+ major := majorTypeByteString
+
+ l := len(s)
+ if l <= additionalMax {
+ lb := byte(l)
+ dst = append(dst, major|lb)
+ } else {
+ dst = appendCborTypePrefix(dst, major, uint64(l))
+ }
+ return append(dst, s...)
+}
+
+// AppendEmbeddedJSON adds a tag and embeds input JSON as such.
+func AppendEmbeddedJSON(dst, s []byte) []byte {
+ major := majorTypeTags
+ minor := additionalTypeEmbeddedJSON
+
+ // Append the TAG to indicate this is Embedded JSON.
+ dst = append(dst, major|additionalTypeIntUint16)
+ dst = append(dst, byte(minor>>8))
+ dst = append(dst, byte(minor&0xff))
+
+ // Append the JSON Object as Byte String.
+ major = majorTypeByteString
+
+ l := len(s)
+ if l <= additionalMax {
+ lb := byte(l)
+ dst = append(dst, major|lb)
+ } else {
+ dst = appendCborTypePrefix(dst, major, uint64(l))
+ }
+ return append(dst, s...)
+}
diff --git a/vendor/github.com/rs/zerolog/internal/cbor/time.go b/vendor/github.com/rs/zerolog/internal/cbor/time.go
new file mode 100644
index 00000000..d81fb125
--- /dev/null
+++ b/vendor/github.com/rs/zerolog/internal/cbor/time.go
@@ -0,0 +1,93 @@
+package cbor
+
+import (
+ "time"
+)
+
+func appendIntegerTimestamp(dst []byte, t time.Time) []byte {
+ major := majorTypeTags
+ minor := additionalTypeTimestamp
+ dst = append(dst, major|minor)
+ secs := t.Unix()
+ var val uint64
+ if secs < 0 {
+ major = majorTypeNegativeInt
+ val = uint64(-secs - 1)
+ } else {
+ major = majorTypeUnsignedInt
+ val = uint64(secs)
+ }
+ dst = appendCborTypePrefix(dst, major, val)
+ return dst
+}
+
+func (e Encoder) appendFloatTimestamp(dst []byte, t time.Time) []byte {
+ major := majorTypeTags
+ minor := additionalTypeTimestamp
+ dst = append(dst, major|minor)
+ secs := t.Unix()
+ nanos := t.Nanosecond()
+ var val float64
+ val = float64(secs)*1.0 + float64(nanos)*1e-9
+ return e.AppendFloat64(dst, val)
+}
+
+// AppendTime encodes and adds a timestamp to the dst byte array.
+func (e Encoder) AppendTime(dst []byte, t time.Time, unused string) []byte {
+ utc := t.UTC()
+ if utc.Nanosecond() == 0 {
+ return appendIntegerTimestamp(dst, utc)
+ }
+ return e.appendFloatTimestamp(dst, utc)
+}
+
+// AppendTimes encodes and adds an array of timestamps to the dst byte array.
+func (e Encoder) AppendTimes(dst []byte, vals []time.Time, unused string) []byte {
+ major := majorTypeArray
+ l := len(vals)
+ if l == 0 {
+ return e.AppendArrayEnd(e.AppendArrayStart(dst))
+ }
+ if l <= additionalMax {
+ lb := byte(l)
+ dst = append(dst, major|lb)
+ } else {
+ dst = appendCborTypePrefix(dst, major, uint64(l))
+ }
+
+ for _, t := range vals {
+ dst = e.AppendTime(dst, t, unused)
+ }
+ return dst
+}
+
+// AppendDuration encodes and adds a duration to the dst byte array.
+// useInt field indicates whether to store the duration as seconds (integer) or
+// as seconds+nanoseconds (float).
+func (e Encoder) AppendDuration(dst []byte, d time.Duration, unit time.Duration, useInt bool) []byte {
+ if useInt {
+ return e.AppendInt64(dst, int64(d/unit))
+ }
+ return e.AppendFloat64(dst, float64(d)/float64(unit))
+}
+
+// AppendDurations encodes and adds an array of durations to the dst byte array.
+// useInt field indicates whether to store the duration as seconds (integer) or
+// as seconds+nanoseconds (float).
+func (e Encoder) AppendDurations(dst []byte, vals []time.Duration, unit time.Duration, useInt bool) []byte {
+ major := majorTypeArray
+ l := len(vals)
+ if l == 0 {
+ return e.AppendArrayEnd(e.AppendArrayStart(dst))
+ }
+ if l <= additionalMax {
+ lb := byte(l)
+ dst = append(dst, major|lb)
+ } else {
+ dst = appendCborTypePrefix(dst, major, uint64(l))
+ }
+ for _, d := range vals {
+ dst = e.AppendDuration(dst, d, unit, useInt)
+ }
+ return dst
+}
diff --git a/vendor/github.com/rs/zerolog/internal/cbor/types.go b/vendor/github.com/rs/zerolog/internal/cbor/types.go
new file mode 100644
index 00000000..6f538328
--- /dev/null
+++ b/vendor/github.com/rs/zerolog/internal/cbor/types.go
@@ -0,0 +1,486 @@
+package cbor
+
+import (
+ "fmt"
+ "math"
+ "net"
+ "reflect"
+)
+
+// AppendNil inserts a 'Nil' object into the dst byte array.
+func (Encoder) AppendNil(dst []byte) []byte {
+ return append(dst, majorTypeSimpleAndFloat|additionalTypeNull)
+}
+
+// AppendBeginMarker inserts a map start into the dst byte array.
+func (Encoder) AppendBeginMarker(dst []byte) []byte {
+ return append(dst, majorTypeMap|additionalTypeInfiniteCount)
+}
+
+// AppendEndMarker inserts a map end into the dst byte array.
+func (Encoder) AppendEndMarker(dst []byte) []byte {
+ return append(dst, majorTypeSimpleAndFloat|additionalTypeBreak)
+}
+
+// AppendObjectData takes an object in form of a byte array and appends to dst.
+func (Encoder) AppendObjectData(dst []byte, o []byte) []byte {
+ // BeginMarker is present in the dst, which
+ // should not be copied when appending to existing data.
+ return append(dst, o[1:]...)
+}
+
+// AppendArrayStart adds markers to indicate the start of an array.
+func (Encoder) AppendArrayStart(dst []byte) []byte {
+ return append(dst, majorTypeArray|additionalTypeInfiniteCount)
+}
+
+// AppendArrayEnd adds markers to indicate the end of an array.
+func (Encoder) AppendArrayEnd(dst []byte) []byte {
+ return append(dst, majorTypeSimpleAndFloat|additionalTypeBreak)
+}
+
+// AppendArrayDelim adds markers to indicate end of a particular array element.
+func (Encoder) AppendArrayDelim(dst []byte) []byte {
+ //No delimiters needed in cbor
+ return dst
+}
+
+// AppendLineBreak is a noop that keep API compat with json encoder.
+func (Encoder) AppendLineBreak(dst []byte) []byte {
+ // No line breaks needed in binary format.
+ return dst
+}
+
+// AppendBool encodes and inserts a boolean value into the dst byte array.
+func (Encoder) AppendBool(dst []byte, val bool) []byte {
+ b := additionalTypeBoolFalse
+ if val {
+ b = additionalTypeBoolTrue
+ }
+ return append(dst, majorTypeSimpleAndFloat|b)
+}
+
+// AppendBools encodes and inserts an array of boolean values into the dst byte array.
+func (e Encoder) AppendBools(dst []byte, vals []bool) []byte {
+ major := majorTypeArray
+ l := len(vals)
+ if l == 0 {
+ return e.AppendArrayEnd(e.AppendArrayStart(dst))
+ }
+ if l <= additionalMax {
+ lb := byte(l)
+ dst = append(dst, major|lb)
+ } else {
+ dst = appendCborTypePrefix(dst, major, uint64(l))
+ }
+ for _, v := range vals {
+ dst = e.AppendBool(dst, v)
+ }
+ return dst
+}
+
+// AppendInt encodes and inserts an integer value into the dst byte array.
+func (Encoder) AppendInt(dst []byte, val int) []byte {
+ major := majorTypeUnsignedInt
+ contentVal := val
+ if val < 0 {
+ major = majorTypeNegativeInt
+ contentVal = -val - 1
+ }
+ if contentVal <= additionalMax {
+ lb := byte(contentVal)
+ dst = append(dst, major|lb)
+ } else {
+ dst = appendCborTypePrefix(dst, major, uint64(contentVal))
+ }
+ return dst
+}
+
+// AppendInts encodes and inserts an array of integer values into the dst byte array.
+func (e Encoder) AppendInts(dst []byte, vals []int) []byte {
+ major := majorTypeArray
+ l := len(vals)
+ if l == 0 {
+ return e.AppendArrayEnd(e.AppendArrayStart(dst))
+ }
+ if l <= additionalMax {
+ lb := byte(l)
+ dst = append(dst, major|lb)
+ } else {
+ dst = appendCborTypePrefix(dst, major, uint64(l))
+ }
+ for _, v := range vals {
+ dst = e.AppendInt(dst, v)
+ }
+ return dst
+}
+
+// AppendInt8 encodes and inserts an int8 value into the dst byte array.
+func (e Encoder) AppendInt8(dst []byte, val int8) []byte {
+ return e.AppendInt(dst, int(val))
+}
+
+// AppendInts8 encodes and inserts an array of integer values into the dst byte array.
+func (e Encoder) AppendInts8(dst []byte, vals []int8) []byte {
+ major := majorTypeArray
+ l := len(vals)
+ if l == 0 {
+ return e.AppendArrayEnd(e.AppendArrayStart(dst))
+ }
+ if l <= additionalMax {
+ lb := byte(l)
+ dst = append(dst, major|lb)
+ } else {
+ dst = appendCborTypePrefix(dst, major, uint64(l))
+ }
+ for _, v := range vals {
+ dst = e.AppendInt(dst, int(v))
+ }
+ return dst
+}
+
+// AppendInt16 encodes and inserts a int16 value into the dst byte array.
+func (e Encoder) AppendInt16(dst []byte, val int16) []byte {
+ return e.AppendInt(dst, int(val))
+}
+
+// AppendInts16 encodes and inserts an array of int16 values into the dst byte array.
+func (e Encoder) AppendInts16(dst []byte, vals []int16) []byte {
+ major := majorTypeArray
+ l := len(vals)
+ if l == 0 {
+ return e.AppendArrayEnd(e.AppendArrayStart(dst))
+ }
+ if l <= additionalMax {
+ lb := byte(l)
+ dst = append(dst, major|lb)
+ } else {
+ dst = appendCborTypePrefix(dst, major, uint64(l))
+ }
+ for _, v := range vals {
+ dst = e.AppendInt(dst, int(v))
+ }
+ return dst
+}
+
+// AppendInt32 encodes and inserts a int32 value into the dst byte array.
+func (e Encoder) AppendInt32(dst []byte, val int32) []byte {
+ return e.AppendInt(dst, int(val))
+}
+
+// AppendInts32 encodes and inserts an array of int32 values into the dst byte array.
+func (e Encoder) AppendInts32(dst []byte, vals []int32) []byte {
+ major := majorTypeArray
+ l := len(vals)
+ if l == 0 {
+ return e.AppendArrayEnd(e.AppendArrayStart(dst))
+ }
+ if l <= additionalMax {
+ lb := byte(l)
+ dst = append(dst, major|lb)
+ } else {
+ dst = appendCborTypePrefix(dst, major, uint64(l))
+ }
+ for _, v := range vals {
+ dst = e.AppendInt(dst, int(v))
+ }
+ return dst
+}
+
+// AppendInt64 encodes and inserts a int64 value into the dst byte array.
+func (Encoder) AppendInt64(dst []byte, val int64) []byte {
+ major := majorTypeUnsignedInt
+ contentVal := val
+ if val < 0 {
+ major = majorTypeNegativeInt
+ contentVal = -val - 1
+ }
+ if contentVal <= additionalMax {
+ lb := byte(contentVal)
+ dst = append(dst, major|lb)
+ } else {
+ dst = appendCborTypePrefix(dst, major, uint64(contentVal))
+ }
+ return dst
+}
+
+// AppendInts64 encodes and inserts an array of int64 values into the dst byte array.
+func (e Encoder) AppendInts64(dst []byte, vals []int64) []byte {
+ major := majorTypeArray
+ l := len(vals)
+ if l == 0 {
+ return e.AppendArrayEnd(e.AppendArrayStart(dst))
+ }
+ if l <= additionalMax {
+ lb := byte(l)
+ dst = append(dst, major|lb)
+ } else {
+ dst = appendCborTypePrefix(dst, major, uint64(l))
+ }
+ for _, v := range vals {
+ dst = e.AppendInt64(dst, v)
+ }
+ return dst
+}
+
+// AppendUint encodes and inserts an unsigned integer value into the dst byte array.
+func (e Encoder) AppendUint(dst []byte, val uint) []byte {
+ return e.AppendInt64(dst, int64(val))
+}
+
+// AppendUints encodes and inserts an array of unsigned integer values into the dst byte array.
+func (e Encoder) AppendUints(dst []byte, vals []uint) []byte {
+ major := majorTypeArray
+ l := len(vals)
+ if l == 0 {
+ return e.AppendArrayEnd(e.AppendArrayStart(dst))
+ }
+ if l <= additionalMax {
+ lb := byte(l)
+ dst = append(dst, major|lb)
+ } else {
+ dst = appendCborTypePrefix(dst, major, uint64(l))
+ }
+ for _, v := range vals {
+ dst = e.AppendUint(dst, v)
+ }
+ return dst
+}
+
+// AppendUint8 encodes and inserts a unsigned int8 value into the dst byte array.
+func (e Encoder) AppendUint8(dst []byte, val uint8) []byte {
+ return e.AppendUint(dst, uint(val))
+}
+
+// AppendUints8 encodes and inserts an array of uint8 values into the dst byte array.
+func (e Encoder) AppendUints8(dst []byte, vals []uint8) []byte {
+ major := majorTypeArray
+ l := len(vals)
+ if l == 0 {
+ return e.AppendArrayEnd(e.AppendArrayStart(dst))
+ }
+ if l <= additionalMax {
+ lb := byte(l)
+ dst = append(dst, major|lb)
+ } else {
+ dst = appendCborTypePrefix(dst, major, uint64(l))
+ }
+ for _, v := range vals {
+ dst = e.AppendUint8(dst, v)
+ }
+ return dst
+}
+
+// AppendUint16 encodes and inserts a uint16 value into the dst byte array.
+func (e Encoder) AppendUint16(dst []byte, val uint16) []byte {
+ return e.AppendUint(dst, uint(val))
+}
+
+// AppendUints16 encodes and inserts an array of uint16 values into the dst byte array.
+func (e Encoder) AppendUints16(dst []byte, vals []uint16) []byte {
+ major := majorTypeArray
+ l := len(vals)
+ if l == 0 {
+ return e.AppendArrayEnd(e.AppendArrayStart(dst))
+ }
+ if l <= additionalMax {
+ lb := byte(l)
+ dst = append(dst, major|lb)
+ } else {
+ dst = appendCborTypePrefix(dst, major, uint64(l))
+ }
+ for _, v := range vals {
+ dst = e.AppendUint16(dst, v)
+ }
+ return dst
+}
+
+// AppendUint32 encodes and inserts a uint32 value into the dst byte array.
+func (e Encoder) AppendUint32(dst []byte, val uint32) []byte {
+ return e.AppendUint(dst, uint(val))
+}
+
+// AppendUints32 encodes and inserts an array of uint32 values into the dst byte array.
+func (e Encoder) AppendUints32(dst []byte, vals []uint32) []byte {
+ major := majorTypeArray
+ l := len(vals)
+ if l == 0 {
+ return e.AppendArrayEnd(e.AppendArrayStart(dst))
+ }
+ if l <= additionalMax {
+ lb := byte(l)
+ dst = append(dst, major|lb)
+ } else {
+ dst = appendCborTypePrefix(dst, major, uint64(l))
+ }
+ for _, v := range vals {
+ dst = e.AppendUint32(dst, v)
+ }
+ return dst
+}
+
+// AppendUint64 encodes and inserts a uint64 value into the dst byte array.
+func (Encoder) AppendUint64(dst []byte, val uint64) []byte {
+ major := majorTypeUnsignedInt
+ contentVal := val
+ if contentVal <= additionalMax {
+ lb := byte(contentVal)
+ dst = append(dst, major|lb)
+ } else {
+ dst = appendCborTypePrefix(dst, major, contentVal)
+ }
+ return dst
+}
+
+// AppendUints64 encodes and inserts an array of uint64 values into the dst byte array.
+func (e Encoder) AppendUints64(dst []byte, vals []uint64) []byte {
+ major := majorTypeArray
+ l := len(vals)
+ if l == 0 {
+ return e.AppendArrayEnd(e.AppendArrayStart(dst))
+ }
+ if l <= additionalMax {
+ lb := byte(l)
+ dst = append(dst, major|lb)
+ } else {
+ dst = appendCborTypePrefix(dst, major, uint64(l))
+ }
+ for _, v := range vals {
+ dst = e.AppendUint64(dst, v)
+ }
+ return dst
+}
+
+// AppendFloat32 encodes and inserts a single precision float value into the dst byte array.
+func (Encoder) AppendFloat32(dst []byte, val float32) []byte {
+ switch {
+ case math.IsNaN(float64(val)):
+ return append(dst, "\xfa\x7f\xc0\x00\x00"...)
+ case math.IsInf(float64(val), 1):
+ return append(dst, "\xfa\x7f\x80\x00\x00"...)
+ case math.IsInf(float64(val), -1):
+ return append(dst, "\xfa\xff\x80\x00\x00"...)
+ }
+ major := majorTypeSimpleAndFloat
+ subType := additionalTypeFloat32
+ n := math.Float32bits(val)
+ var buf [4]byte
+ for i := uint(0); i < 4; i++ {
+ buf[i] = byte(n >> ((3 - i) * 8))
+ }
+ return append(append(dst, major|subType), buf[0], buf[1], buf[2], buf[3])
+}
+
+// AppendFloats32 encodes and inserts an array of single precision float value into the dst byte array.
+func (e Encoder) AppendFloats32(dst []byte, vals []float32) []byte {
+ major := majorTypeArray
+ l := len(vals)
+ if l == 0 {
+ return e.AppendArrayEnd(e.AppendArrayStart(dst))
+ }
+ if l <= additionalMax {
+ lb := byte(l)
+ dst = append(dst, major|lb)
+ } else {
+ dst = appendCborTypePrefix(dst, major, uint64(l))
+ }
+ for _, v := range vals {
+ dst = e.AppendFloat32(dst, v)
+ }
+ return dst
+}
+
+// AppendFloat64 encodes and inserts a double precision float value into the dst byte array.
+func (Encoder) AppendFloat64(dst []byte, val float64) []byte {
+ switch {
+ case math.IsNaN(val):
+ return append(dst, "\xfb\x7f\xf8\x00\x00\x00\x00\x00\x00"...)
+ case math.IsInf(val, 1):
+ return append(dst, "\xfb\x7f\xf0\x00\x00\x00\x00\x00\x00"...)
+ case math.IsInf(val, -1):
+ return append(dst, "\xfb\xff\xf0\x00\x00\x00\x00\x00\x00"...)
+ }
+ major := majorTypeSimpleAndFloat
+ subType := additionalTypeFloat64
+ n := math.Float64bits(val)
+ dst = append(dst, major|subType)
+ for i := uint(1); i <= 8; i++ {
+ b := byte(n >> ((8 - i) * 8))
+ dst = append(dst, b)
+ }
+ return dst
+}
+
+// AppendFloats64 encodes and inserts an array of double precision float values into the dst byte array.
+func (e Encoder) AppendFloats64(dst []byte, vals []float64) []byte {
+ major := majorTypeArray
+ l := len(vals)
+ if l == 0 {
+ return e.AppendArrayEnd(e.AppendArrayStart(dst))
+ }
+ if l <= additionalMax {
+ lb := byte(l)
+ dst = append(dst, major|lb)
+ } else {
+ dst = appendCborTypePrefix(dst, major, uint64(l))
+ }
+ for _, v := range vals {
+ dst = e.AppendFloat64(dst, v)
+ }
+ return dst
+}
+
+// AppendInterface takes an arbitrary object and converts it to JSON and embeds it dst.
+func (e Encoder) AppendInterface(dst []byte, i interface{}) []byte {
+ marshaled, err := JSONMarshalFunc(i)
+ if err != nil {
+ return e.AppendString(dst, fmt.Sprintf("marshaling error: %v", err))
+ }
+ return AppendEmbeddedJSON(dst, marshaled)
+}
+
+// AppendType appends the parameter type (as a string) to the input byte slice.
+func (e Encoder) AppendType(dst []byte, i interface{}) []byte {
+ if i == nil {
+ return e.AppendString(dst, "<nil>")
+ }
+ return e.AppendString(dst, reflect.TypeOf(i).String())
+}
+
+// AppendIPAddr encodes and inserts an IP Address (IPv4 or IPv6).
+func (e Encoder) AppendIPAddr(dst []byte, ip net.IP) []byte {
+ dst = append(dst, majorTypeTags|additionalTypeIntUint16)
+ dst = append(dst, byte(additionalTypeTagNetworkAddr>>8))
+ dst = append(dst, byte(additionalTypeTagNetworkAddr&0xff))
+ return e.AppendBytes(dst, ip)
+}
+
+// AppendIPPrefix encodes and inserts an IP Address Prefix (Address + Mask Length).
+func (e Encoder) AppendIPPrefix(dst []byte, pfx net.IPNet) []byte {
+ dst = append(dst, majorTypeTags|additionalTypeIntUint16)
+ dst = append(dst, byte(additionalTypeTagNetworkPrefix>>8))
+ dst = append(dst, byte(additionalTypeTagNetworkPrefix&0xff))
+
+ // Prefix is a tuple (aka MAP of 1 pair of elements) -
+ // first element is prefix, second is mask length.
+ dst = append(dst, majorTypeMap|0x1)
+ dst = e.AppendBytes(dst, pfx.IP)
+ maskLen, _ := pfx.Mask.Size()
+ return e.AppendUint8(dst, uint8(maskLen))
+}
+
+// AppendMACAddr encodes and inserts a Hardware (MAC) address.
+func (e Encoder) AppendMACAddr(dst []byte, ha net.HardwareAddr) []byte {
+ dst = append(dst, majorTypeTags|additionalTypeIntUint16)
+ dst = append(dst, byte(additionalTypeTagNetworkAddr>>8))
+ dst = append(dst, byte(additionalTypeTagNetworkAddr&0xff))
+ return e.AppendBytes(dst, ha)
+}
+
+// AppendHex adds a TAG and inserts a hex bytes as a string.
+func (e Encoder) AppendHex(dst []byte, val []byte) []byte {
+ dst = append(dst, majorTypeTags|additionalTypeIntUint16)
+ dst = append(dst, byte(additionalTypeTagHexString>>8))
+ dst = append(dst, byte(additionalTypeTagHexString&0xff))
+ return e.AppendBytes(dst, val)
+}