-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathdecode.go
115 lines (105 loc) · 1.83 KB
/
decode.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
package eddnc
import (
"bytes"
"compress/zlib"
"io"
)
func Decode(zmqmsg []byte, limit int64, into []byte) ([]byte, error) {
zrd, err := zlib.NewReader(bytes.NewReader(zmqmsg))
if err != nil {
return nil, err
}
defer zrd.Close()
txt := bytes.NewBuffer(into)
if limit > 0 {
_, err = io.Copy(txt, &io.LimitedReader{R: zrd, N: limit})
if err != nil {
return nil, err
}
} else {
_, err = io.Copy(txt, zrd)
if err != nil {
return nil, err
}
}
return txt.Bytes(), nil
}
func SchemaString(event []byte) string {
return string(Schema(event))
}
func Schema(raw []byte) []byte {
tmp := fieldStart(raw, schemaKey)
if tmp < 0 {
return nil
}
q1 := bytes.IndexByte(raw[tmp:], '"')
if q1 < 0 {
return nil
}
q1 += tmp + 1
q2 := bytes.IndexByte(raw[q1:], '"')
if q2 < 0 {
return nil
}
return raw[q1 : q1+q2]
}
func Message(event []byte) []byte {
s := MessageStart(event)
if s < 0 {
return nil
}
e := MessageEnd(event[s:])
if e < 0 {
return nil
}
return event[s : s+e]
}
func MessageStart(event []byte) int { return fieldStart(event, messageKey) }
var (
schemaKey = []byte(`"$schemaRef"`)
messageKey = []byte(`"message"`)
eventKey = []byte(`"event"`)
)
func fieldStart(raw, name []byte) int {
key := bytes.Index(raw, name)
if key < 0 {
return -1
}
sep := bytes.IndexByte(raw[key:], ':')
if sep < 0 {
return -1
}
return key + sep + 1
}
func MessageEnd(event []byte) int {
lvl := 0
l := len(event)
for i := 0; i < l; i++ {
c := event[i]
switch c {
case '{':
lvl++
case '}':
lvl--
if lvl == 0 {
return i + 1
}
case '"':
i = jsonSkipString(event, i+1)
}
}
return -1
}
// Check inlining with go build -gcflags -m decode.go
func jsonSkipString(b []byte, i int) int {
for i <= len(b) {
switch b[i] {
case '\\':
i++
case '"':
return i
}
i++
}
return i
}