-
Notifications
You must be signed in to change notification settings - Fork 3
/
encoder.go
98 lines (88 loc) · 2.45 KB
/
encoder.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
package parser
import (
"encoding/json"
"strconv"
"strings"
"github.com/zishang520/engine.io-go-parser/types"
)
// A socket.io Encoder instance
type encoder struct {
}
func NewEncoder() Encoder {
return &encoder{}
}
// Encode a packet as a single string if non-binary, or as a
// buffer sequence, depending on packet type.
func (e *encoder) Encode(packet *Packet) []types.BufferInterface {
parser_log.Debug("encoding packet %v", packet)
if packet.Type == EVENT || packet.Type == ACK {
if HasBinary(packet.Data) {
if packet.Type == EVENT {
packet.Type = BINARY_EVENT
} else {
packet.Type = BINARY_ACK
}
return e.encodeAsBinary(packet)
}
}
return []types.BufferInterface{e.encodeAsString(packet)}
}
func _encodeData(data any) any {
if data == nil {
return nil
}
switch tdata := data.(type) {
// *strings.Reader special handling
case *strings.Reader:
rdata, _ := types.NewStringBufferReader(tdata)
return rdata
case []any:
newData := make([]any, 0, len(tdata))
for _, v := range tdata {
newData = append(newData, _encodeData(v))
}
return newData
case map[string]any:
newData := map[string]any{}
for k, v := range tdata {
newData[k] = _encodeData(v)
}
return newData
}
return data
}
// Encode packet as string.
func (e *encoder) encodeAsString(packet *Packet) types.BufferInterface {
// first is type
str := types.NewStringBuffer([]byte{byte(packet.Type)})
// attachments if we have them
if (packet.Type == BINARY_EVENT || packet.Type == BINARY_ACK) && packet.Attachments != nil {
str.WriteString(strconv.FormatUint(*packet.Attachments, 10))
str.WriteByte('-')
}
// if we have a namespace other than `/`
// we append it followed by a comma `,`
if len(packet.Nsp) > 0 && "/" != packet.Nsp {
str.WriteString(packet.Nsp)
str.WriteByte(',')
}
// immediately followed by the id
if nil != packet.Id {
str.WriteString(strconv.FormatUint(*packet.Id, 10))
}
// json data
if nil != packet.Data {
if b, err := json.Marshal(_encodeData(packet.Data)); err == nil {
str.Write(b)
}
}
parser_log.Debug("encoded %v as %v", packet, str)
return str
}
// Encode packet as 'buffer sequence' by removing blobs, and
// deconstructing packet into object with placeholders and
// a list of buffers.
func (e *encoder) encodeAsBinary(obj *Packet) []types.BufferInterface {
packet, buffers := DeconstructPacket(obj)
return append([]types.BufferInterface{e.encodeAsString(packet)}, buffers...) // write all the buffers
}